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