/[escript]/trunk/escript/py_src/util.py
ViewVC logotype

Contents of /trunk/escript/py_src/util.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3368 - (show annotations)
Fri Nov 19 05:59:46 2010 UTC (8 years, 11 months ago) by jfenwick
File MIME type: text/x-python
File size: 235561 byte(s)
3d interpolateTable support.
New more generic interface for table interpolation.
tests and doco updated
1
2 ########################################################
3 #
4 # Copyright (c) 2003-2010 by University of Queensland
5 # Earth Systems Science Computational Center (ESSCC)
6 # http://www.uq.edu.au/esscc
7 #
8 # Primary Business: Queensland, Australia
9 # Licensed under the Open Software License version 3.0
10 # http://www.opensource.org/licenses/osl-3.0.php
11 #
12 ########################################################
13
14 __copyright__="""Copyright (c) 2003-2010 by University of Queensland
15 Earth Systems Science Computational Center (ESSCC)
16 http://www.uq.edu.au/esscc
17 Primary Business: Queensland, Australia"""
18 __license__="""Licensed under the Open Software License version 3.0
19 http://www.opensource.org/licenses/osl-3.0.php"""
20 __url__="https://launchpad.net/escript-finley"
21
22 """
23 Utility functions for escript
24
25 :var __author__: name of author
26 :var __copyright__: copyrights
27 :var __license__: licence agreement
28 :var __url__: url entry point on documentation
29 :var __version__: version
30 :var __date__: date of the version
31 :var EPSILON: smallest positive value with 1.<1.+EPSILON
32 :var DBLE_MAX: largest positive float
33 """
34
35 __author__="Lutz Gross, l.gross@uq.edu.au"
36
37
38 import math
39 import numpy
40 import escript
41 import os
42 from esys.escript import C_GeneralTensorProduct
43 from esys.escript import getVersion, getMPIRankWorld, getMPIWorldMax
44 from esys.escript import printParallelThreadCounts
45 from esys.escript import listEscriptParams
46 from esys.escript.escriptcpp import Data, _saveDataCSV, _condEval
47
48 #=========================================================
49 # some helpers:
50 #=========================================================
51 def getEpsilon():
52 return escript.getMachinePrecision()
53 EPSILON=getEpsilon()
54
55 def getMaxFloat():
56 return escript.getMaxFloat()
57 DBLE_MAX=getMaxFloat()
58
59 def getTagNames(domain):
60 """
61 Returns a list of tag names used by the domain.
62
63 :param domain: a domain object
64 :type domain: `escript.Domain`
65 :return: a list of tag names used by the domain
66 :rtype: ``list`` of ``str``
67 """
68 return [n.strip() for n in domain.showTagNames().split(",") ]
69
70 def insertTagNames(domain,**kwargs):
71 """
72 Inserts tag names into the domain.
73
74 :param domain: a domain object
75 :type domain: ``escript.Domain``
76 :keyword <tag_name>: tag key assigned to <tag_name>
77 :type <tag_name>: ``int``
78 """
79 for k in kwargs:
80 domain.setTagMap(k,kwargs[k])
81
82 def insertTaggedValues(target,**kwargs):
83 """
84 Inserts tagged values into the target using tag names.
85
86 :param target: data to be filled by tagged values
87 :type target: `escript.Data`
88 :keyword <tag_name>: value to be used for <tag_name>
89 :type <tag_name>: ``float`` or ``numpy.ndarray``
90 :return: ``target``
91 :rtype: `escript.Data`
92 """
93 for k in kwargs:
94 target.setTaggedValue(k,kwargs[k])
95 return target
96
97
98 def interpolateTable(tab, dat, start, step, undef=1.e50, check_boundaries=False):
99 try:
100 dim=len(start)
101 except TypeError:
102 start=(start,)
103 dim=1
104 try:
105 slen=len(step)
106 except TypeError:
107 step=(step,)
108 slen=1
109 if dim<1 or dim>3:
110 raise ValueError("Length of start list must be between 1 and 3.")
111 if dim!=slen:
112 raise ValueError("Length of start and step must be the same.")
113 dshape=dat.getShape()
114 if len(dshape)==0:
115 datdim=0
116 firstdim=dat
117 else:
118 datdim=dshape[0]
119 firstdim=dat[0]
120 #So now we know firstdim is a scalar
121 if (dim==1 and datdim>1) or (dim>1 and datdim!=dim):
122 print dim, datdim
123 raise ValueError("The dimension of dat must be equal to the length of start.")
124 if dim==3:
125 d1=dat[1]
126 d2=dat[2]
127 return firstdim._interpolateTable3d(tab, start[0], step[0], d1, start[1], step[1], d2, start[2], step[2], undef, check_boundaries)
128 if dim==2:
129 d1=dat[1]
130 return d1.interpolateTable(tab, start[0], step[0], firstdim, start[1], step[1], undef, check_boundaries)
131 else:
132 return firstdim.interpolateTable(tab, start[0], step[0], undef, check_boundaries)
133
134
135 def saveDataCSV(filename, append=False, sep=", ", csep="_", **data):
136 """
137 Writes `Data` objects to a csv file.
138 These objects must have compatible FunctionSpaces. ie it must be possible to
139 interpolate all data to one `FunctionSpace`.
140
141 :param filename: file to save data to.
142 :type filename: ``string``
143 :param append: If ``True``, then open file at end rather than beginning
144 :type append: ``bool``
145 :param sep: separator between fields
146 :type sep: ``string``
147 :param csep: separator for components of rank2 and above eg ('_' -> c0_1)
148
149 The keyword args are Data objects to save.
150 If a scalar `Data` object is passed with the name ``mask``, then only
151 samples which correspond to positive values in ``mask`` will be output.
152 Example::
153
154 s=Scalar(..)
155 v=Vector(..)
156 t=Tensor(..)
157 f=float()
158 saveDataCSV("f.csv",a=s, b=v, c=t, d=f)
159
160 Will result in a file
161
162 a, b0, b1, c0_0, c0_1, .., c1_0 d
163 1.0, 1.5, 2.7, 3.1, 3.4, .., 0.89 0.0
164 0.9, 8.7, 1.9, 3.4, 7.8, .., 1.21 0.0
165
166 The first line is a header, the remaining lines give the values.
167
168 """
169 # find a function space:
170 fs = None
171 for n,d in data.items():
172 if isinstance(d, Data): fs=d.getFunctionSpace()
173 if fs == None:
174 raise ValueError, "saveDataCSV: there must be at least one Data object in the argument list."
175
176 new_data={}
177 for n,d in data.items():
178 if isinstance(d, Data):
179 new_data[n]=d
180 else:
181 try:
182 new_data[n]=Data(d,fs)
183 except:
184 raise ValueError, "saveDataCSV: unknown non-data argument type for %s"%(str(n))
185 _saveDataCSV(filename, new_data,sep, csep, append)
186
187 def saveVTK(filename,domain=None, metadata=None, metadata_schema=None, **data):
188 """
189 Deprecated. See esys.weipa.saveVTK().
190 """
191
192 import warnings
193 msg = "esys.escript.util.saveVTK is deprecated. Use the esys.weipa module."
194 warnings.warn(msg, DeprecationWarning, stacklevel=2)
195
196 from esys import weipa
197 weipa.saveVTK(filename, domain, metadata, metadata_schema, **data)
198
199 def saveDX(filename,domain=None,**data):
200 """
201 Writes `Data` objects into a file using the OpenDX file format.
202
203 Example::
204
205 tmp=Scalar(..)
206 v=Vector(..)
207 saveDX("solution.dx", temperature=tmp, velocity=v)
208
209 ``tmp`` and ``v`` are written into "solution.dx" where ``tmp`` is named
210 "temperature" and ``v`` is named "velocity".
211
212 :param filename: file name of the output file
213 :type filename: ``str``
214 :param domain: domain of the `Data` objects. If not specified, the domain
215 of the given `Data` objects is used.
216 :type domain: `escript.Domain`
217 :keyword <name>: writes the assigned value to the DX file using <name> as
218 identifier. The identifier can be used to select the data
219 set when data are imported into DX.
220 :type <name>: `Data` object
221 :note: The data objects have to be defined on the same domain. They may not
222 be in the same `FunctionSpace` but one cannot expect that all
223 `FunctionSpace` s can be mixed. Typically, data on the boundary and
224 data on the interior cannot be mixed.
225 """
226 new_data={}
227 for n,d in data.items():
228 if not d.isEmpty():
229 fs=d.getFunctionSpace()
230 domain2=fs.getDomain()
231 if fs == escript.Solution(domain2):
232 new_data[n]=interpolate(d,escript.ReducedContinuousFunction(domain2))
233 elif fs == escript.ReducedSolution(domain2):
234 new_data[n]=interpolate(d,escript.ReducedContinuousFunction(domain2))
235 elif fs == escript.ContinuousFunction(domain2):
236 new_data[n]=interpolate(d,escript.ReducedContinuousFunction(domain2))
237 else:
238 new_data[n]=d
239 if domain==None: domain=domain2
240 if domain==None:
241 raise ValueError,"saveDX: no domain detected."
242 domain.saveDX(filename,new_data)
243
244 def saveESD(datasetName, dataDir=".", domain=None, timeStep=0, deltaT=1, dynamicMesh=0, **data):
245 """
246 Saves `Data` objects to files and creates an I{escript dataset} (ESD) file
247 for convenient processing/visualisation.
248
249 Single timestep example::
250
251 tmp = Scalar(..)
252 v = Vector(..)
253 saveESD("solution", "data", temperature=tmp, velocity=v)
254
255 Time series example::
256
257 while t < t_end:
258 tmp = Scalar(..)
259 v = Vector(..)
260 # save every 10 timesteps
261 if t % 10 == 0:
262 saveESD("solution", "data", timeStep=t, deltaT=10, temperature=tmp, velocity=v)
263 t = t + 1
264
265 tmp, v and the domain are saved in native format in the "data"
266 directory and the file "solution.esd" is created that refers to tmp by
267 the name "temperature" and to v by the name "velocity".
268
269 :param datasetName: name of the dataset, used to name the ESD file
270 :type datasetName: ``str``
271 :param dataDir: optional directory where the data files should be saved
272 :type dataDir: ``str``
273 :param domain: domain of the `Data` object(s). If not specified, the
274 domain of the given `Data` objects is used.
275 :type domain: `escript.Domain`
276 :param timeStep: current timestep or sequence number - first one must be 0
277 :type timeStep: `int`
278 :param deltaT: timestep or sequence increment, see example above
279 :type deltaT: `int`
280 :param dynamicMesh: by default the mesh is assumed to be static and thus
281 only saved once at timestep 0 to save disk space.
282 Setting this to 1 changes the behaviour and the mesh
283 is saved at each timestep.
284 :type dynamicMesh: `int`
285 :keyword <name>: writes the assigned value to the file using <name> as
286 identifier
287 :type <name>: `Data` object
288 :note: The ESD concept is experimental and the file format likely to
289 change so use this function with caution.
290 :note: The data objects have to be defined on the same domain (but not
291 necessarily on the same `FunctionSpace`).
292 :note: When saving a time series the first timestep must be 0 and it is
293 assumed that data from all timesteps share the domain. The dataset
294 file is updated in each iteration.
295 """
296 new_data = {}
297 for n,d in data.items():
298 if not d.isEmpty():
299 fs = d.getFunctionSpace()
300 domain2 = fs.getDomain()
301 if fs == escript.Solution(domain2):
302 new_data[n]=interpolate(d,escript.ContinuousFunction(domain2))
303 elif fs == escript.ReducedSolution(domain2):
304 new_data[n]=interpolate(d,escript.ReducedContinuousFunction(domain2))
305 else:
306 new_data[n]=d
307 if domain==None: domain=domain2
308 if domain==None:
309 raise ValueError, "saveESD: no domain detected."
310
311 if domain.onMasterProcessor() and not os.path.isdir(dataDir):
312 os.mkdir(dataDir)
313
314 meshFile = datasetName+"_mesh"
315 fileNumber = timeStep / deltaT
316
317 if dynamicMesh == 0:
318 # later timesteps reuse mesh from t=0
319 if timeStep == 0:
320 domain.dump(os.path.join(dataDir, meshFile + ".nc"))
321 else:
322 meshFile += ".%04d"
323 domain.dump(os.path.join(dataDir, (meshFile + ".nc") % fileNumber))
324
325 outputString = ""
326
327 if domain.onMasterProcessor():
328 outputString += "#escript datafile V1.0\n"
329 # number of timesteps (currently only 1 is supported)
330 outputString += "T=%d\n" % (fileNumber+1)
331 # timestep increment
332 outputString += "DT=1\n"
333 # name of the mesh file
334 outputString += "M=%s\n" % meshFile
335 # number of blocks (MPI size)
336 outputString += "N=%d\n" % domain.getMPISize()
337
338 # now add the variables
339 for varName, d in new_data.items():
340 varFile = datasetName+"_"+varName+".%04d"
341 d.dump(os.path.join(dataDir, (varFile + ".nc") % fileNumber))
342 if domain.onMasterProcessor():
343 outputString += "V=%s:%s\n" % (varFile, varName)
344
345 if domain.onMasterProcessor():
346 esdfile = open(os.path.join(dataDir, datasetName+".esd"), "w")
347 esdfile.write(outputString)
348 esdfile.close()
349
350 def kronecker(d=3):
351 """
352 Returns the kronecker delta-symbol.
353
354 :param d: dimension or an object that has the ``getDim`` method defining the
355 dimension
356 :type d: ``int``, `escript.Domain` or `escript.FunctionSpace`
357 :return: the object u of rank 2 with *u[i,j]=1* for *i=j* and *u[i,j]=0*
358 otherwise
359 :rtype: ``numpy.ndarray`` or `escript.Data` of rank 2
360 """
361 return identityTensor(d)
362
363 def identity(shape=()):
364 """
365 Returns the ``shape`` x ``shape`` identity tensor.
366
367 :param shape: input shape for the identity tensor
368 :type shape: ``tuple`` of ``int``
369 :return: array whose shape is shape x shape where *u[i,k]=1* for *i=k* and
370 *u[i,k]=0* otherwise for len(shape)=1. If len(shape)=2:
371 *u[i,j,k,l]=1* for *i=k and j=l* and *u[i,j,k,l]=0* otherwise.
372 :rtype: ``numpy.ndarray`` of rank 1, rank 2 or rank 4
373 :raise ValueError: if len(shape)>2
374 """
375 if len(shape)>0:
376 out=numpy.zeros(shape+shape,numpy.float64)
377 if len(shape)==1:
378 for i0 in range(shape[0]):
379 out[i0,i0]=1.
380 elif len(shape)==2:
381 for i0 in range(shape[0]):
382 for i1 in range(shape[1]):
383 out[i0,i1,i0,i1]=1.
384 else:
385 raise ValueError,"identity: length of shape is restricted to 2."
386 else:
387 out=1.
388 return out
389
390 def zeros(shape=()):
391 """
392 Returns the ``shape`` zero tensor.
393
394 :param shape: input shape for the identity tensor
395 :type shape: ``tuple`` of ``int``
396 :return: array of shape filled with zeros
397 :rtype: ``numpy.ndarray``
398 """
399 if len(shape)>0:
400 out=numpy.zeros(shape,numpy.float64)
401 else:
402 out=0.
403 return out
404
405 def identityTensor(d=3):
406 """
407 Returns the ``d`` x ``d`` identity matrix.
408
409 :param d: dimension or an object that has the ``getDim`` method defining the
410 dimension
411 :type d: ``int``, `escript.Domain` or `escript.FunctionSpace`
412 :return: the object u of rank 2 with *u[i,j]=1* for *i=j* and *u[i,j]=0*
413 otherwise
414 :rtype: ``numpy.ndarray`` or `escript.Data` of rank 2
415 """
416 if isinstance(d,escript.FunctionSpace):
417 return escript.Data(identity((d.getDim(),)),d)
418 elif isinstance(d,escript.Domain):
419 return identity((d.getDim(),))
420 else:
421 return identity((d,))
422
423 def identityTensor4(d=3):
424 """
425 Returns the ``d`` x ``d`` x ``d`` x ``d`` identity tensor.
426
427 :param d: dimension or an object that has the ``getDim`` method defining the
428 dimension
429 :type d: ``int`` or any object with a ``getDim`` method
430 :return: the object u of rank 4 with *u[i,j,k,l]=1* for *i=k and j=l* and
431 *u[i,j,k,l]=0* otherwise
432 :rtype: ``numpy.ndarray`` or `escript.Data` of rank 4
433 """
434 if isinstance(d,escript.FunctionSpace):
435 return escript.Data(identity((d.getDim(),d.getDim())),d)
436 elif isinstance(d,escript.Domain):
437 return identity((d.getDim(),d.getDim()))
438 else:
439 return identity((d,d))
440
441 def unitVector(i=0,d=3):
442 """
443 Returns a unit vector u of dimension d whose non-zero element is at index i.
444
445 :param i: index for non-zero element
446 :type i: ``int``
447 :param d: dimension or an object that has the ``getDim`` method defining the
448 dimension
449 :type d: ``int``, `escript.Domain` or `escript.FunctionSpace`
450 :return: the object u of rank 1 with *u[j]=1* for *j=index* and *u[j]=0*
451 otherwise
452 :rtype: ``numpy.ndarray`` or `escript.Data` of rank 1
453 """
454 return kronecker(d)[i]
455
456 #=========================================================================
457 # global reduction operations (these functions have no symbolic version)
458 #=========================================================================
459 def Lsup(arg):
460 """
461 Returns the Lsup-norm of argument ``arg``. This is the maximum absolute value
462 over all data points. This function is equivalent to ``sup(abs(arg))``.
463
464 :param arg: argument
465 :type arg: ``float``, ``int``, `escript.Data`, ``numpy.ndarray``
466 :return: maximum value of the absolute value of ``arg`` over all components
467 and all data points
468 :rtype: ``float``
469 :raise TypeError: if type of ``arg`` cannot be processed
470 """
471 if isinstance(arg,numpy.ndarray):
472 return sup(abs(arg))
473 elif isinstance(arg,escript.Data):
474 return arg._Lsup()
475 elif isinstance(arg,float):
476 return abs(arg)
477 elif isinstance(arg,int):
478 return abs(float(arg))
479 else:
480 raise TypeError,"Lsup: Unknown argument type."
481
482 def sup(arg):
483 """
484 Returns the maximum value over all data points.
485
486 :param arg: argument
487 :type arg: ``float``, ``int``, `escript.Data`, ``numpy.ndarray``
488 :return: maximum value of ``arg`` over all components and all data points
489 :rtype: ``float``
490 :raise TypeError: if type of ``arg`` cannot be processed
491 """
492 if isinstance(arg,numpy.ndarray):
493 return arg.max()
494 elif isinstance(arg,escript.Data):
495 return arg._sup()
496 elif isinstance(arg,float):
497 return arg
498 elif isinstance(arg,int):
499 return float(arg)
500 else:
501 raise TypeError,"sup: Unknown argument type."
502
503 def inf(arg):
504 """
505 Returns the minimum value over all data points.
506
507 :param arg: argument
508 :type arg: ``float``, ``int``, `escript.Data`, ``numpy.ndarray``
509 :return: minimum value of ``arg`` over all components and all data points
510 :rtype: ``float``
511 :raise TypeError: if type of ``arg`` cannot be processed
512 """
513 if isinstance(arg,numpy.ndarray):
514 return arg.min()
515 elif isinstance(arg,escript.Data):
516 return arg._inf()
517 elif isinstance(arg,float):
518 return arg
519 elif isinstance(arg,int):
520 return float(arg)
521 else:
522 raise TypeError,"inf: Unknown argument type."
523
524
525 #=========================================================================
526 # some little helpers
527 #=========================================================================
528 def getRank(arg):
529 """
530 Identifies the rank of the argument.
531
532 :param arg: an object whose rank is to be returned
533 :type arg: ``numpy.ndarray``, `escript.Data`, ``float``, ``int``,
534 ``Symbol``
535 :return: the rank of the argument
536 :rtype: ``int``
537 :raise TypeError: if type of ``arg`` cannot be processed
538 """
539
540 if isinstance(arg,numpy.ndarray):
541 return arg.ndim
542 elif isinstance(arg,escript.Data):
543 return arg.getRank()
544 elif isinstance(arg,float):
545 return 0
546 elif isinstance(arg,int):
547 return 0
548 elif isinstance(arg,Symbol):
549 return arg.getRank()
550 else:
551 raise TypeError,"getRank: Unknown argument type."
552
553 def getShape(arg):
554 """
555 Identifies the shape of the argument.
556
557 :param arg: an object whose shape is to be returned
558 :type arg: ``numpy.ndarray``, `escript.Data`, ``float``, ``int``,
559 ``Symbol``
560 :return: the shape of the argument
561 :rtype: ``tuple`` of ``int``
562 :raise TypeError: if type of ``arg`` cannot be processed
563 """
564
565 if isinstance(arg,numpy.ndarray):
566 return arg.shape
567 elif isinstance(arg,list):
568 return numpy.array(arg).shape
569 elif isinstance(arg,escript.Data):
570 return arg.getShape()
571 elif isinstance(arg,float):
572 return ()
573 elif isinstance(arg,int):
574 return ()
575 elif isinstance(arg,Symbol):
576 return arg.getShape()
577 else:
578 raise TypeError,"getShape: Cannot identify shape"
579
580 def pokeDim(arg):
581 """
582 Identifies the spatial dimension of the argument.
583
584 :param arg: an object whose spatial dimension is to be returned
585 :type arg: any
586 :return: the spatial dimension of the argument, if available, or ``None``
587 :rtype: ``int`` or ``None``
588 """
589
590 if isinstance(arg,escript.Data):
591 return arg.getFunctionSpace().getDim()
592 elif isinstance(arg,Symbol):
593 return arg.getDim()
594 else:
595 return None
596
597 def commonShape(arg0, arg1):
598 """
599 Returns a shape to which ``arg0`` can be extended from the right and ``arg1``
600 can be extended from the left.
601
602 :param arg0: an object with a shape (see `getShape`)
603 :param arg1: an object with a shape (see `getShape`)
604 :return: the shape of ``arg0`` or ``arg1`` such that the left part equals the
605 shape of ``arg0`` and the right end equals the shape of ``arg1``
606 :rtype: ``tuple`` of ``int``
607 :raise ValueError: if no shape can be found
608 """
609 sh0=getShape(arg0)
610 sh1=getShape(arg1)
611 if len(sh0)<len(sh1):
612 if not sh0==sh1[:len(sh0)]:
613 raise ValueError,"argument 0 cannot be extended to the shape of argument 1"
614 return sh1
615 elif len(sh0)>len(sh1):
616 if not sh1==sh0[:len(sh1)]:
617 raise ValueError,"argument 1 cannot be extended to the shape of argument 0"
618 return sh0
619 else:
620 if not sh0==sh1:
621 raise ValueError,"argument 1 and argument 0 have not the same shape."
622 return sh0
623
624 def commonDim(*args):
625 """
626 Identifies, if possible, the spatial dimension across a set of objects
627 which may or may not have a spatial dimension.
628
629 :param args: given objects
630 :return: the spatial dimension of the objects with identifiable dimension
631 (see `pokeDim`). If none of the objects has a spatial dimension
632 ``None`` is returned.
633 :rtype: ``int`` or ``None``
634 :raise ValueError: if the objects with identifiable dimension don't have
635 the same spatial dimension.
636 """
637 out=None
638 for a in args:
639 d=pokeDim(a)
640 if not out==None:
641 if not (d==None or out==d):
642 raise ValueError,"dimension of arguments don't match"
643 else:
644 out=d
645 return out
646
647 def testForZero(arg):
648 """
649 Tests if the argument is identical to zero.
650
651 :param arg: the object to test for zero
652 :type arg: typically ``numpy.ndarray``, `escript.Data`, ``float``, ``int``
653 :return: True if the argument is identical to zero, False otherwise
654 :rtype: ``bool``
655 """
656 if isinstance(arg,numpy.ndarray):
657 return not Lsup(arg)>0.
658 elif isinstance(arg,escript.Data):
659 return False
660 elif isinstance(arg,float):
661 return not Lsup(arg)>0.
662 elif isinstance(arg,int):
663 return not Lsup(arg)>0.
664 elif isinstance(arg,Symbol):
665 return False
666 else:
667 return False
668
669 def matchType(arg0=0.,arg1=0.):
670 """
671 Converts ``arg0`` and ``arg1`` both to the same type ``numpy.ndarray`` or
672 `escript.Data` or, if one of ``arg0`` or ``arg1`` is of type `Symbol`, the
673 other one to be of type ``numpy.ndarray`` or `escript.Data`.
674
675 :param arg0: first argument
676 :type arg0: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, ``Symbol``
677 :param arg1: second argument
678 :type arg1: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, ``Symbol``
679 :return: a tuple representing ``arg0`` and ``arg1`` with the same type or
680 with one of them being a `Symbol`
681 :rtype: ``tuple`` of two ``numpy.ndarray``, two `escript.Data`,
682 a ``Symbol`` and one of the types ``numpy.ndarray`` or
683 `escript.Data`
684 :raise TypeError: if type of ``arg0`` or ``arg1`` cannot be processed
685 """
686 if isinstance(arg0,numpy.ndarray):
687 if isinstance(arg1,numpy.ndarray):
688 pass
689 elif isinstance(arg1,escript.Data):
690 arg0=escript.Data(arg0,arg1.getFunctionSpace())
691 elif isinstance(arg1,float):
692 arg1=numpy.array(arg1,dtype=numpy.float64)
693 elif isinstance(arg1,int):
694 arg1=numpy.array(float(arg1),dtype=numpy.float64)
695 elif isinstance(arg1,Symbol):
696 pass
697 else:
698 raise TypeError,"function: Unknown type of second argument."
699 elif isinstance(arg0,escript.Data):
700 if isinstance(arg1,numpy.ndarray):
701 arg1=escript.Data(arg1,arg0.getFunctionSpace())
702 elif isinstance(arg1,escript.Data):
703 pass
704 elif isinstance(arg1,float):
705 arg1=escript.Data(arg1,(),arg0.getFunctionSpace())
706 elif isinstance(arg1,int):
707 arg1=escript.Data(float(arg1),(),arg0.getFunctionSpace())
708 elif isinstance(arg1,Symbol):
709 pass
710 else:
711 raise TypeError,"function: Unknown type of second argument."
712 elif isinstance(arg0,Symbol):
713 if isinstance(arg1,numpy.ndarray):
714 pass
715 elif isinstance(arg1,escript.Data):
716 pass
717 elif isinstance(arg1,float):
718 arg1=numpy.array(arg1,dtype=numpy.float64)
719 elif isinstance(arg1,int):
720 arg1=numpy.array(float(arg1),dtype=numpy.float64)
721 elif isinstance(arg1,Symbol):
722 pass
723 else:
724 raise TypeError,"function: Unknown type of second argument."
725 elif isinstance(arg0,float):
726 if isinstance(arg1,numpy.ndarray):
727 arg0=numpy.array(arg0,dtype=numpy.float64)
728 elif isinstance(arg1,escript.Data):
729 arg0=escript.Data(arg0,arg1.getFunctionSpace())
730 elif isinstance(arg1,float):
731 arg0=numpy.array(arg0,dtype=numpy.float64)
732 arg1=numpy.array(arg1,dtype=numpy.float64)
733 elif isinstance(arg1,int):
734 arg0=numpy.array(arg0,dtype=numpy.float64)
735 arg1=numpy.array(float(arg1),dtype=numpy.float64)
736 elif isinstance(arg1,Symbol):
737 arg0=numpy.array(arg0,dtype=numpy.float64)
738 else:
739 raise TypeError,"function: Unknown type of second argument."
740 elif isinstance(arg0,int):
741 if isinstance(arg1,numpy.ndarray):
742 arg0=numpy.array(float(arg0),dtype=numpy.float64)
743 elif isinstance(arg1,escript.Data):
744 arg0=escript.Data(float(arg0),arg1.getFunctionSpace())
745 elif isinstance(arg1,float):
746 arg0=numpy.array(float(arg0),dtype=numpy.float64)
747 arg1=numpy.array(arg1,dtype=numpy.float64)
748 elif isinstance(arg1,int):
749 arg0=numpy.array(float(arg0),dtype=numpy.float64)
750 arg1=numpy.array(float(arg1),dtype=numpy.float64)
751 elif isinstance(arg1,Symbol):
752 arg0=numpy.array(float(arg0),dtype=numpy.float64)
753 else:
754 raise TypeError,"function: Unknown type of second argument."
755 else:
756 raise TypeError,"function: Unknown type of first argument."
757
758 return arg0,arg1
759
760 def matchShape(arg0,arg1):
761 """
762 Returns a representation of ``arg0`` and ``arg1`` which have the same shape.
763
764 :param arg0: first argument
765 :type arg0: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, `Symbol`
766 :param arg1: second argument
767 :type arg1: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, `Symbol`
768 :return: ``arg0`` and ``arg1`` where copies are returned when the shape has
769 to be changed
770 :rtype: ``tuple``
771 """
772 sh=commonShape(arg0,arg1)
773 sh0=getShape(arg0)
774 sh1=getShape(arg1)
775 if len(sh0)<len(sh):
776 return outer(arg0,numpy.ones(sh[len(sh0):],numpy.float64)),arg1
777 elif len(sh1)<len(sh):
778 return arg0,outer(arg1,numpy.ones(sh[len(sh1):],numpy.float64))
779 else:
780 return arg0,arg1
781
782 #=========================================================
783 # symbolic tool box starts here:
784 #=========================================================
785 class Symbol(object):
786 """
787 Symbol class objects provide the same functionality as ``numpy.ndarray``
788 and `escript.Data` objects but they do not have a value and therefore
789 cannot be plotted or visualized. The main purpose is the possibility to
790 calculate derivatives with respect to other Symbols used to define a Symbol.
791
792 """
793 def __init__(self,shape=(),args=[],dim=None):
794 """
795 Creates an instance of a symbol of a given shape. The symbol may depend
796 on a list of arguments ``args`` which may be symbols or any other object.
797
798 :param args: the arguments of the symbol
799 :type args: ``list``
800 :param shape: the shape of the symbol
801 :type shape: ``tuple`` of ``int``
802 :param dim: spatial dimension of the symbol. If dim=``None`` the spatial
803 dimension is undefined.
804 :type dim: ``None`` or ``int``
805
806 """
807 if len(shape)>4:
808 raise ValueError,"Symbol only supports tensors up to order 4"
809 self.__args=args
810 self.__shape=shape
811 self.__dim=dim
812
813 def getArgument(self,i=None):
814 """
815 Returns the i-th argument of the symbol.
816
817 :param i: index of the argument requested
818 :type i: ``int`` or ``None``
819 :raise IndexError: if the requested index does not exist
820 :return: the value of the i-th argument or if i is not specified the
821 list of all arguments
822 :rtype: a single object or a list of objects
823 """
824 if i==None:
825 return self.__args
826 else:
827 if i<0 or i>=len(self.__args):
828 raise IndexError,"there are only %s arguments"%len(self.__args)
829 return self.__args[i]
830
831 def getRank(self):
832 """
833 Returns the rank of the symbol.
834
835 :return: the rank of the symbol. This is length of the shape.
836 :rtype: ``int``
837 """
838 return len(self.getShape())
839
840 def getShape(self):
841 """
842 Returns the shape of the symbol.
843
844 :return: the shape of the symbol
845 :rtype: ``tuple`` of ``int``
846 """
847 return self.__shape
848
849 def getDim(self):
850 """
851 Returns the spatial dimension.
852
853 :return: the symbol's spatial dimension
854 :rtype: ``int`` if the dimension is defined, ``None`` otherwise
855 """
856 return self.__dim
857
858 def __str__(self):
859 """
860 Returns a string representation of the symbol.
861
862 :return: a string representation of the object
863 :rtype: ``str``
864 """
865 args=[]
866 for arg in self.getArgument():
867 args.append(str(arg))
868 try:
869 out=self.getMyCode(args,format="str")
870 except NotImplementedError:
871 out="<Symbol %s>"%id(self)
872 return out
873
874 def getSubstitutedArguments(self,argvals):
875 """
876 Substitutes symbols in the arguments of this object and returns the
877 result as a list.
878
879 :param argvals: `Symbol` and their substitutes. The `Symbol` u in the
880 expression defining this object is replaced by
881 argvals[u].
882 :type argvals: ``dict`` with keywords of type `Symbol`
883 :rtype: ``list`` of objects
884 :return: list of the object assigned to the arguments through
885 substitution or for the arguments which are not `Symbol` s the
886 value assigned to the argument at instantiation.
887 """
888 out=[]
889 for a in self.getArgument():
890 if isinstance(a,Symbol):
891 out.append(a.substitute(argvals))
892 else:
893 out.append(a)
894 return out
895
896 def getDifferentiatedArguments(self,arg):
897 """
898 Applies differentials to the arguments of this object and returns the
899 result as a list.
900
901 :param arg: the derivative is calculated with respect to ``arg``
902 :type arg: typically `escript.Symbol` but can also be ``float``,
903 `escript.Data`, ``numpy.ndarray`` depending on the
904 involved functions and data
905 :rtype: ``list`` of objects
906 :return: list of object obtained by calculating the derivatives of the
907 arguments with respect to ``arg``
908 """
909 out=[]
910 for a in self.getArgument():
911 if isinstance(a,Symbol):
912 out.append(a.substitute(argvals))
913 else:
914 s=getShape(s)+arg.getShape()
915 if len(s)>0:
916 out.append(numpy.zeros(s),numpy.float64)
917 else:
918 out.append(a)
919 return out
920
921 def isAppropriateValue(self,arg):
922 """
923 Checks if the given argument ``arg`` can be used as a substitution for
924 this object. The method checks the shape of ``arg`` and, if the spatial
925 dimension is defined, the spatial dimension of ``arg``.
926
927 :param arg: object to be checked
928 :type arg: ``numpy.ndarray``, `escript.Data`, ``float``, ``int``,
929 ``Symbol``
930 :return: True if ``arg`` is a suitable object to be used for substitution,
931 False otherwise
932 :rtype: ``bool``
933 """
934 if isinstance(arg,numpy.ndarray):
935 return arg.shape==self.getShape()
936 elif isinstance(arg,escript.Data):
937 if self.getDim()==None:
938 return arg.getShape()==self.getShape()
939 elif self.getDim()==arg.getFunctionSpace().getDim():
940 return arg.getShape()==self.getShape()
941 else:
942 return False
943 elif isinstance(arg,Symbol):
944 if self.getDim()==None:
945 return arg.getShape()==self.getShape()
946 elif self.getDim()==arg.getDim():
947 return arg.getShape()==self.getShape()
948 else:
949 return False
950 elif isinstance(arg,float):
951 return ()==self.getShape()
952 elif isinstance(arg,int):
953 return ()==self.getShape()
954 else:
955 return False
956
957 def getMyCode(self,argstrs,format="escript"):
958 """
959 Returns program code that can be used to evaluate the symbol.
960
961 :param argstrs: a string for each argument representing the argument
962 for the evaluation
963 :type argstrs: ``list`` of ``str``
964 :param format: specifies the format to be used. At the moment only
965 "escript", "str" and "text" are supported.
966 :type format: ``str``
967 :return: a piece of program code which can be used to evaluate the
968 expression assuming the values for the arguments are available
969 :rtype: ``str``
970 :raise NotImplementedError: if no implementation for the given format
971 is available
972 :note: This method has to be overwritten by subclasses.
973 """
974 raise NotImplementedError,"no code for %s representation available"%format
975
976 def substitute(self,argvals):
977 """
978 Assigns new values to symbols in the definition of the symbol.
979
980 The method replaces the `Symbol` u by argvals[u] in the expression
981 defining this object.
982
983 :param argvals: new values assigned to symbols
984 :type argvals: ``dict`` with keywords of type `Symbol`
985 :return: result of the substitution process. Operations are executed as
986 much as possible.
987 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
988 depending on the degree of substitution
989 :note: this method has to be overwritten by a particular `Symbol`
990 :raise NotImplementedError: if no implementation for the given format is
991 available
992 :raise TypeError: if a value for a `Symbol` cannot be substituted
993 """
994 if argvals.has_key(self):
995 arg=argvals[self]
996 if self.isAppropriateValue(arg):
997 return arg
998 else:
999 raise TypeError,"Symbol: new value is not appropriate."
1000 else:
1001 raise NotImplementedError,"no substitution in %s avialable"%str(self)
1002
1003 def diff(self,arg):
1004 """
1005 Returns the derivative of the symbol with respect to `Symbol` ``arg``.
1006
1007 :param arg: the derivative is calculated with respect to ``arg``
1008 :type arg: typically `escript.Symbol` but can also be ``float``,
1009 `escript.Data`, ``numpy.ndarray`` depending on the
1010 involved functions and data
1011 :return: derivative with respect to ``arg``
1012 :rtype: typically `escript.Symbol` but other types such as ``float``,
1013 `escript.Data`, ``numpy.ndarray`` are possible
1014 :note: this method is overwritten by a particular `Symbol`.
1015 """
1016 if arg==self:
1017 return identity(self.getShape())
1018 else:
1019 s=self.getShape()+arg.getShape()
1020 if len(s)>0:
1021 return numpy.zeros(s,numpy.float64)
1022 else:
1023 return 0.
1024
1025 def __neg__(self):
1026 """
1027 Returns -self.
1028
1029 :return: a `Symbol` representing the negative of the object
1030 :rtype: `DependendSymbol`
1031 """
1032 return self*(-1.)
1033
1034 def __pos__(self):
1035 """
1036 Returns +self.
1037
1038 :return: a `Symbol` representing the positive of the object
1039 :rtype: `DependendSymbol`
1040 """
1041 return self*(1.)
1042
1043 def __abs__(self):
1044 """
1045 Returns a `Symbol` representing the absolute value of the object.
1046 """
1047 return Abs_Symbol(self)
1048
1049 def __add__(self,other):
1050 """
1051 Adds another object to this object.
1052
1053 :param other: object to be added to this object
1054 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1055 ``numpy.ndarray``.
1056 :return: a `Symbol` representing the sum of this object and ``other``
1057 :rtype: `DependendSymbol`
1058 """
1059 return add(self,other)
1060
1061 def __radd__(self,other):
1062 """
1063 Adds this object to another object.
1064
1065 :param other: object to add this object to
1066 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1067 ``numpy.ndarray``
1068 :return: a `Symbol` representing the sum of ``other`` and this object
1069 :rtype: `DependendSymbol`
1070 """
1071 return add(other,self)
1072
1073 def __sub__(self,other):
1074 """
1075 Subtracts another object from this object.
1076
1077 :param other: object to be subtracted from this object
1078 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1079 ``numpy.ndarray``
1080 :return: a `Symbol` representing the difference of ``other`` and this
1081 object
1082 :rtype: `DependendSymbol`
1083 """
1084 return add(self,-other)
1085
1086 def __rsub__(self,other):
1087 """
1088 Subtracts this object from another object.
1089
1090 :param other: object this object is to be subtracted from
1091 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1092 ``numpy.ndarray``
1093 :return: a `Symbol` representing the difference of this object and
1094 ``other``.
1095 :rtype: `DependendSymbol`
1096 """
1097 return add(-self,other)
1098
1099 def __mul__(self,other):
1100 """
1101 Multiplies this object with another object.
1102
1103 :param other: object to be mutiplied by this object
1104 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1105 ``numpy.ndarray``
1106 :return: a `Symbol` representing the product of the object and ``other``
1107 :rtype: `DependendSymbol` or 0 if other is identical to zero.
1108 """
1109 return mult(self,other)
1110
1111 def __rmul__(self,other):
1112 """
1113 Multiplies another object by this object.
1114
1115 :param other: object this object is multiplied with
1116 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1117 ``numpy.ndarray``
1118 :return: a `Symbol` representing the product of ``other`` and the object
1119 :rtype: `DependendSymbol` or 0 if other is identical to zero
1120 """
1121 return mult(other,self)
1122
1123 def __div__(self,other):
1124 """
1125 Divides this object by another object.
1126
1127 :param other: object dividing this object
1128 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1129 ``numpy.ndarray``
1130 :return: a `Symbol` representing the quotient of this object and
1131 ``other``
1132 :rtype: `DependendSymbol`
1133 """
1134 return quotient(self,other)
1135
1136 def __rdiv__(self,other):
1137 """
1138 Divides another object by this object.
1139
1140 :param other: object to be divided by this object
1141 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1142 ``numpy.ndarray``
1143 :return: a `Symbol` representing the quotient of ``other`` and this
1144 object
1145 :rtype: `DependendSymbol` or 0 if ``other`` is identical to zero
1146 """
1147 return quotient(other,self)
1148
1149 def __pow__(self,other):
1150 """
1151 Raises this object to the power of ``other``.
1152
1153 :param other: exponent
1154 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1155 ``numpy.ndarray``
1156 :return: a `Symbol` representing the power of this object to ``other``
1157 :rtype: `DependendSymbol` or 1 if ``other`` is identical to zero
1158 """
1159 return power(self,other)
1160
1161 def __rpow__(self,other):
1162 """
1163 Raises an object to the power of this object.
1164
1165 :param other: basis
1166 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1167 ``numpy.ndarray``
1168 :return: a `Symbol` representing the power of ``other`` to this object
1169 :rtype: `DependendSymbol` or 0 if ``other`` is identical to zero
1170 """
1171 return power(other,self)
1172
1173 def __getitem__(self,index):
1174 """
1175 Returns the slice defined by ``index``.
1176
1177 :param index: the slice index
1178 :type index: ``slice`` or ``int`` or a ``tuple`` of them
1179 :return: a `Symbol` representing the slice defined by index
1180 :rtype: `DependendSymbol`
1181 """
1182 return GetSlice_Symbol(self,index)
1183
1184 class DependendSymbol(Symbol):
1185 """
1186 DependendSymbol extents `Symbol` by modifying the == operator to allow two
1187 instances to be equal. Two ``DependendSymbol`` s are equal if they have the
1188 same shape, the same arguments and one of them has an unspecified spatial
1189 dimension or the spatial dimension is identical.
1190
1191 Example::
1192
1193 u1=Symbol(shape=(3,4),dim=2,args=[4.])
1194 u2=Symbol(shape=(3,4),dim=2,args=[4.])
1195 print u1==u2
1196 False
1197
1198 but::
1199
1200 u1=DependendSymbol(shape=(3,4),dim=2,args=[4.])
1201 u2=DependendSymbol(shape=(3,4),dim=2,args=[4.])
1202 u3=DependendSymbol(shape=(2,),dim=2,args=[4.])
1203 print u1==u2, u1==u3
1204 True False
1205
1206 :note: DependendSymbol should be used as return value of functions with
1207 `Symbol` arguments. This will allow the optimizer to remove
1208 redundant function calls.
1209 """
1210 def __eq__(self,other):
1211 """
1212 Checks if ``other`` equals self.
1213
1214 :param other: any object
1215 :return: True if other has the same class as self and the shape, the
1216 spatial dimension and the arguments are equal, False otherwise
1217 :rtype: ``bool``
1218 """
1219 if isinstance(other,DependendSymbol):
1220 if self.__class__==other.__class__:
1221 if self.getShape()==other.getShape():
1222 if self.getArgument()==other.getArgument():
1223 if self.getDim()==None or other.getDim()==None or self.getDim()==other.getDim():
1224 return True
1225 return False
1226
1227 def __ne__(self,other):
1228 """
1229 Checks if ``other`` is not equal to self.
1230
1231 :param other: any object
1232 :return: False if other has the same class as self and the shape, the
1233 spatial dimension and the arguments are equal, True otherwise
1234 :rtype: ``bool``
1235 """
1236 return not self==other
1237 #=========================================================
1238 # Unary operations preserving the shape
1239 #========================================================
1240 class GetSlice_Symbol(DependendSymbol):
1241 """
1242 `Symbol` representing getting a slice for a `Symbol`.
1243 """
1244 def __init__(self,arg,index):
1245 """
1246 Initialization of the `Symbol` with argument ``arg``.
1247
1248 :param arg: argument
1249 :type arg: `Symbol`
1250 :param index: defines index
1251 :type index: ``slice`` or ``int`` or a ``tuple`` of them
1252 :raise IndexError: if length of index is larger than rank of arg or
1253 index start or stop is out of range
1254 :raise ValueError: if a step is given
1255 """
1256 if not isinstance(index,tuple): index=(index,)
1257 if len(index)>arg.getRank():
1258 raise IndexError,"GetSlice_Symbol: index out of range."
1259 sh=()
1260 index2=()
1261 for i in range(len(index)):
1262 ix=index[i]
1263 if isinstance(ix,int):
1264 if ix<0 or ix>=arg.getShape()[i]:
1265 raise IndexError,"GetSlice_Symbol: index out of range."
1266 index2=index2+(ix,)
1267 else:
1268 if not ix.step==None:
1269 raise ValueError,"GetSlice_Symbol: stepping is not supported."
1270 if ix.start==None:
1271 s=0
1272 else:
1273 s=ix.start
1274 if ix.stop==None:
1275 e=arg.getShape()[i]
1276 else:
1277 e=ix.stop
1278 if e>arg.getShape()[i]:
1279 raise IndexError,"GetSlice_Symbol: index out of range."
1280 index2=index2+(slice(s,e),)
1281 if e>s:
1282 sh=sh+(e-s,)
1283 elif s>e:
1284 raise IndexError,"GetSlice_Symbol: slice start must be less or equal slice end"
1285 for i in range(len(index),arg.getRank()):
1286 index2=index2+(slice(0,arg.getShape()[i]),)
1287 sh=sh+(arg.getShape()[i],)
1288 super(GetSlice_Symbol, self).__init__(args=[arg,index2],shape=sh,dim=arg.getDim())
1289
1290 def getMyCode(self,argstrs,format="escript"):
1291 """
1292 Returns program code that can be used to evaluate the symbol.
1293
1294 :param argstrs: a string for each argument representing the argument
1295 for the evaluation
1296 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1297 :param format: specifies the format to be used. At the moment only
1298 "escript", "str" and "text" are supported.
1299 :type format: ``str``
1300 :return: a piece of program code which can be used to evaluate the
1301 expression assuming the values for the arguments are available
1302 :rtype: ``str``
1303 :raise NotImplementedError: if no implementation for the given format
1304 is available
1305 """
1306 if format=="escript" or format=="str" or format=="text":
1307 return "%s.__getitem__(%s)"%(argstrs[0],argstrs[1])
1308 else:
1309 raise NotImplementedError,"GetItem_Symbol does not provide program code for format %s."%format
1310
1311 def substitute(self,argvals):
1312 """
1313 Assigns new values to symbols in the definition of the symbol.
1314 The method replaces the `Symbol` u by argvals[u] in the expression
1315 defining this object.
1316
1317 :param argvals: new values assigned to symbols
1318 :type argvals: ``dict`` with keywords of type `Symbol`
1319 :return: result of the substitution process. Operations are executed as
1320 much as possible.
1321 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1322 depending on the degree of substitution
1323 :raise TypeError: if a value for a `Symbol` cannot be substituted
1324 """
1325 if argvals.has_key(self):
1326 arg=argvals[self]
1327 if self.isAppropriateValue(arg):
1328 return arg
1329 else:
1330 raise TypeError,"%s: new value is not appropriate."%str(self)
1331 else:
1332 args=self.getSubstitutedArguments(argvals)
1333 arg=args[0]
1334 index=args[1]
1335 return arg.__getitem__(index)
1336
1337 def log10(arg):
1338 """
1339 Returns base-10 logarithm of argument ``arg``.
1340
1341 :param arg: argument
1342 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1343 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1344 on the type of ``arg``
1345 :raise TypeError: if the type of the argument is not expected
1346 """
1347 if isinstance(arg,numpy.ndarray):
1348 return numpy.log10(arg)
1349 elif isinstance(arg,escript.Data):
1350 return arg._log10()
1351 elif isinstance(arg,float):
1352 return math.log10(arg)
1353 elif isinstance(arg,int):
1354 return math.log10(float(arg))
1355 elif isinstance(arg,Symbol):
1356 return log(arg)/log(10.)
1357 else:
1358 raise TypeError,"log10: Unknown argument type."
1359
1360 def wherePositive(arg):
1361 """
1362 Returns mask of positive values of argument ``arg``.
1363
1364 :param arg: argument
1365 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1366 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1367 on the type of ``arg``
1368 :raise TypeError: if the type of the argument is not expected
1369 """
1370 if isinstance(arg,numpy.ndarray):
1371 out=numpy.greater(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1372 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1373 return out
1374 elif isinstance(arg,escript.Data):
1375 return arg._wherePositive()
1376 elif isinstance(arg,float):
1377 if arg>0:
1378 return 1.
1379 else:
1380 return 0.
1381 elif isinstance(arg,int):
1382 if arg>0:
1383 return 1.
1384 else:
1385 return 0.
1386 elif isinstance(arg,Symbol):
1387 return WherePositive_Symbol(arg)
1388 else:
1389 raise TypeError,"wherePositive: Unknown argument type."
1390
1391 class WherePositive_Symbol(DependendSymbol):
1392 """
1393 `Symbol` representing the result of the mask of positive values function.
1394 """
1395 def __init__(self,arg):
1396 """
1397 Initialization of wherePositive `Symbol` with argument ``arg``.
1398
1399 :param arg: argument of function
1400 :type arg: typically `Symbol`
1401 """
1402 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1403
1404 def getMyCode(self,argstrs,format="escript"):
1405 """
1406 Returns program code that can be used to evaluate the symbol.
1407
1408 :param argstrs: a string for each argument representing the argument
1409 for the evaluation
1410 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1411 :param format: specifies the format to be used. At the moment only
1412 "escript", "str" and "text" are supported.
1413 :type format: ``str``
1414 :return: a piece of program code which can be used to evaluate the
1415 expression assuming the values for the arguments are available
1416 :rtype: ``str``
1417 :raise NotImplementedError: if no implementation for the given format
1418 is available
1419 """
1420 if isinstance(argstrs,list):
1421 argstrs=argstrs[0]
1422 if format=="escript" or format=="str" or format=="text":
1423 return "wherePositive(%s)"%argstrs
1424 else:
1425 raise NotImplementedError,"WherePositive_Symbol does not provide program code for format %s."%format
1426
1427 def substitute(self,argvals):
1428 """
1429 Assigns new values to symbols in the definition of the symbol.
1430 The method replaces the `Symbol` u by argvals[u] in the expression
1431 defining this object.
1432
1433 :param argvals: new values assigned to symbols
1434 :type argvals: ``dict`` with keywords of type `Symbol`
1435 :return: result of the substitution process. Operations are executed as
1436 much as possible.
1437 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1438 depending on the degree of substitution
1439 :raise TypeError: if a value for a `Symbol` cannot be substituted
1440 """
1441 if argvals.has_key(self):
1442 arg=argvals[self]
1443 if self.isAppropriateValue(arg):
1444 return arg
1445 else:
1446 raise TypeError,"%s: new value is not appropriate."%str(self)
1447 else:
1448 arg=self.getSubstitutedArguments(argvals)[0]
1449 return wherePositive(arg)
1450
1451 def whereNegative(arg):
1452 """
1453 Returns mask of negative values of argument ``arg``.
1454
1455 :param arg: argument
1456 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1457 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1458 on the type of ``arg``
1459 :raise TypeError: if the type of the argument is not expected
1460 """
1461 if isinstance(arg,numpy.ndarray):
1462 out=numpy.less(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1463 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1464 return out
1465 elif isinstance(arg,escript.Data):
1466 return arg._whereNegative()
1467 elif isinstance(arg,float):
1468 if arg<0:
1469 return 1.
1470 else:
1471 return 0.
1472 elif isinstance(arg,int):
1473 if arg<0:
1474 return 1.
1475 else:
1476 return 0.
1477 elif isinstance(arg,Symbol):
1478 return WhereNegative_Symbol(arg)
1479 else:
1480 raise TypeError,"whereNegative: Unknown argument type."
1481
1482 class WhereNegative_Symbol(DependendSymbol):
1483 """
1484 `Symbol` representing the result of the mask of negative values function.
1485 """
1486 def __init__(self,arg):
1487 """
1488 Initialization of whereNegative `Symbol` with argument ``arg``.
1489
1490 :param arg: argument of function
1491 :type arg: typically `Symbol`
1492 """
1493 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1494
1495 def getMyCode(self,argstrs,format="escript"):
1496 """
1497 Returns program code that can be used to evaluate the symbol.
1498
1499 :param argstrs: a string for each argument representing the argument
1500 for the evaluation
1501 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1502 :param format: specifies the format to be used. At the moment only
1503 "escript", "str" and "text" are supported.
1504 :type format: ``str``
1505 :return: a piece of program code which can be used to evaluate the
1506 expression assuming the values for the arguments are available
1507 :rtype: ``str``
1508 :raise NotImplementedError: if no implementation for the given format
1509 is available
1510 """
1511 if isinstance(argstrs,list):
1512 argstrs=argstrs[0]
1513 if format=="escript" or format=="str" or format=="text":
1514 return "whereNegative(%s)"%argstrs
1515 else:
1516 raise NotImplementedError,"WhereNegative_Symbol does not provide program code for format %s."%format
1517
1518 def substitute(self,argvals):
1519 """
1520 Assigns new values to symbols in the definition of the symbol.
1521 The method replaces the `Symbol` u by argvals[u] in the expression
1522 defining this object.
1523
1524 :param argvals: new values assigned to symbols
1525 :type argvals: ``dict`` with keywords of type `Symbol`
1526 :return: result of the substitution process. Operations are executed as
1527 much as possible.
1528 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1529 depending on the degree of substitution
1530 :raise TypeError: if a value for a `Symbol` cannot be substituted
1531 """
1532 if argvals.has_key(self):
1533 arg=argvals[self]
1534 if self.isAppropriateValue(arg):
1535 return arg
1536 else:
1537 raise TypeError,"%s: new value is not appropriate."%str(self)
1538 else:
1539 arg=self.getSubstitutedArguments(argvals)[0]
1540 return whereNegative(arg)
1541
1542 def whereNonNegative(arg):
1543 """
1544 Returns mask of non-negative values of argument ``arg``.
1545
1546 :param arg: argument
1547 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1548 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1549 on the type of ``arg``
1550 :raise TypeError: if the type of the argument is not expected
1551 """
1552 if isinstance(arg,numpy.ndarray):
1553 out=numpy.greater_equal(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1554 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1555 return out
1556 elif isinstance(arg,escript.Data):
1557 return arg._whereNonNegative()
1558 elif isinstance(arg,float):
1559 if arg<0:
1560 return 0.
1561 else:
1562 return 1.
1563 elif isinstance(arg,int):
1564 if arg<0:
1565 return 0.
1566 else:
1567 return 1.
1568 elif isinstance(arg,Symbol):
1569 return 1.-whereNegative(arg)
1570 else:
1571 raise TypeError,"whereNonNegative: Unknown argument type."
1572
1573 def whereNonPositive(arg):
1574 """
1575 Returns mask of non-positive values of argument ``arg``.
1576
1577 :param arg: argument
1578 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1579 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1580 on the type of ``arg``
1581 :raise TypeError: if the type of the argument is not expected
1582 """
1583 if isinstance(arg,numpy.ndarray):
1584 out=numpy.less_equal(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1585 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1586 return out
1587 elif isinstance(arg,escript.Data):
1588 return arg._whereNonPositive()
1589 elif isinstance(arg,float):
1590 if arg>0:
1591 return 0.
1592 else:
1593 return 1.
1594 elif isinstance(arg,int):
1595 if arg>0:
1596 return 0.
1597 else:
1598 return 1.
1599 elif isinstance(arg,Symbol):
1600 return 1.-wherePositive(arg)
1601 else:
1602 raise TypeError,"whereNonPositive: Unknown argument type."
1603
1604 def whereZero(arg,tol=None,rtol=math.sqrt(EPSILON)):
1605 """
1606 Returns mask of zero entries of argument ``arg``.
1607
1608 :param arg: argument
1609 :type arg: ``float``, `escript.Data` , `Symbol` , ``numpy.ndarray``
1610 :param tol: absolute tolerance. Values with absolute value less than tol are accepted
1611 as zero. If ``tol`` is not present ``rtol``*```Lsup` (arg)`` is used.
1612 :type tol: ``float``
1613 :param rtol: relative tolerance used to define the absolute tolerance if ``tol`` is not present.
1614 :type rtol: non-negative ``float``
1615 :rtype: ``float``, `escript.Data` , `Symbol` , ``numpy.ndarray`` depending
1616 on the type of ``arg``
1617 :raise ValueError: if ``rtol`` is non-negative.
1618 :raise TypeError: if the type of the argument is not expected
1619 """
1620 if tol == None:
1621 if not isinstance(arg,Symbol):
1622 if rtol<=0: raise ValueError,"rtol must be non-negative."
1623 tol = Lsup(arg)*rtol
1624 else:
1625 tol=0.
1626 if isinstance(arg,numpy.ndarray):
1627 out=numpy.less_equal(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.
1628 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1629 return out
1630 elif isinstance(arg,escript.Data):
1631 return arg._whereZero(tol)
1632 elif isinstance(arg,float):
1633 if abs(arg)<=tol:
1634 return 1.
1635 else:
1636 return 0.
1637 elif isinstance(arg,int):
1638 if abs(float(arg))<=tol:
1639 return 1.
1640 else:
1641 return 0.
1642 elif isinstance(arg,Symbol):
1643 return WhereZero_Symbol(arg,tol)
1644 else:
1645 raise TypeError,"whereZero: Unknown argument type."
1646
1647 class WhereZero_Symbol(DependendSymbol):
1648 """
1649 `Symbol` representing the result of the mask of zero entries function.
1650 """
1651 def __init__(self,arg,tol=0.):
1652 """
1653 Initialization of whereZero `Symbol` with argument ``arg``.
1654
1655 :param arg: argument of function
1656 :type arg: typically `Symbol`
1657 """
1658 DependendSymbol.__init__(self,args=[arg,tol],shape=arg.getShape(),dim=arg.getDim())
1659
1660 def getMyCode(self,argstrs,format="escript"):
1661 """
1662 Returns program code that can be used to evaluate the symbol.
1663
1664 :param argstrs: a string for each argument representing the argument
1665 for the evaluation
1666 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1667 :param format: specifies the format to be used. At the moment only
1668 "escript", "str" and "text" are supported.
1669 :type format: ``str``
1670 :return: a piece of program code which can be used to evaluate the
1671 expression assuming the values for the arguments are available
1672 :rtype: ``str``
1673 :raise NotImplementedError: if no implementation for the given format
1674 is available
1675 """
1676 if format=="escript" or format=="str" or format=="text":
1677 return "whereZero(%s,tol=%s)"%(argstrs[0],argstrs[1])
1678 else:
1679 raise NotImplementedError,"WhereZero_Symbol does not provide program code for format %s."%format
1680
1681 def substitute(self,argvals):
1682 """
1683 Assigns new values to symbols in the definition of the symbol.
1684 The method replaces the `Symbol` u by argvals[u] in the expression
1685 defining this object.
1686
1687 :param argvals: new values assigned to symbols
1688 :type argvals: ``dict`` with keywords of type `Symbol`
1689 :return: result of the substitution process. Operations are executed as
1690 much as possible.
1691 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1692 depending on the degree of substitution
1693 :raise TypeError: if a value for a `Symbol` cannot be substituted
1694 """
1695 if argvals.has_key(self):
1696 arg=argvals[self]
1697 if self.isAppropriateValue(arg):
1698 return arg
1699 else:
1700 raise TypeError,"%s: new value is not appropriate."%str(self)
1701 else:
1702 arg=self.getSubstitutedArguments(argvals)
1703 return whereZero(arg[0],arg[1])
1704
1705 def whereNonZero(arg,tol=0.):
1706 """
1707 Returns mask of values different from zero of argument ``arg``.
1708
1709 :param arg: argument
1710 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1711 :param tol: absolute tolerance. Values with absolute value less than tol are accepted
1712 as zero. If ``tol`` is not present ``rtol``*```Lsup` (arg)`` is used.
1713 :type tol: ``float``
1714 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1715 on the type of ``arg``
1716 :raise ValueError: if ``rtol`` is non-negative.
1717 :raise TypeError: if the type of the argument is not expected
1718 """
1719 if tol == None:
1720 if not isinstance(arg,Symbol):
1721 if rtol<=0: raise ValueError,"rtol must be non-negative."
1722 tol = Lsup(arg)*rtol
1723 else:
1724 tol=0.
1725 if isinstance(arg,numpy.ndarray):
1726 out=numpy.greater(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.
1727 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1728 return out
1729 elif isinstance(arg,escript.Data):
1730 return arg._whereNonZero(tol)
1731 elif isinstance(arg,float):
1732 if abs(arg)>tol:
1733 return 1.
1734 else:
1735 return 0.
1736 elif isinstance(arg,int):
1737 if abs(float(arg))>tol:
1738 return 1.
1739 else:
1740 return 0.
1741 elif isinstance(arg,Symbol):
1742 return 1.-whereZero(arg,tol)
1743 else:
1744 raise TypeError,"whereNonZero: Unknown argument type."
1745
1746 def erf(arg):
1747 """
1748 Returns the error function *erf* of argument ``arg``.
1749
1750 :param arg: argument
1751 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1752 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1753 on the type of ``arg``
1754 :raise TypeError: if the type of the argument is not expected
1755 """
1756 if isinstance(arg,escript.Data):
1757 return arg._erf()
1758 else:
1759 raise TypeError,"erf: Unknown argument type."
1760
1761 def sin(arg):
1762 """
1763 Returns sine of argument ``arg``.
1764
1765 :param arg: argument
1766 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1767 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1768 on the type of ``arg``
1769 :raise TypeError: if the type of the argument is not expected
1770 """
1771 if isinstance(arg,numpy.ndarray):
1772 return numpy.sin(arg)
1773 elif isinstance(arg,escript.Data):
1774 return arg._sin()
1775 elif isinstance(arg,float):
1776 return math.sin(arg)
1777 elif isinstance(arg,int):
1778 return math.sin(arg)
1779 elif isinstance(arg,Symbol):
1780 return Sin_Symbol(arg)
1781 else:
1782 raise TypeError,"sin: Unknown argument type."
1783
1784 class Sin_Symbol(DependendSymbol):
1785 """
1786 `Symbol` representing the result of the sine function.
1787 """
1788 def __init__(self,arg):
1789 """
1790 Initialization of sin `Symbol` with argument ``arg``.
1791
1792 :param arg: argument of function
1793 :type arg: typically `Symbol`
1794 """
1795 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1796
1797 def getMyCode(self,argstrs,format="escript"):
1798 """
1799 Returns program code that can be used to evaluate the symbol.
1800
1801 :param argstrs: a string for each argument representing the argument
1802 for the evaluation
1803 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1804 :param format: specifies the format to be used. At the moment only
1805 "escript", "str" and "text" are supported.
1806 :type format: ``str``
1807 :return: a piece of program code which can be used to evaluate the
1808 expression assuming the values for the arguments are available
1809 :rtype: ``str``
1810 :raise NotImplementedError: if no implementation for the given format
1811 is available
1812 """
1813 if isinstance(argstrs,list):
1814 argstrs=argstrs[0]
1815 if format=="escript" or format=="str" or format=="text":
1816 return "sin(%s)"%argstrs
1817 else:
1818 raise NotImplementedError,"Sin_Symbol does not provide program code for format %s."%format
1819
1820 def substitute(self,argvals):
1821 """
1822 Assigns new values to symbols in the definition of the symbol.
1823 The method replaces the `Symbol` u by argvals[u] in the expression
1824 defining this object.
1825
1826 :param argvals: new values assigned to symbols
1827 :type argvals: ``dict`` with keywords of type `Symbol`
1828 :return: result of the substitution process. Operations are executed as
1829 much as possible.
1830 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1831 depending on the degree of substitution
1832 :raise TypeError: if a value for a `Symbol` cannot be substituted
1833 """
1834 if argvals.has_key(self):
1835 arg=argvals[self]
1836 if self.isAppropriateValue(arg):
1837 return arg
1838 else:
1839 raise TypeError,"%s: new value is not appropriate."%str(self)
1840 else:
1841 arg=self.getSubstitutedArguments(argvals)[0]
1842 return sin(arg)
1843
1844 def diff(self,arg):
1845 """
1846 Differential of this object.
1847
1848 :param arg: the derivative is calculated with respect to ``arg``
1849 :type arg: `escript.Symbol`
1850 :return: derivative with respect to ``arg``
1851 :rtype: typically `Symbol` but other types such as ``float``,
1852 `escript.Data`, ``numpy.ndarray`` are possible
1853 """
1854 if arg==self:
1855 return identity(self.getShape())
1856 else:
1857 myarg=self.getArgument()[0]
1858 val=matchShape(cos(myarg),self.getDifferentiatedArguments(arg)[0])
1859 return val[0]*val[1]
1860
1861 def cos(arg):
1862 """
1863 Returns cosine of argument ``arg``.
1864
1865 :param arg: argument
1866 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1867 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1868 on the type of ``arg``
1869 :raise TypeError: if the type of the argument is not expected
1870 """
1871 if isinstance(arg,numpy.ndarray):
1872 return numpy.cos(arg)
1873 elif isinstance(arg,escript.Data):
1874 return arg._cos()
1875 elif isinstance(arg,float):
1876 return math.cos(arg)
1877 elif isinstance(arg,int):
1878 return math.cos(arg)
1879 elif isinstance(arg,Symbol):
1880 return Cos_Symbol(arg)
1881 else:
1882 raise TypeError,"cos: Unknown argument type."
1883
1884 class Cos_Symbol(DependendSymbol):
1885 """
1886 `Symbol` representing the result of the cosine function.
1887 """
1888 def __init__(self,arg):
1889 """
1890 Initialization of cos `Symbol` with argument ``arg``.
1891
1892 :param arg: argument of function
1893 :type arg: typically `Symbol`
1894 """
1895 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1896
1897 def getMyCode(self,argstrs,format="escript"):
1898 """
1899 Returns program code that can be used to evaluate the symbol.
1900
1901 :param argstrs: a string for each argument representing the argument
1902 for the evaluation
1903 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1904 :param format: specifies the format to be used. At the moment only
1905 "escript", "str" and "text" are supported.
1906 :type format: ``str``
1907 :return: a piece of program code which can be used to evaluate the
1908 expression assuming the values for the arguments are available
1909 :rtype: ``str``
1910 :raise NotImplementedError: if no implementation for the given format
1911 is available
1912 """
1913 if isinstance(argstrs,list):
1914 argstrs=argstrs[0]
1915 if format=="escript" or format=="str" or format=="text":
1916 return "cos(%s)"%argstrs
1917 else:
1918 raise NotImplementedError,"Cos_Symbol does not provide program code for format %s."%format
1919
1920 def substitute(self,argvals):
1921 """
1922 Assigns new values to symbols in the definition of the symbol.
1923 The method replaces the `Symbol` u by argvals[u] in the expression
1924 defining this object.
1925
1926 :param argvals: new values assigned to symbols
1927 :type argvals: ``dict`` with keywords of type `Symbol`
1928 :return: result of the substitution process. Operations are executed as
1929 much as possible.
1930 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1931 depending on the degree of substitution
1932 :raise TypeError: if a value for a `Symbol` cannot be substituted
1933 """
1934 if argvals.has_key(self):
1935 arg=argvals[self]
1936 if self.isAppropriateValue(arg):
1937 return arg
1938 else:
1939 raise TypeError,"%s: new value is not appropriate."%str(self)
1940 else:
1941 arg=self.getSubstitutedArguments(argvals)[0]
1942 return cos(arg)
1943
1944 def diff(self,arg):
1945 """
1946 Differential of this object.
1947
1948 :param arg: the derivative is calculated with respect to ``arg``
1949 :type arg: `escript.Symbol`
1950 :return: derivative with respect to ``arg``
1951 :rtype: typically `Symbol` but other types such as ``float``,
1952 `escript.Data`, ``numpy.ndarray`` are possible
1953 """
1954 if arg==self:
1955 return identity(self.getShape())
1956 else:
1957 myarg=self.getArgument()[0]
1958 val=matchShape(-sin(myarg),self.getDifferentiatedArguments(arg)[0])
1959 return val[0]*val[1]
1960
1961 def tan(arg):
1962 """
1963 Returns tangent of argument ``arg``.
1964
1965 :param arg: argument
1966 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1967 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1968 on the type of ``arg``
1969 :raise TypeError: if the type of the argument is not expected
1970 """
1971 if isinstance(arg,numpy.ndarray):
1972 return numpy.tan(arg)
1973 elif isinstance(arg,escript.Data):
1974 return arg._tan()
1975 elif isinstance(arg,float):
1976 return math.tan(arg)
1977 elif isinstance(arg,int):
1978 return math.tan(arg)
1979 elif isinstance(arg,Symbol):
1980 return Tan_Symbol(arg)
1981 else:
1982 raise TypeError,"tan: Unknown argument type."
1983
1984 class Tan_Symbol(DependendSymbol):
1985 """
1986 `Symbol` representing the result of the tangent function.
1987 """
1988 def __init__(self,arg):
1989 """
1990 Initialization of tan `Symbol` with argument ``arg``.
1991
1992 :param arg: argument of function
1993 :type arg: typically `Symbol`
1994 """
1995 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1996
1997 def getMyCode(self,argstrs,format="escript"):
1998 """
1999 Returns program code that can be used to evaluate the symbol.
2000
2001 :param argstrs: a string for each argument representing the argument
2002 for the evaluation
2003 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2004 :param format: specifies the format to be used. At the moment only
2005 "escript", "str" and "text" are supported.
2006 :type format: ``str``
2007 :return: a piece of program code which can be used to evaluate the
2008 expression assuming the values for the arguments are available
2009 :rtype: ``str``
2010 :raise NotImplementedError: if no implementation for the given format
2011 is available
2012 """
2013 if isinstance(argstrs,list):
2014 argstrs=argstrs[0]
2015 if format=="escript" or format=="str" or format=="text":
2016 return "tan(%s)"%argstrs
2017 else:
2018 raise NotImplementedError,"Tan_Symbol does not provide program code for format %s."%format
2019
2020 def substitute(self,argvals):
2021 """
2022 Assigns new values to symbols in the definition of the symbol.
2023 The method replaces the `Symbol` u by argvals[u] in the expression
2024 defining this object.
2025
2026 :param argvals: new values assigned to symbols
2027 :type argvals: ``dict`` with keywords of type `Symbol`
2028 :return: result of the substitution process. Operations are executed as
2029 much as possible.
2030 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2031 depending on the degree of substitution
2032 :raise TypeError: if a value for a `Symbol` cannot be substituted
2033 """
2034 if argvals.has_key(self):
2035 arg=argvals[self]
2036 if self.isAppropriateValue(arg):
2037 return arg
2038 else:
2039 raise TypeError,"%s: new value is not appropriate."%str(self)
2040 else:
2041 arg=self.getSubstitutedArguments(argvals)[0]
2042 return tan(arg)
2043
2044 def diff(self,arg):
2045 """
2046 Differential of this object.
2047
2048 :param arg: the derivative is calculated with respect to ``arg``
2049 :type arg: `escript.Symbol`
2050 :return: derivative with respect to ``arg``
2051 :rtype: typically `Symbol` but other types such as ``float``,
2052 `escript.Data`, ``numpy.ndarray`` are possible
2053 """
2054 if arg==self:
2055 return identity(self.getShape())
2056 else:
2057 myarg=self.getArgument()[0]
2058 val=matchShape(1./cos(myarg)**2,self.getDifferentiatedArguments(arg)[0])
2059 return val[0]*val[1]
2060
2061 def asin(arg):
2062 """
2063 Returns the inverse sine of argument ``arg``.
2064
2065 :param arg: argument
2066 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2067 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2068 on the type of ``arg``
2069 :raise TypeError: if the type of the argument is not expected
2070 """
2071 if isinstance(arg,numpy.ndarray):
2072 return numpy.arcsin(arg)
2073 elif isinstance(arg,escript.Data):
2074 return arg._asin()
2075 elif isinstance(arg,float):
2076 return math.asin(arg)
2077 elif isinstance(arg,int):
2078 return math.asin(arg)
2079 elif isinstance(arg,Symbol):
2080 return Asin_Symbol(arg)
2081 else:
2082 raise TypeError,"asin: Unknown argument type."
2083
2084 class Asin_Symbol(DependendSymbol):
2085 """
2086 `Symbol` representing the result of the inverse sine function.
2087 """
2088 def __init__(self,arg):
2089 """
2090 Initialization of asin `Symbol` with argument ``arg``.
2091
2092 :param arg: argument of function
2093 :type arg: typically `Symbol`
2094 """
2095 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2096
2097 def getMyCode(self,argstrs,format="escript"):
2098 """
2099 Returns program code that can be used to evaluate the symbol.
2100
2101 :param argstrs: a string for each argument representing the argument
2102 for the evaluation
2103 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2104 :param format: specifies the format to be used. At the moment only
2105 "escript", "str" and "text" are supported.
2106 :type format: ``str``
2107 :return: a piece of program code which can be used to evaluate the
2108 expression assuming the values for the arguments are available
2109 :rtype: ``str``
2110 :raise NotImplementedError: if no implementation for the given format
2111 is available
2112 """
2113 if isinstance(argstrs,list):
2114 argstrs=argstrs[0]
2115 if format=="escript" or format=="str" or format=="text":
2116 return "asin(%s)"%argstrs
2117 else:
2118 raise NotImplementedError,"Asin_Symbol does not provide program code for format %s."%format
2119
2120 def substitute(self,argvals):
2121 """
2122 Assigns new values to symbols in the definition of the symbol.
2123 The method replaces the `Symbol` u by argvals[u] in the expression
2124 defining this object.
2125
2126 :param argvals: new values assigned to symbols
2127 :type argvals: ``dict`` with keywords of type `Symbol`
2128 :return: result of the substitution process. Operations are executed as
2129 much as possible.
2130 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2131 depending on the degree of substitution
2132 :raise TypeError: if a value for a `Symbol` cannot be substituted
2133 """
2134 if argvals.has_key(self):
2135 arg=argvals[self]
2136 if self.isAppropriateValue(arg):
2137 return arg
2138 else:
2139 raise TypeError,"%s: new value is not appropriate."%str(self)
2140 else:
2141 arg=self.getSubstitutedArguments(argvals)[0]
2142 return asin(arg)
2143
2144 def diff(self,arg):
2145 """
2146 Differential of this object.
2147
2148 :param arg: the derivative is calculated with respect to ``arg``
2149 :type arg: `escript.Symbol`
2150 :return: derivative with respect to ``arg``
2151 :rtype: typically `Symbol` but other types such as ``float``,
2152 `escript.Data`, ``numpy.ndarray`` are possible
2153 """
2154 if arg==self:
2155 return identity(self.getShape())
2156 else:
2157 myarg=self.getArgument()[0]
2158 val=matchShape(1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2159 return val[0]*val[1]
2160
2161 def acos(arg):
2162 """
2163 Returns the inverse cosine of argument ``arg``.
2164
2165 :param arg: argument
2166 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2167 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2168 on the type of ``arg``
2169 :raise TypeError: if the type of the argument is not expected
2170 """
2171 if isinstance(arg,numpy.ndarray):
2172 return numpy.arccos(arg)
2173 elif isinstance(arg,escript.Data):
2174 return arg._acos()
2175 elif isinstance(arg,float):
2176 return math.acos(arg)
2177 elif isinstance(arg,int):
2178 return math.acos(arg)
2179 elif isinstance(arg,Symbol):
2180 return Acos_Symbol(arg)
2181 else:
2182 raise TypeError,"acos: Unknown argument type."
2183
2184 class Acos_Symbol(DependendSymbol):
2185 """
2186 `Symbol` representing the result of the inverse cosine function.
2187 """
2188 def __init__(self,arg):
2189 """
2190 Initialization of acos `Symbol` with argument ``arg``.
2191
2192 :param arg: argument of function
2193 :type arg: typically `Symbol`
2194 """
2195 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2196
2197 def getMyCode(self,argstrs,format="escript"):
2198 """
2199 Returns program code that can be used to evaluate the symbol.
2200
2201 :param argstrs: a string for each argument representing the argument
2202 for the evaluation
2203 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2204 :param format: specifies the format to be used. At the moment only
2205 "escript", "str" and "text" are supported.
2206 :type format: ``str``
2207 :return: a piece of program code which can be used to evaluate the
2208 expression assuming the values for the arguments are available
2209 :rtype: ``str``
2210 :raise NotImplementedError: if no implementation for the given format
2211 is available
2212 """
2213 if isinstance(argstrs,list):
2214 argstrs=argstrs[0]
2215 if format=="escript" or format=="str" or format=="text":
2216 return "acos(%s)"%argstrs
2217 else:
2218 raise NotImplementedError,"Acos_Symbol does not provide program code for format %s."%format
2219
2220 def substitute(self,argvals):
2221 """
2222 Assigns new values to symbols in the definition of the symbol.
2223 The method replaces the `Symbol` u by argvals[u] in the expression
2224 defining this object.
2225
2226 :param argvals: new values assigned to symbols
2227 :type argvals: ``dict`` with keywords of type `Symbol`
2228 :return: result of the substitution process. Operations are executed as
2229 much as possible.
2230 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2231 depending on the degree of substitution
2232 :raise TypeError: if a value for a `Symbol` cannot be substituted
2233 """
2234 if argvals.has_key(self):
2235 arg=argvals[self]
2236 if self.isAppropriateValue(arg):
2237 return arg
2238 else:
2239 raise TypeError,"%s: new value is not appropriate."%str(self)
2240 else:
2241 arg=self.getSubstitutedArguments(argvals)[0]
2242 return acos(arg)
2243
2244 def diff(self,arg):
2245 """
2246 Differential of this object.
2247
2248 :param arg: the derivative is calculated with respect to ``arg``
2249 :type arg: `escript.Symbol`
2250 :return: derivative with respect to ``arg``
2251 :rtype: typically `Symbol` but other types such as ``float``,
2252 `escript.Data`, ``numpy.ndarray`` are possible
2253 """
2254 if arg==self:
2255 return identity(self.getShape())
2256 else:
2257 myarg=self.getArgument()[0]
2258 val=matchShape(-1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2259 return val[0]*val[1]
2260
2261 def atan(arg):
2262 """
2263 Returns inverse tangent of argument ``arg``.
2264
2265 :param arg: argument
2266 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2267 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2268 on the type of ``arg``
2269 :raise TypeError: if the type of the argument is not expected
2270 """
2271 if isinstance(arg,numpy.ndarray):
2272 return numpy.arctan(arg)
2273 elif isinstance(arg,escript.Data):
2274 return arg._atan()
2275 elif isinstance(arg,float):
2276 return math.atan(arg)
2277 elif isinstance(arg,int):
2278 return math.atan(arg)
2279 elif isinstance(arg,Symbol):
2280 return Atan_Symbol(arg)
2281 else:
2282 raise TypeError,"atan: Unknown argument type."
2283
2284 class Atan_Symbol(DependendSymbol):
2285 """
2286 `Symbol` representing the result of the inverse tangent function.
2287 """
2288 def __init__(self,arg):
2289 """
2290 Initialization of atan `Symbol` with argument ``arg``.
2291
2292 :param arg: argument of function
2293 :type arg: typically `Symbol`
2294 """
2295 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2296
2297 def getMyCode(self,argstrs,format="escript"):
2298 """
2299 Returns program code that can be used to evaluate the symbol.
2300
2301 :param argstrs: a string for each argument representing the argument
2302 for the evaluation
2303 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2304 :param format: specifies the format to be used. At the moment only
2305 "escript", "str" and "text" are supported.
2306 :type format: ``str``
2307 :return: a piece of program code which can be used to evaluate the
2308 expression assuming the values for the arguments are available
2309 :rtype: ``str``
2310 :raise NotImplementedError: if no implementation for the given format
2311 is available
2312 """
2313 if isinstance(argstrs,list):
2314 argstrs=argstrs[0]
2315 if format=="escript" or format=="str" or format=="text":
2316 return "atan(%s)"%argstrs
2317 else:
2318 raise NotImplementedError,"Atan_Symbol does not provide program code for format %s."%format
2319
2320 def substitute(self,argvals):
2321 """
2322 Assigns new values to symbols in the definition of the symbol.
2323 The method replaces the `Symbol` u by argvals[u] in the expression
2324 defining this object.
2325
2326 :param argvals: new values assigned to symbols
2327 :type argvals: ``dict`` with keywords of type `Symbol`
2328 :return: result of the substitution process. Operations are executed as
2329 much as possible.
2330 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2331 depending on the degree of substitution
2332 :raise TypeError: if a value for a `Symbol` cannot be substituted
2333 """
2334 if argvals.has_key(self):
2335 arg=argvals[self]
2336 if self.isAppropriateValue(arg):
2337 return arg
2338 else:
2339 raise TypeError,"%s: new value is not appropriate."%str(self)
2340 else:
2341 arg=self.getSubstitutedArguments(argvals)[0]
2342 return atan(arg)
2343
2344 def diff(self,arg):
2345 """
2346 Differential of this object.
2347
2348 :param arg: the derivative is calculated with respect to ``arg``
2349 :type arg: `escript.Symbol`
2350 :return: derivative with respect to ``arg``
2351 :rtype: typically `Symbol` but other types such as ``float``,
2352 `escript.Data`, ``numpy.ndarray`` are possible
2353 """
2354 if arg==self:
2355 return identity(self.getShape())
2356 else:
2357 myarg=self.getArgument()[0]
2358 val=matchShape(1./(1+myarg**2),self.getDifferentiatedArguments(arg)[0])
2359 return val[0]*val[1]
2360
2361 def sinh(arg):
2362 """
2363 Returns the hyperbolic sine of argument ``arg``.
2364
2365 :param arg: argument
2366 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2367 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2368 on the type of ``arg``
2369 :raise TypeError: if the type of the argument is not expected
2370 """
2371 if isinstance(arg,numpy.ndarray):
2372 return numpy.sinh(arg)
2373 elif isinstance(arg,escript.Data):
2374 return arg._sinh()
2375 elif isinstance(arg,float):
2376 return math.sinh(arg)
2377 elif isinstance(arg,int):
2378 return math.sinh(arg)
2379 elif isinstance(arg,Symbol):
2380 return Sinh_Symbol(arg)
2381 else:
2382 raise TypeError,"sinh: Unknown argument type."
2383
2384 class Sinh_Symbol(DependendSymbol):
2385 """
2386 `Symbol` representing the result of the hyperbolic sine function.
2387 """
2388 def __init__(self,arg):
2389 """
2390 Initialization of sinh `Symbol` with argument ``arg``.
2391
2392 :param arg: argument of function
2393 :type arg: typically `Symbol`
2394 """
2395 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2396
2397 def getMyCode(self,argstrs,format="escript"):
2398 """
2399 Returns program code that can be used to evaluate the symbol.
2400
2401 :param argstrs: a string for each argument representing the argument
2402 for the evaluation
2403 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2404 :param format: specifies the format to be used. At the moment only
2405 "escript", "str" and "text" are supported.
2406 :type format: ``str``
2407 :return: a piece of program code which can be used to evaluate the
2408 expression assuming the values for the arguments are available
2409 :rtype: ``str``
2410 :raise NotImplementedError: if no implementation for the given format
2411 is available
2412 """
2413 if isinstance(argstrs,list):
2414 argstrs=argstrs[0]
2415 if format=="escript" or format=="str" or format=="text":
2416 return "sinh(%s)"%argstrs
2417 else:
2418 raise NotImplementedError,"Sinh_Symbol does not provide program code for format %s."%format
2419
2420 def substitute(self,argvals):
2421 """
2422 Assigns new values to symbols in the definition of the symbol.
2423 The method replaces the `Symbol` u by argvals[u] in the expression
2424 defining this object.
2425
2426 :param argvals: new values assigned to symbols
2427 :type argvals: ``dict`` with keywords of type `Symbol`
2428 :return: result of the substitution process. Operations are executed as
2429 much as possible.
2430 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2431 depending on the degree of substitution
2432 :raise TypeError: if a value for a `Symbol` cannot be substituted
2433 """
2434 if argvals.has_key(self):
2435 arg=argvals[self]
2436 if self.isAppropriateValue(arg):
2437 return arg
2438 else:
2439 raise TypeError,"%s: new value is not appropriate."%str(self)
2440 else:
2441 arg=self.getSubstitutedArguments(argvals)[0]
2442 return sinh(arg)
2443
2444 def diff(self,arg):
2445 """
2446 Differential of this object.
2447
2448 :param arg: the derivative is calculated with respect to ``arg``
2449 :type arg: `escript.Symbol`
2450 :return: derivative with respect to ``arg``
2451 :rtype: typically `Symbol` but other types such as ``float``,
2452 `escript.Data`, ``numpy.ndarray`` are possible
2453 """
2454 if arg==self:
2455 return identity(self.getShape())
2456 else:
2457 myarg=self.getArgument()[0]
2458 val=matchShape(cosh(myarg),self.getDifferentiatedArguments(arg)[0])
2459 return val[0]*val[1]
2460
2461 def cosh(arg):
2462 """
2463 Returns the hyperbolic cosine of argument ``arg``.
2464
2465 :param arg: argument
2466 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2467 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2468 on the type of ``arg``
2469 :raise TypeError: if the type of the argument is not expected
2470 """
2471 if isinstance(arg,numpy.ndarray):
2472 return numpy.cosh(arg)
2473 elif isinstance(arg,escript.Data):
2474 return arg._cosh()
2475 elif isinstance(arg,float):
2476 return math.cosh(arg)
2477 elif isinstance(arg,int):
2478 return math.cosh(arg)
2479 elif isinstance(arg,Symbol):
2480 return Cosh_Symbol(arg)
2481 else:
2482 raise TypeError,"cosh: Unknown argument type."
2483
2484 class Cosh_Symbol(DependendSymbol):
2485 """
2486 `Symbol` representing the result of the hyperbolic cosine function.
2487 """
2488 def __init__(self,arg):
2489 """
2490 Initialization of cosh `Symbol` with argument ``arg``.
2491
2492 :param arg: argument of function
2493 :type arg: typically `Symbol`
2494 """
2495 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2496
2497 def getMyCode(self,argstrs,format="escript"):
2498 """
2499 Returns program code that can be used to evaluate the symbol.
2500
2501 :param argstrs: a string for each argument representing the argument
2502 for the evaluation
2503 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2504 :param format: specifies the format to be used. At the moment only
2505 "escript", "str" and "text" are supported.
2506 :type format: ``str``
2507 :return: a piece of program code which can be used to evaluate the
2508 expression assuming the values for the arguments are available
2509 :rtype: ``str``
2510 :raise NotImplementedError: if no implementation for the given format
2511 is available
2512 """
2513 if isinstance(argstrs,list):
2514 argstrs=argstrs[0]
2515 if format=="escript" or format=="str" or format=="text":
2516 return "cosh(%s)"%argstrs
2517 else:
2518 raise NotImplementedError,"Cosh_Symbol does not provide program code for format %s."%format
2519
2520 def substitute(self,argvals):
2521 """
2522 Assigns new values to symbols in the definition of the symbol.
2523 The method replaces the `Symbol` u by argvals[u] in the expression
2524 defining this object.
2525
2526 :param argvals: new values assigned to symbols
2527 :type argvals: ``dict`` with keywords of type `Symbol`
2528 :return: result of the substitution process. Operations are executed as
2529 much as possible.
2530 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2531 depending on the degree of substitution
2532 :raise TypeError: if a value for a `Symbol` cannot be substituted
2533 """
2534 if argvals.has_key(self):
2535 arg=argvals[self]
2536 if self.isAppropriateValue(arg):
2537 return arg
2538 else:
2539 raise TypeError,"%s: new value is not appropriate."%str(self)
2540 else:
2541 arg=self.getSubstitutedArguments(argvals)[0]
2542 return cosh(arg)
2543
2544 def diff(self,arg):
2545 """
2546 Differential of this object.
2547
2548 :param arg: the derivative is calculated with respect to ``arg``
2549 :type arg: `escript.Symbol`
2550 :return: derivative with respect to ``arg``
2551 :rtype: typically `Symbol` but other types such as ``float``,
2552 `escript.Data`, ``numpy.ndarray`` are possible
2553 """
2554 if arg==self:
2555 return identity(self.getShape())
2556 else:
2557 myarg=self.getArgument()[0]
2558 val=matchShape(sinh(myarg),self.getDifferentiatedArguments(arg)[0])
2559 return val[0]*val[1]
2560
2561 def tanh(arg):
2562 """
2563 Returns the hyperbolic tangent of argument ``arg``.
2564
2565 :param arg: argument
2566 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2567 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2568 on the type of ``arg``
2569 :raise TypeError: if the type of the argument is not expected
2570 """
2571 if isinstance(arg,numpy.ndarray):
2572 return numpy.tanh(arg)
2573 elif isinstance(arg,escript.Data):
2574 return arg._tanh()
2575 elif isinstance(arg,float):
2576 return math.tanh(arg)
2577 elif isinstance(arg,int):
2578 return math.tanh(arg)
2579 elif isinstance(arg,Symbol):
2580 return Tanh_Symbol(arg)
2581 else:
2582 raise TypeError,"tanh: Unknown argument type."
2583
2584 class Tanh_Symbol(DependendSymbol):
2585 """
2586 `Symbol` representing the result of the hyperbolic tangent function.
2587 """
2588 def __init__(self,arg):
2589 """
2590 Initialization of tanh `Symbol` with argument ``arg``.
2591
2592 :param arg: argument of function
2593 :type arg: typically `Symbol`
2594 """
2595 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2596
2597 def getMyCode(self,argstrs,format="escript"):
2598 """
2599 Returns program code that can be used to evaluate the symbol.
2600
2601 :param argstrs: a string for each argument representing the argument
2602 for the evaluation
2603 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2604 :param format: specifies the format to be used. At the moment only
2605 "escript", "str" and "text" are supported.
2606 :type format: ``str``
2607 :return: a piece of program code which can be used to evaluate the
2608 expression assuming the values for the arguments are available
2609 :rtype: ``str``
2610 :raise NotImplementedError: if no implementation for the given format
2611 is available
2612 """
2613 if isinstance(argstrs,list):
2614 argstrs=argstrs[0]
2615 if format=="escript" or format=="str" or format=="text":
2616 return "tanh(%s)"%argstrs
2617 else:
2618 raise NotImplementedError,"Tanh_Symbol does not provide program code for format %s."%format
2619
2620 def substitute(self,argvals):
2621 """
2622 Assigns new values to symbols in the definition of the symbol.
2623 The method replaces the `Symbol` u by argvals[u] in the expression
2624 defining this object.
2625
2626 :param argvals: new values assigned to symbols
2627 :type argvals: ``dict`` with keywords of type `Symbol`
2628 :return: result of the substitution process. Operations are executed as
2629 much as possible.
2630 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2631 depending on the degree of substitution
2632 :raise TypeError: if a value for a `Symbol` cannot be substituted
2633 """
2634 if argvals.has_key(self):
2635 arg=argvals[self]
2636 if self.isAppropriateValue(arg):
2637 return arg
2638 else:
2639 raise TypeError,"%s: new value is not appropriate."%str(self)
2640 else:
2641 arg=self.getSubstitutedArguments(argvals)[0]
2642 return tanh(arg)
2643
2644 def diff(self,arg):
2645 """
2646 Differential of this object.
2647
2648 :param arg: the derivative is calculated with respect to ``arg``
2649 :type arg: `escript.Symbol`
2650 :return: derivative with respect to ``arg``
2651 :rtype: typically `Symbol` but other types such as ``float``,
2652 `escript.Data`, ``numpy.ndarray`` are possible
2653 """
2654 if arg==self:
2655 return identity(self.getShape())
2656 else:
2657 myarg=self.getArgument()[0]
2658 val=matchShape(1./cosh(myarg)**2,self.getDifferentiatedArguments(arg)[0])
2659 return val[0]*val[1]
2660
2661 def asinh(arg):
2662 """
2663 Returns the inverse hyperbolic sine of argument ``arg``.
2664
2665 :param arg: argument
2666 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2667 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2668 on the type of ``arg``
2669 :raise TypeError: if the type of the argument is not expected
2670 """
2671 if isinstance(arg,numpy.ndarray):
2672 return numpy.arcsinh(arg)
2673 elif isinstance(arg,escript.Data):
2674 return arg._asinh()
2675 elif isinstance(arg,float):
2676 return numpy.arcsinh(arg)
2677 elif isinstance(arg,int):
2678 return numpy.arcsinh(float(arg))
2679 elif isinstance(arg,Symbol):
2680 return Asinh_Symbol(arg)
2681 else:
2682 raise TypeError,"asinh: Unknown argument type."
2683
2684 class Asinh_Symbol(DependendSymbol):
2685 """
2686 `Symbol` representing the result of the inverse hyperbolic sine function.
2687 """
2688 def __init__(self,arg):
2689 """
2690 Initialization of asinh `Symbol` with argument ``arg``.
2691
2692 :param arg: argument of function
2693 :type arg: typically `Symbol`
2694 """
2695 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2696
2697 def getMyCode(self,argstrs,format="escript"):
2698 """
2699 Returns program code that can be used to evaluate the symbol.
2700
2701 :param argstrs: a string for each argument representing the argument
2702 for the evaluation
2703 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2704 :param format: specifies the format to be used. At the moment only
2705 "escript", "str" and "text" are supported.
2706 :type format: ``str``
2707 :return: a piece of program code which can be used to evaluate the
2708 expression assuming the values for the arguments are available
2709 :rtype: ``str``
2710 :raise NotImplementedError: if no implementation for the given format
2711 is available
2712 """
2713 if isinstance(argstrs,list):
2714 argstrs=argstrs[0]
2715 if format=="escript" or format=="str" or format=="text":
2716 return "asinh(%s)"%argstrs
2717 else:
2718 raise NotImplementedError,"Asinh_Symbol does not provide program code for format %s."%format
2719
2720 def substitute(self,argvals):
2721 """
2722 Assigns new values to symbols in the definition of the symbol.
2723 The method replaces the `Symbol` u by argvals[u] in the expression
2724 defining this object.
2725
2726 :param argvals: new values assigned to symbols
2727 :type argvals: ``dict`` with keywords of type `Symbol`
2728 :return: result of the substitution process. Operations are executed as
2729 much as possible.
2730 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2731 depending on the degree of substitution
2732 :raise TypeError: if a value for a `Symbol` cannot be substituted
2733 """
2734 if argvals.has_key(self):
2735 arg=argvals[self]
2736 if self.isAppropriateValue(arg):
2737 return arg
2738 else:
2739 raise TypeError,"%s: new value is not appropriate."%str(self)
2740 else:
2741 arg=self.getSubstitutedArguments(argvals)[0]
2742 return asinh(arg)
2743
2744 def diff(self,arg):
2745 """
2746 Differential of this object.
2747
2748 :param arg: the derivative is calculated with respect to ``arg``
2749 :type arg: `escript.Symbol`
2750 :return: derivative with respect to ``arg``
2751 :rtype: typically `Symbol` but other types such as ``float``,
2752 `escript.Data`, ``numpy.ndarray`` are possible
2753 """
2754 if arg==self:
2755 return identity(self.getShape())
2756 else:
2757 myarg=self.getArgument()[0]
2758 val=matchShape(1./sqrt(myarg**2+1),self.getDifferentiatedArguments(arg)[0])
2759 return val[0]*val[1]
2760
2761 def acosh(arg):
2762 """
2763 Returns the inverse hyperbolic cosine of argument ``arg``.
2764
2765 :param arg: argument
2766 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2767 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2768 on the type of ``arg``
2769 :raise TypeError: if the type of the argument is not expected
2770 """
2771 if isinstance(arg,numpy.ndarray):
2772 return numpy.arccosh(arg)
2773 elif isinstance(arg,escript.Data):
2774 return arg._acosh()
2775 elif isinstance(arg,float):
2776 return numpy.arccosh(arg)
2777 elif isinstance(arg,int):
2778 return numpy.arccosh(float(arg))
2779 elif isinstance(arg,Symbol):
2780 return Acosh_Symbol(arg)
2781 else:
2782 raise TypeError,"acosh: Unknown argument type."
2783
2784 class Acosh_Symbol(DependendSymbol):
2785 """
2786 `Symbol` representing the result of the inverse hyperbolic cosine function.
2787 """
2788 def __init__(self,arg):
2789 """
2790 Initialization of acosh `Symbol` with argument ``arg``.
2791
2792 :param arg: argument of function
2793 :type arg: typically `Symbol`
2794 """
2795 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2796
2797 def getMyCode(self,argstrs,format="escript"):
2798 """
2799 Returns program code that can be used to evaluate the symbol.
2800
2801 :param argstrs: a string for each argument representing the argument
2802 for the evaluation
2803 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2804 :param format: specifies the format to be used. At the moment only
2805 "escript", "str" and "text" are supported.
2806 :type format: ``str``
2807 :return: a piece of program code which can be used to evaluate the
2808 expression assuming the values for the arguments are available
2809 :rtype: ``str``
2810 :raise NotImplementedError: if no implementation for the given format
2811 is available
2812 """
2813 if isinstance(argstrs,list):
2814 argstrs=argstrs[0]
2815 if format=="escript" or format=="str" or format=="text":
2816 return "acosh(%s)"%argstrs
2817 else:
2818 raise NotImplementedError,"Acosh_Symbol does not provide program code for format %s."%format
2819
2820 def substitute(self,argvals):
2821 """
2822 Assigns new values to symbols in the definition of the symbol.
2823 The method replaces the `Symbol` u by argvals[u] in the expression
2824 defining this object.
2825
2826 :param argvals: new values assigned to symbols
2827 :type argvals: ``dict`` with keywords of type `Symbol`
2828 :return: result of the substitution process. Operations are executed as
2829 much as possible.
2830 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2831 depending on the degree of substitution
2832 :raise TypeError: if a value for a `Symbol` cannot be substituted
2833 """
2834 if argvals.has_key(self):
2835 arg=argvals[self]
2836 if self.isAppropriateValue(arg):
2837 return arg
2838 else:
2839 raise TypeError,"%s: new value is not appropriate."%str(self)
2840 else:
2841 arg=self.getSubstitutedArguments(argvals)[0]
2842 return acosh(arg)
2843
2844 def diff(self,arg):
2845 """
2846 Differential of this object.
2847
2848 :param arg: the derivative is calculated with respect to ``arg``
2849 :type arg: `escript.Symbol`
2850 :return: derivative with respect to ``arg``
2851 :rtype: typically `Symbol` but other types such as ``float``,
2852 `escript.Data`, ``numpy.ndarray`` are possible
2853 """
2854 if arg==self:
2855 return identity(self.getShape())
2856 else:
2857 myarg=self.getArgument()[0]
2858 val=matchShape(1./sqrt(myarg**2-1),self.getDifferentiatedArguments(arg)[0])
2859 return val[0]*val[1]
2860
2861 def atanh(arg):
2862 """
2863 Returns the inverse hyperbolic tangent of argument ``arg``.
2864
2865 :param arg: argument
2866 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2867 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2868 on the type of ``arg``
2869 :raise TypeError: if the type of the argument is not expected
2870 """
2871 if isinstance(arg,numpy.ndarray):
2872 return numpy.arctanh(arg)
2873 elif isinstance(arg,escript.Data):
2874 return arg._atanh()
2875 elif isinstance(arg,float):
2876 return numpy.arctanh(arg)
2877 elif isinstance(arg,int):
2878 return numpy.arctanh(float(arg))
2879 elif isinstance(arg,Symbol):
2880 return Atanh_Symbol(arg)
2881 else:
2882 raise TypeError,"atanh: Unknown argument type."
2883
2884 class Atanh_Symbol(DependendSymbol):
2885 """
2886 `Symbol` representing the result of the inverse hyperbolic tangent function.
2887 """
2888 def __init__(self,arg):
2889 """
2890 Initialization of atanh `Symbol` with argument ``arg``.
2891
2892 :param arg: argument of function
2893 :type arg: typically `Symbol`
2894 """
2895 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2896
2897 def getMyCode(self,argstrs,format="escript"):
2898 """
2899 Returns program code that can be used to evaluate the symbol.
2900
2901 :param argstrs: a string for each argument representing the argument
2902 for the evaluation
2903 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2904 :param format: specifies the format to be used. At the moment only
2905 "escript", "str" and "text" are supported.
2906 :type format: ``str``
2907 :return: a piece of program code which can be used to evaluate the
2908 expression assuming the values for the arguments are available
2909 :rtype: ``str``
2910 :raise NotImplementedError: if no implementation for the given format
2911 is available
2912 """
2913 if isinstance(argstrs,list):
2914 argstrs=argstrs[0]
2915 if format=="escript" or format=="str" or format=="text":
2916 return "atanh(%s)"%argstrs
2917 else:
2918 raise NotImplementedError,"Atanh_Symbol does not provide program code for format %s."%format
2919
2920 def substitute(self,argvals):
2921 """
2922 Assigns new values to symbols in the definition of the symbol.
2923 The method replaces the `Symbol` u by argvals[u] in the expression
2924 defining this object.
2925
2926 :param argvals: new values assigned to symbols
2927 :type argvals: ``dict`` with keywords of type `Symbol`
2928 :return: result of the substitution process. Operations are executed as
2929 much as possible.
2930 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2931 depending on the degree of substitution
2932 :raise TypeError: if a value for a `Symbol` cannot be substituted
2933 """
2934 if argvals.has_key(self):
2935 arg=argvals[self]
2936 if self.isAppropriateValue(arg):
2937 return arg
2938 else:
2939 raise TypeError,"%s: new value is not appropriate."%str(self)
2940 else:
2941 arg=self.getSubstitutedArguments(argvals)[0]
2942 return atanh(arg)
2943
2944 def diff(self,arg):
2945 """
2946 Differential of this object.
2947
2948 :param arg: the derivative is calculated with respect to ``arg``
2949 :type arg: `escript.Symbol`
2950 :return: derivative with respect to ``arg``
2951 :rtype: typically `Symbol` but other types such as ``float``,
2952 `escript.Data`, ``numpy.ndarray`` are possible
2953 """
2954 if arg==self:
2955 return identity(self.getShape())
2956 else:
2957 myarg=self.getArgument()[0]
2958 val=matchShape(1./(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2959 return val[0]*val[1]
2960
2961 def exp(arg):
2962 """
2963 Returns *e* to the power of argument ``arg``.
2964
2965 :param arg: argument
2966 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
2967 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2968 on the type of arg
2969 :raise TypeError: if the type of the argument is not expected
2970 """
2971 if isinstance(arg,numpy.ndarray):
2972 return numpy.exp(arg)
2973 elif isinstance(arg,escript.Data):
2974 return arg._exp()
2975 elif isinstance(arg,float):
2976 return math.exp(arg)
2977 elif isinstance(arg,int):
2978 return math.exp(arg)
2979 elif isinstance(arg,Symbol):
2980 return Exp_Symbol(arg)
2981 else:
2982 raise TypeError,"exp: Unknown argument type."
2983
2984 class Exp_Symbol(DependendSymbol):
2985 """
2986 `Symbol` representing the result of the exponential function.
2987 """
2988 def __init__(self,arg):
2989 """
2990 Initialization of exp `Symbol` with argument ``arg``.
2991
2992 :param arg: argument of function
2993 :type arg: typically `Symbol`
2994 """
2995 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2996
2997 def getMyCode(self,argstrs,format="escript"):
2998 """
2999 Returns program code that can be used to evaluate the symbol.
3000
3001 :param argstrs: a string for each argument representing the argument
3002 for the evaluation
3003 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3004 :param format: specifies the format to be used. At the moment only
3005 "escript", "str" and "text" are supported.
3006 :type format: ``str``
3007 :return: a piece of program code which can be used to evaluate the
3008 expression assuming the values for the arguments are available
3009 :rtype: ``str``
3010 :raise NotImplementedError: if no implementation for the given format
3011 is available
3012 """
3013 if isinstance(argstrs,list):
3014 argstrs=argstrs[0]
3015 if format=="escript" or format=="str" or format=="text":
3016 return "exp(%s)"%argstrs
3017 else:
3018 raise NotImplementedError,"Exp_Symbol does not provide program code for format %s."%format
3019
3020 def substitute(self,argvals):
3021 """
3022 Assigns new values to symbols in the definition of the symbol.
3023 The method replaces the `Symbol` u by argvals[u] in the expression
3024 defining this object.
3025
3026 :param argvals: new values assigned to symbols
3027 :type argvals: ``dict`` with keywords of type `Symbol`
3028 :return: result of the substitution process. Operations are executed as
3029 much as possible.
3030 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3031 depending on the degree of substitution
3032 :raise TypeError: if a value for a `Symbol` cannot be substituted
3033 """
3034 if argvals.has_key(self):
3035 arg=argvals[self]
3036 if self.isAppropriateValue(arg):
3037 return arg
3038 else:
3039 raise TypeError,"%s: new value is not appropriate."%str(self)
3040 else:
3041 arg=self.getSubstitutedArguments(argvals)[0]
3042 return exp(arg)
3043
3044 def diff(self,arg):
3045 """
3046 Differential of this object.
3047
3048 :param arg: the derivative is calculated with respect to ``arg``
3049 :type arg: `escript.Symbol`
3050 :return: derivative with respect to ``arg``
3051 :rtype: typically `Symbol` but other types such as ``float``,
3052 `escript.Data`, ``numpy.ndarray`` are possible
3053 """
3054 if arg==self:
3055 return identity(self.getShape())
3056 else:
3057 myarg=self.getArgument()[0]
3058 val=matchShape(self,self.getDifferentiatedArguments(arg)[0])
3059 return val[0]*val[1]
3060
3061 def sqrt(arg):
3062 """
3063 Returns the square root of argument ``arg``.
3064
3065 :param arg: argument
3066 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3067 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3068 depending on the type of ``arg``
3069 :raise TypeError: if the type of the argument is not expected
3070 """
3071 if isinstance(arg,numpy.ndarray):
3072 return numpy.sqrt(arg)
3073 elif isinstance(arg,escript.Data):
3074 return arg._sqrt()
3075 elif isinstance(arg,float):
3076 return math.sqrt(arg)
3077 elif isinstance(arg,int):
3078 return math.sqrt(arg)
3079 elif isinstance(arg,Symbol):
3080 return Sqrt_Symbol(arg)
3081 else:
3082 raise TypeError,"sqrt: Unknown argument type."
3083
3084 class Sqrt_Symbol(DependendSymbol):
3085 """
3086 `Symbol` representing the result of the square root function.
3087 """
3088 def __init__(self,arg):
3089 """
3090 Initialization of sqrt `Symbol` with argument ``arg``.
3091
3092 :param arg: argument of function
3093 :type arg: typically `Symbol`
3094 """
3095 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
3096
3097 def getMyCode(self,argstrs,format="escript"):
3098 """
3099 Returns program code that can be used to evaluate the symbol.
3100
3101 :param argstrs: a string for each argument representing the argument
3102 for the evaluation
3103 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3104 :param format: specifies the format to be used. At the moment only
3105 "escript", "str" and "text" are supported.
3106 :type format: ``str``
3107 :return: a piece of program code which can be used to evaluate the
3108 expression assuming the values for the arguments are available
3109 :rtype: ``str``
3110 :raise NotImplementedError: if no implementation for the given format
3111 is available
3112 """
3113 if isinstance(argstrs,list):
3114 argstrs=argstrs[0]
3115 if format=="escript" or format=="str" or format=="text":
3116 return "sqrt(%s)"%argstrs
3117 else:
3118 raise NotImplementedError,"Sqrt_Symbol does not provide program code for format %s."%format
3119
3120 def substitute(self,argvals):
3121 """
3122 Assigns new values to symbols in the definition of the symbol.
3123 The method replaces the `Symbol` u by argvals[u] in the expression
3124 defining this object.
3125
3126 :param argvals: new values assigned to symbols
3127 :type argvals: ``dict`` with keywords of type `Symbol`
3128 :return: result of the substitution process. Operations are executed as
3129 much as possible.
3130 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3131 depending on the degree of substitution
3132 :raise TypeError: if a value for a `Symbol` cannot be substituted
3133 """
3134 if argvals.has_key(self):
3135 arg=argvals[self]
3136 if self.isAppropriateValue(arg):
3137 return arg
3138 else:
3139 raise TypeError,"%s: new value is not appropriate."%str(self)
3140 else:
3141 arg=self.getSubstitutedArguments(argvals)[0]
3142 return sqrt(arg)
3143
3144 def diff(self,arg):
3145 """
3146 Differential of this object.
3147
3148 :param arg: the derivative is calculated with respect to ``arg``
3149 :type arg: `escript.Symbol`
3150 :return: derivative with respect to ``arg``
3151 :rtype: typically `Symbol` but other types such as ``float``,
3152 `escript.Data`, ``numpy.ndarray`` are possible
3153 """
3154 if arg==self:
3155 return identity(self.getShape())
3156 else:
3157 myarg=self.getArgument()[0]
3158 val=matchShape(0.5/self,self.getDifferentiatedArguments(arg)[0])
3159 return val[0]*val[1]
3160
3161 def log(arg):
3162 """
3163 Returns the natural logarithm of argument ``arg``.
3164
3165 :param arg: argument
3166 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
3167 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
3168 on the type of ``arg``
3169 :raise TypeError: if the type of the argument is not expected
3170 """
3171 if isinstance(arg,numpy.ndarray):
3172 return numpy.log(arg)
3173 elif isinstance(arg,escript.Data):
3174 return arg._log()
3175 elif isinstance(arg,float):
3176 return math.log(arg)
3177 elif isinstance(arg,int):
3178 return math.log(arg)
3179 elif isinstance(arg,Symbol):
3180 return Log_Symbol(arg)
3181 else:
3182 raise TypeError,"log: Unknown argument type."
3183
3184 class Log_Symbol(DependendSymbol):
3185 """
3186 `Symbol` representing the result of the natural logarithm function.
3187 """
3188 def __init__(self,arg):
3189 """
3190 Initialization of log `Symbol` with argument ``arg``.
3191
3192 :param arg: argument of function
3193 :type arg: typically `Symbol`
3194 """
3195 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
3196
3197 def getMyCode(self,argstrs,format="escript"):
3198 """
3199 Returns program code that can be used to evaluate the symbol.
3200
3201 :param argstrs: a string for each argument representing the argument
3202 for the evaluation
3203 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3204 :param format: specifies the format to be used. At the moment only
3205 "escript", "str" and "text" are supported.
3206 :type format: ``str``
3207 :return: a piece of program code which can be used to evaluate the
3208 expression assuming the values for the arguments are available
3209 :rtype: ``str``
3210 :raise NotImplementedError: if no implementation for the given format
3211 is available
3212 """
3213 if isinstance(argstrs,list):
3214 argstrs=argstrs[0]
3215 if format=="escript" or format=="str" or format=="text":
3216 return "log(%s)"%argstrs
3217 else:
3218 raise NotImplementedError,"Log_Symbol does not provide program code for format %s."%format
3219
3220 def substitute(self,argvals):
3221 """
3222 Assigns new values to symbols in the definition of the symbol.
3223 The method replaces the `Symbol` u by argvals[u] in the expression
3224 defining this object.
3225
3226 :param argvals: new values assigned to symbols
3227 :type argvals: ``dict`` with keywords of type `Symbol`
3228 :return: result of the substitution process. Operations are executed as
3229 much as possible.
3230 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3231 depending on the degree of substitution
3232 :raise TypeError: if a value for a `Symbol` cannot be substituted
3233 """
3234 if argvals.has_key(self):
3235 arg=argvals[self]
3236 if self.isAppropriateValue(arg):
3237 return arg
3238 else:
3239 raise TypeError,"%s: new value is not appropriate."%str(self)
3240 else:
3241 arg=self.getSubstitutedArguments(argvals)[0]
3242 return log(arg)
3243
3244 def diff(self,arg):
3245 """
3246 Differential of this object.
3247
3248 :param arg: the derivative is calculated with respect to ``arg``
3249 :type arg: `escript.Symbol`
3250 :return: derivative with respect to ``arg``
3251 :rtype: typically `Symbol` but other types such as ``float``,
3252 `escript.Data`, ``numpy.ndarray`` are possible
3253 """
3254 if arg==self:
3255 return identity(self.getShape())
3256 else:
3257 myarg=self.getArgument()[0]
3258 val=matchShape(1./arg,self.getDifferentiatedArguments(arg)[0])
3259 return val[0]*val[1]
3260
3261 def sign(arg):
3262 """
3263 Returns the sign of argument ``arg``.
3264
3265 :param arg: argument
3266 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3267 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
3268 on the type of ``arg``
3269 :raise TypeError: if the type of the argument is not expected
3270 """
3271 if isinstance(arg,numpy.ndarray):
3272 return wherePositive(arg)-whereNegative(arg)
3273 elif isinstance(arg,escript.Data):
3274 return arg._sign()
3275 elif isinstance(arg,float):
3276 if arg>0:
3277 return 1.
3278 elif arg<0:
3279 return -1.
3280 else:
3281 return 0.
3282 elif isinstance(arg,int):
3283 if float(arg)>0:
3284 return 1.
3285 elif float(arg)<0:
3286 return -1.
3287 else:
3288 return 0.
3289 elif isinstance(arg,Symbol):
3290 return wherePositive(arg)-whereNegative(arg)
3291 else:
3292 raise TypeError,"sign: Unknown argument type."
3293
3294 class Abs_Symbol(DependendSymbol):
3295 """
3296 `Symbol` representing the result of the absolute value function.
3297 """
3298 def __init__(self,arg):
3299 """
3300 Initialization of abs `Symbol` with argument ``arg``.
3301
3302 :param arg: argument of function
3303 :type arg: typically `Symbol`
3304 """
3305 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
3306
3307 def getMyCode(self,argstrs,format="escript"):
3308 """
3309 Returns program code that can be used to evaluate the symbol.
3310
3311 :param argstrs: a string for each argument representing the argument
3312 for the evaluation
3313 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3314 :param format: specifies the format to be used. At the moment only
3315 "escript", "str" and "text" are supported.
3316 :type format: ``str``
3317 :return: a piece of program code which can be used to evaluate the
3318 expression assuming the values for the arguments are available
3319 :rtype: ``str``
3320 :raise NotImplementedError: if no implementation for the given format
3321 is available
3322 """
3323 if isinstance(argstrs,list):
3324 argstrs=argstrs[0]
3325 if format=="escript" or format=="str" or format=="text":
3326 return "abs(%s)"%argstrs
3327 else:
3328 raise NotImplementedError,"Abs_Symbol does not provide program code for format %s."%format
3329
3330 def substitute(self,argvals):
3331 """
3332 Assigns new values to symbols in the definition of the symbol.
3333 The method replaces the `Symbol` u by argvals[u] in the expression
3334 defining this object.
3335
3336 :param argvals: new values assigned to symbols
3337 :type argvals: ``dict`` with keywords of type `Symbol`
3338 :return: result of the substitution process. Operations are executed as
3339 much as possible.
3340 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3341 depending on the degree of substitution
3342 :raise TypeError: if a value for a `Symbol` cannot be substituted
3343 """
3344 if argvals.has_key(self):
3345 arg=argvals[self]
3346 if self.isAppropriateValue(arg):
3347 return arg
3348 else:
3349 raise TypeError,"%s: new value is not appropriate."%str(self)
3350 else:
3351 arg=self.getSubstitutedArguments(argvals)[0]
3352 return abs(arg)
3353
3354 def diff(self,arg):
3355 """
3356 Differential of this object.
3357
3358 :param arg: the derivative is calculated with respect to ``arg``
3359 :type arg: `escript.Symbol`
3360 :return: derivative with respect to ``arg``
3361 :rtype: typically `Symbol` but other types such as ``float``,
3362 `escript.Data`, ``numpy.ndarray`` are possible
3363 """
3364 if arg==self:
3365 return identity(self.getShape())
3366 else:
3367 myarg=self.getArgument()[0]
3368 val=matchShape(sign(myarg),self.getDifferentiatedArguments(arg)[0])
3369 return val[0]*val[1]
3370
3371 def minval(arg):
3372 """
3373 Returns the minimum value over all components of ``arg`` at each data point.
3374
3375 :param arg: argument
3376 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3377 :rtype: ``float``, `escript.Data`, `Symbol` depending on the type of ``arg``
3378 :raise TypeError: if the type of the argument is not expected
3379 """
3380 if isinstance(arg,numpy.ndarray):
3381 if arg.ndim==0:
3382 return float(arg)
3383 else:
3384 return arg.min()
3385 elif isinstance(arg,escript.Data):
3386 return arg._minval()
3387 elif isinstance(arg,float):
3388 return arg
3389 elif isinstance(arg,int):
3390 return float(arg)
3391 elif isinstance(arg,Symbol):
3392 return Minval_Symbol(arg)
3393 else:
3394 raise TypeError,"minval: Unknown argument type."
3395
3396 class Minval_Symbol(DependendSymbol):
3397 """
3398 `Symbol` representing the result of the minimum value function.
3399 """
3400 def __init__(self,arg):
3401 """
3402 Initialization of minimum value `Symbol` with argument ``arg``.
3403
3404 :param arg: argument of function
3405 :type arg: typically `Symbol`
3406 """
3407 DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
3408
3409 def getMyCode(self,argstrs,format="escript"):
3410 """
3411 Returns program code that can be used to evaluate the symbol.
3412
3413 :param argstrs: a string for each argument representing the argument
3414 for the evaluation
3415 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3416 :param format: specifies the format to be used. At the moment only
3417 "escript", "str" and "text" are supported.
3418 :type format: ``str``
3419 :return: a piece of program code which can be used to evaluate the
3420 expression assuming the values for the arguments are available
3421 :rtype: ``str``
3422 :raise NotImplementedError: if no implementation for the given format
3423 is available
3424 """
3425 if isinstance(argstrs,list):
3426 argstrs=argstrs[0]
3427 if format=="escript" or format=="str" or format=="text":
3428 return "minval(%s)"%argstrs
3429 else:
3430 raise NotImplementedError,"Minval_Symbol does not provide program code for format %s."%format
3431
3432 def substitute(self,argvals):
3433 """
3434 Assigns new values to symbols in the definition of the symbol.
3435 The method replaces the `Symbol` u by argvals[u] in the expression
3436 defining this object.
3437
3438 :param argvals: new values assigned to symbols
3439 :type argvals: ``dict`` with keywords of type `Symbol`
3440 :return: result of the substitution process. Operations are executed as
3441 much as possible.
3442 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3443 depending on the degree of substitution
3444 :raise TypeError: if a value for a `Symbol` cannot be substituted
3445 """
3446 if argvals.has_key(self):
3447 arg=argvals[self]
3448 if self.isAppropriateValue(arg):
3449 return arg
3450 else:
3451 raise TypeError,"%s: new value is not appropriate."%str(self)
3452 else:
3453 arg=self.getSubstitutedArguments(argvals)[0]
3454 return minval(arg)
3455
3456 def maxval(arg):
3457 """
3458 Returns the maximum value over all components of ``arg`` at each data point.
3459
3460 :param arg: argument
3461 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3462 :rtype: ``float``, `escript.Data`, `Symbol` depending on the type of ``arg``
3463 :raise TypeError: if the type of the argument is not expected
3464 """
3465 if isinstance(arg,numpy.ndarray):
3466 if arg.ndim==0:
3467 return float(arg)
3468 else:
3469 return arg.max()
3470 elif isinstance(arg,escript.Data):
3471 return arg._maxval()
3472 elif isinstance(arg,float):
3473 return arg
3474 elif isinstance(arg,int):
3475 return float(arg)
3476 elif isinstance(arg,Symbol):
3477 return Maxval_Symbol(arg)
3478 else:
3479 raise TypeError,"maxval: Unknown argument type."
3480
3481 class Maxval_Symbol(DependendSymbol):
3482 """
3483 `Symbol` representing the result of the maximum value function.
3484 """
3485 def __init__(self,arg):
3486 """
3487 Initialization of maximum value `Symbol` with argument ``arg``.
3488
3489 :param arg: argument of function
3490 :type arg: typically `Symbol`
3491 """
3492 DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
3493
3494 def getMyCode(self,argstrs,format="escript"):
3495 """
3496 Returns program code that can be used to evaluate the symbol.
3497
3498 :param argstrs: a string for each argument representing the argument
3499 for the evaluation
3500 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3501 :param format: specifies the format to be used. At the moment only
3502 "escript", "str" and "text" are supported.
3503 :type format: ``str``
3504 :return: a piece of program code which can be used to evaluate the
3505 expression assuming the values for the arguments are available
3506 :rtype: ``str``
3507 :raise NotImplementedError: if no implementation for the given format
3508 is available
3509 """
3510 if isinstance(argstrs,list):
3511 argstrs=argstrs[0]
3512 if format=="escript" or format=="str" or format=="text":
3513 return "maxval(%s)"%argstrs
3514 else:
3515 raise NotImplementedError,"Maxval_Symbol does not provide program code for format %s."%format
3516
3517 def substitute(self,argvals):
3518 """
3519 Assigns new values to symbols in the definition of the symbol.
3520 The method replaces the `Symbol` u by argvals[u] in the expression
3521 defining this object.
3522
3523 :param argvals: new values assigned to symbols
3524 :type argvals: ``dict`` with keywords of type `Symbol`
3525 :return: result of the substitution process. Operations are executed as
3526 much as possible.
3527 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3528 depending on the degree of substitution
3529 :raise TypeError: if a value for a `Symbol` cannot be substituted
3530 """
3531 if argvals.has_key(self):
3532 arg=argvals[self]
3533 if self.isAppropriateValue(arg):
3534 return arg
3535 else:
3536 raise TypeError,"%s: new value is not appropriate."%str(self)
3537 else:
3538 arg=self.getSubstitutedArguments(argvals)[0]
3539 return maxval(arg)
3540
3541 def length(arg):
3542 """
3543 Returns the length (Euclidean norm) of argument ``arg`` at each data point.
3544
3545 :param arg: argument
3546 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3547 :rtype: ``float``, `escript.Data`, `Symbol` depending on the type of ``arg``
3548 """
3549 return sqrt(inner(arg,arg))
3550
3551 def trace(arg,axis_offset=0):
3552 """
3553 Returns the trace of ``arg`` which is the sum of ``arg[k,k]`` over k.
3554
3555 :param arg: argument
3556 :type arg: `escript.Data`, `Symbol`, ``numpy.ndarray``
3557 :param axis_offset: ``axis_offset`` to components to sum over. ``axis_offset``
3558 must be non-negative and less than the rank of ``arg`` +1.
3559 The dimensions of component ``axis_offset`` and
3560 axis_offset+1 must be equal.
3561 :type axis_offset: ``int``
3562 :return: trace of arg. The rank of the returned object is rank of ``arg``
3563 minus 2.
3564 :rtype: `escript.Data`, `Symbol`, ``numpy.ndarray`` depending on the
3565 type of ``arg``
3566 """
3567 if isinstance(arg,numpy.ndarray):
3568 sh=arg.shape
3569 if len(sh)<2:
3570 raise ValueError,"rank of argument must be greater than 1"
3571 if axis_offset<0 or axis_offset>len(sh)-2:
3572 raise ValueError,"axis_offset must be between 0 and %d"%(len(sh)-2)
3573 s1=1
3574 for i in range(axis_offset): s1*=sh[i]
3575 s2=1
3576