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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2745 - (hide annotations)
Tue Nov 17 04:23:02 2009 UTC (11 years, 5 months ago) by jfenwick
File MIME type: text/x-python
File size: 234890 byte(s)
Added getInfLocator and getSupLocator to pdetools.
This means if you want to use them, you will need to import them.
These methods return a locator to a point with the smallest/largest value.

Added resolve() and delay() to utils.
Now you can do things like:

d=delay(v)
..
..
z=resolve(d+1)


1 ksteube 1809
2     ########################################################
3 ksteube 1312 #
4 jfenwick 2548 # Copyright (c) 2003-2009 by University of Queensland
5 ksteube 1809 # Earth Systems Science Computational Center (ESSCC)
6     # http://www.uq.edu.au/esscc
7 ksteube 1312 #
8 ksteube 1809 # 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 ksteube 1312 #
12 ksteube 1809 ########################################################
13 jgs 82
14 jfenwick 2549 __copyright__="""Copyright (c) 2003-2009 by University of Queensland
15 ksteube 1809 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 jfenwick 2344 __url__="https://launchpad.net/escript-finley"
21 ksteube 1809
22 jgs 82 """
23 jgs 149 Utility functions for escript
24 jgs 123
25 jfenwick 2625 :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 jgs 82 """
34 ksteube 1809
35 gross 290 __author__="Lutz Gross, l.gross@uq.edu.au"
36 jgs 82
37 gross 290
38     import math
39 jfenwick 2455 import numpy
40 jgs 102 import escript
41 jgs 150 import os
42 ksteube 813 from esys.escript import C_GeneralTensorProduct
43 gross 2415 from esys.escript import getVersion, getMPIRankWorld, getMPIWorldMax
44 ksteube 1561 from esys.escript import printParallelThreadCounts
45 jfenwick 2142 from esys.escript import listEscriptParams
46 jfenwick 2635 from esys.escript.escriptcpp import Data, _saveDataCSV
47 jgs 124
48 jgs 123 #=========================================================
49 gross 290 # some helpers:
50 jgs 123 #=========================================================
51 ksteube 1312 def getEpsilon():
52 gross 2100 return escript.getMachinePrecision()
53 ksteube 1312 EPSILON=getEpsilon()
54    
55 gross 2100 def getMaxFloat():
56     return escript.getMaxFloat()
57     DBLE_MAX=getMaxFloat()
58    
59 gross 1042 def getTagNames(domain):
60     """
61 caltinay 2169 Returns a list of tag names used by the domain.
62 gross 1042
63 jfenwick 2625 :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 gross 1042 """
68     return [n.strip() for n in domain.showTagNames().split(",") ]
69 gross 1044
70     def insertTagNames(domain,**kwargs):
71     """
72 caltinay 2169 Inserts tag names into the domain.
73 gross 1044
74 jfenwick 2625 :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 gross 1044 """
79     for k in kwargs:
80     domain.setTagMap(k,kwargs[k])
81    
82     def insertTaggedValues(target,**kwargs):
83     """
84 caltinay 2169 Inserts tagged values into the target using tag names.
85 gross 1044
86 jfenwick 2625 :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 gross 1044 """
93     for k in kwargs:
94     target.setTaggedValue(k,kwargs[k])
95     return target
96    
97 jfenwick 2635 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     saveDataCSV("f.csv",a=s, b=v, c=t)
107    
108     Will result in a file
109    
110     a, b0, b1, c0_0, c0_1, .., c1_0
111     1.0, 1.5, 2.7, 3.1, 3.4, .., 0.89
112     0.9, 8.7, 1.9, 3.4, 7.8, .., 1.21
113    
114     The first line is a header, the remaining lines give the values.
115    
116     :param filename: file to save data to.
117     :type filename: ``string``
118 jfenwick 2644 :param append: If ``True``, then open file at end rather than beginning
119     :type append: ``bool``
120 jfenwick 2635 :param sep: separator between fields
121     :type sep: ``string``
122     :param csep: separator for components of rank2 and above eg ('_' -> c0_1)
123    
124     The keyword args are Data objects to save.
125 jfenwick 2644 If a scalar `Data` object is passed with the name ``mask``, then only
126     samples which correspond to positive values in ``mask`` will be output.
127 jfenwick 2635 """
128     new_data={}
129     for n,d in data.items():
130     if not isinstance(d, Data):
131     raise ValueError, "saveDataCSV: unknown non-data argument %s"%(str(n))
132     new_data[n]=d
133     _saveDataCSV(filename, new_data,sep, csep, append)
134    
135 gross 2421 def saveVTK(filename,domain=None, metadata=None, metadata_schema=None, **data):
136 jgs 150 """
137 jfenwick 2625 Writes `Data` objects and their mesh into a file using the VTK XML file
138 caltinay 2169 format.
139 jgs 123
140 gross 720 Example::
141 jgs 123
142 caltinay 2169 tmp=Scalar(..)
143     v=Vector(..)
144 caltinay 2534 saveVTK("solution.vtu", temperature=tmp, velocity=v)
145 jgs 150
146 jfenwick 2625 ``tmp`` and ``v`` are written into "solution.vtu" where ``tmp`` is named
147     "temperature" and ``v`` is named "velocity".
148 jgs 153
149 caltinay 2526 Meta tags, e.g. a timeStamp, can be added to the file, for instance::
150 gross 2421
151     tmp=Scalar(..)
152     v=Vector(..)
153 caltinay 2534 saveVTK("solution.vtu", temperature=tmp, velocity=v,
154 caltinay 2526 metadata="<timeStamp>1.234</timeStamp>",
155     metadata_schema={ "gml" : "http://www.opengis.net/gml"})
156 gross 2421
157 jfenwick 2625 The argument ``metadata_schema`` allows the definition of name spaces with a schema used in the definition of meta tags.
158 gross 2421
159 jfenwick 2625 :param filename: file name of the output file
160     :type filename: ``str``
161     :param domain: domain of the `Data` objects. If not specified, the domain
162     of the given `Data` objects is used.
163     :type domain: `escript.Domain`
164     :keyword <name>: writes the assigned value to the VTK file using <name> as
165 caltinay 2169 identifier
166 jfenwick 2625 :param metadata: additional XML meta data which are inserted into the VTK file. The meta data are marked by the tag ``<MetaData>``.
167     :type metadata: ``str``
168     :param metadata_schema: assignes schema to namespaces which have been used to define meta data.
169     :type metadata_schema: ``dict`` with ``metadata_schema[<namespace>]=<URI>`` to assign the scheme ``<URI>`` to the name space ``<namespace>``.
170     :note: The data objects have to be defined on the same domain. They may not
171     be in the same `FunctionSpace` but one cannot expect that all
172     `FunctionSpace` s can be mixed. Typically, data on the boundary and
173 caltinay 2169 data on the interior cannot be mixed.
174 jgs 149 """
175 gross 2421 # create the string if meta data:
176     if not metadata==None:
177     metadata2="<MetaData>"+metadata+"</MetaData>"
178     else:
179     metadata2=""
180     metadata_shema2=""
181     if not metadata_schema==None:
182     for i,p in metadata_schema.items():
183     metadata_shema2="%s xmlns:%s=\"%s\""%(metadata_shema2,i,p)
184 ksteube 1312 new_data={}
185     for n,d in data.items():
186 caltinay 2169 if not d.isEmpty():
187     fs=d.getFunctionSpace()
188 ksteube 1312 domain2=fs.getDomain()
189     if fs == escript.Solution(domain2):
190     new_data[n]=interpolate(d,escript.ContinuousFunction(domain2))
191     elif fs == escript.ReducedSolution(domain2):
192     new_data[n]=interpolate(d,escript.ReducedContinuousFunction(domain2))
193     else:
194     new_data[n]=d
195     if domain==None: domain=domain2
196 jgs 153 if domain==None:
197 caltinay 2169 raise ValueError,"saveVTK: no domain detected."
198 gross 2421 domain.saveVTK(filename,new_data,metadata2.strip(),metadata_shema2.strip())
199 jgs 154
200 jgs 153 def saveDX(filename,domain=None,**data):
201 jgs 149 """
202 jfenwick 2625 Writes `Data` objects into a file using the OpenDX file format.
203 jgs 149
204 gross 720 Example::
205 jgs 150
206 caltinay 2169 tmp=Scalar(..)
207     v=Vector(..)
208     saveDX("solution.dx", temperature=tmp, velocity=v)
209 jgs 150
210 jfenwick 2625 ``tmp`` and ``v`` are written into "solution.dx" where ``tmp`` is named
211     "temperature" and ``v`` is named "velocity".
212 jgs 153
213 jfenwick 2625 :param filename: file name of the output file
214     :type filename: ``str``
215     :param domain: domain of the `Data` objects. If not specified, the domain
216     of the given `Data` objects is used.
217     :type domain: `escript.Domain`
218     :keyword <name>: writes the assigned value to the DX file using <name> as
219 caltinay 2169 identifier. The identifier can be used to select the data
220     set when data are imported into DX.
221 jfenwick 2625 :type <name>: `Data` object
222     :note: The data objects have to be defined on the same domain. They may not
223     be in the same `FunctionSpace` but one cannot expect that all
224     `FunctionSpace` s can be mixed. Typically, data on the boundary and
225 caltinay 2169 data on the interior cannot be mixed.
226 jgs 149 """
227 ksteube 1312 new_data={}
228     for n,d in data.items():
229 caltinay 2169 if not d.isEmpty():
230     fs=d.getFunctionSpace()
231 ksteube 1312 domain2=fs.getDomain()
232     if fs == escript.Solution(domain2):
233     new_data[n]=interpolate(d,escript.ReducedContinuousFunction(domain2))
234     elif fs == escript.ReducedSolution(domain2):
235     new_data[n]=interpolate(d,escript.ReducedContinuousFunction(domain2))
236     elif fs == escript.ContinuousFunction(domain2):
237     new_data[n]=interpolate(d,escript.ReducedContinuousFunction(domain2))
238     else:
239     new_data[n]=d
240     if domain==None: domain=domain2
241 jgs 153 if domain==None:
242 caltinay 2169 raise ValueError,"saveDX: no domain detected."
243 ksteube 1312 domain.saveDX(filename,new_data)
244 jgs 154
245 caltinay 2599 def saveESD(datasetName, dataDir=".", domain=None, timeStep=0, deltaT=1, dynamicMesh=0, **data):
246 caltinay 2188 """
247 jfenwick 2625 Saves `Data` objects to files and creates an I{escript dataset} (ESD) file
248 caltinay 2188 for convenient processing/visualisation.
249    
250 caltinay 2526 Single timestep example::
251 caltinay 2188
252     tmp = Scalar(..)
253     v = Vector(..)
254     saveESD("solution", "data", temperature=tmp, velocity=v)
255    
256 caltinay 2526 Time series example::
257    
258     while t < t_end:
259     tmp = Scalar(..)
260     v = Vector(..)
261     # save every 10 timesteps
262     if t % 10 == 0:
263     saveESD("solution", "data", timeStep=t, deltaT=10, temperature=tmp, velocity=v)
264     t = t + 1
265    
266 caltinay 2188 tmp, v and the domain are saved in native format in the "data"
267     directory and the file "solution.esd" is created that refers to tmp by
268     the name "temperature" and to v by the name "velocity".
269    
270 jfenwick 2625 :param datasetName: name of the dataset, used to name the ESD file
271     :type datasetName: ``str``
272     :param dataDir: optional directory where the data files should be saved
273     :type dataDir: ``str``
274     :param domain: domain of the `Data` object(s). If not specified, the
275     domain of the given `Data` objects is used.
276     :type domain: `escript.Domain`
277     :param timeStep: current timestep or sequence number - first one must be 0
278     :type timeStep: `int`
279     :param deltaT: timestep or sequence increment, see example above
280     :type deltaT: `int`
281     :param dynamicMesh: by default the mesh is assumed to be static and thus
282 caltinay 2599 only saved once at timestep 0 to save disk space.
283     Setting this to 1 changes the behaviour and the mesh
284     is saved at each timestep.
285 jfenwick 2625 :type dynamicMesh: `int`
286     :keyword <name>: writes the assigned value to the file using <name> as
287 caltinay 2188 identifier
288 jfenwick 2625 :type <name>: `Data` object
289     :note: The data objects have to be defined on the same domain. They may not
290     be in the same `FunctionSpace` but one cannot expect that all
291     `FunctionSpace` s can be mixed. Typically, data on the boundary and
292 caltinay 2188 data on the interior cannot be mixed.
293 jfenwick 2625 :note: When saving a time series the first timestep must be 0 and it is
294 caltinay 2526 assumed that data from all timesteps share the domain. The dataset
295     file is updated in each iteration.
296 caltinay 2188 """
297     new_data = {}
298     for n,d in data.items():
299     if not d.isEmpty():
300     fs = d.getFunctionSpace()
301     domain2 = fs.getDomain()
302     if fs == escript.Solution(domain2):
303     new_data[n]=interpolate(d,escript.ContinuousFunction(domain2))
304     elif fs == escript.ReducedSolution(domain2):
305     new_data[n]=interpolate(d,escript.ReducedContinuousFunction(domain2))
306     else:
307     new_data[n]=d
308     if domain==None: domain=domain2
309     if domain==None:
310     raise ValueError, "saveESD: no domain detected."
311    
312     if domain.onMasterProcessor() and not os.path.isdir(dataDir):
313     os.mkdir(dataDir)
314    
315     meshFile = os.path.join(dataDir, datasetName+"_mesh")
316 caltinay 2599 fileNumber = timeStep / deltaT
317 caltinay 2526
318 caltinay 2599 if dynamicMesh == 0:
319     # later timesteps reuse mesh from t=0
320     if timeStep == 0:
321     domain.dump(meshFile + ".nc")
322     else:
323     meshFile += ".%04d"
324     domain.dump((meshFile + ".nc") % fileNumber)
325 caltinay 2526
326 caltinay 2188 outputString = ""
327 caltinay 2526
328 caltinay 2188 if domain.onMasterProcessor():
329     outputString += "#escript datafile V1.0\n"
330     # number of timesteps (currently only 1 is supported)
331 caltinay 2526 outputString += "T=%d\n" % (fileNumber+1)
332     # timestep increment
333     outputString += "DT=1\n"
334 caltinay 2188 # name of the mesh file
335     outputString += "M=%s\n" % meshFile
336     # number of blocks (MPI size)
337     outputString += "N=%d\n" % domain.getMPISize()
338    
339     # now add the variables
340     for varName, d in new_data.items():
341 caltinay 2526 varFile = os.path.join(dataDir, datasetName+"_"+varName+".%04d")
342     d.dump((varFile + ".nc") % fileNumber)
343 caltinay 2188 if domain.onMasterProcessor():
344     outputString += "V=%s:%s\n" % (varFile, varName)
345    
346     if domain.onMasterProcessor():
347     esdfile = open(datasetName+".esd", "w")
348     esdfile.write(outputString)
349     esdfile.close()
350    
351 gross 290 def kronecker(d=3):
352     """
353 jfenwick 2625 Returns the kronecker delta-symbol.
354 jgs 123
355 jfenwick 2625 :param d: dimension or an object that has the ``getDim`` method defining the
356 caltinay 2169 dimension
357 jfenwick 2625 :type d: ``int``, `escript.Domain` or `escript.FunctionSpace`
358     :return: the object u of rank 2 with *u[i,j]=1* for *i=j* and *u[i,j]=0*
359 caltinay 2169 otherwise
360 jfenwick 2625 :rtype: ``numpy.ndarray`` or `escript.Data` of rank 2
361 gross 290 """
362     return identityTensor(d)
363    
364     def identity(shape=()):
365     """
366 jfenwick 2625 Returns the ``shape`` x ``shape`` identity tensor.
367 gross 290
368 jfenwick 2625 :param shape: input shape for the identity tensor
369     :type shape: ``tuple`` of ``int``
370     :return: array whose shape is shape x shape where *u[i,k]=1* for *i=k* and
371     *u[i,k]=0* otherwise for len(shape)=1. If len(shape)=2:
372     *u[i,j,k,l]=1* for *i=k and j=l* and *u[i,j,k,l]=0* otherwise.
373     :rtype: ``numpy.ndarray`` of rank 1, rank 2 or rank 4
374     :raise ValueError: if len(shape)>2
375 gross 290 """
376     if len(shape)>0:
377 jfenwick 2455 out=numpy.zeros(shape+shape,numpy.float64)
378 gross 290 if len(shape)==1:
379     for i0 in range(shape[0]):
380     out[i0,i0]=1.
381     elif len(shape)==2:
382     for i0 in range(shape[0]):
383     for i1 in range(shape[1]):
384     out[i0,i1,i0,i1]=1.
385     else:
386     raise ValueError,"identity: length of shape is restricted to 2."
387     else:
388     out=1.
389     return out
390    
391     def identityTensor(d=3):
392     """
393 jfenwick 2625 Returns the ``d`` x ``d`` identity matrix.
394 gross 290
395 jfenwick 2625 :param d: dimension or an object that has the ``getDim`` method defining the
396 caltinay 2169 dimension
397 jfenwick 2625 :type d: ``int``, `escript.Domain` or `escript.FunctionSpace`
398     :return: the object u of rank 2 with *u[i,j]=1* for *i=j* and *u[i,j]=0*
399 caltinay 2169 otherwise
400 jfenwick 2625 :rtype: ``numpy.ndarray`` or `escript.Data` of rank 2
401 gross 290 """
402 gross 442 if isinstance(d,escript.FunctionSpace):
403     return escript.Data(identity((d.getDim(),)),d)
404     elif isinstance(d,escript.Domain):
405     return identity((d.getDim(),))
406     else:
407     return identity((d,))
408 gross 290
409     def identityTensor4(d=3):
410     """
411 jfenwick 2625 Returns the ``d`` x ``d`` x ``d`` x ``d`` identity tensor.
412 gross 290
413 jfenwick 2625 :param d: dimension or an object that has the ``getDim`` method defining the
414 caltinay 2169 dimension
415 jfenwick 2625 :type d: ``int`` or any object with a ``getDim`` method
416     :return: the object u of rank 4 with *u[i,j,k,l]=1* for *i=k and j=l* and
417     *u[i,j,k,l]=0* otherwise
418     :rtype: ``numpy.ndarray`` or `escript.Data` of rank 4
419 gross 290 """
420 gross 442 if isinstance(d,escript.FunctionSpace):
421     return escript.Data(identity((d.getDim(),d.getDim())),d)
422     elif isinstance(d,escript.Domain):
423     return identity((d.getDim(),d.getDim()))
424     else:
425     return identity((d,d))
426 gross 290
427     def unitVector(i=0,d=3):
428     """
429 caltinay 2169 Returns a unit vector u of dimension d whose non-zero element is at index i.
430 gross 290
431 jfenwick 2625 :param i: index for non-zero element
432     :type i: ``int``
433     :param d: dimension or an object that has the ``getDim`` method defining the
434 caltinay 2169 dimension
435 jfenwick 2625 :type d: ``int``, `escript.Domain` or `escript.FunctionSpace`
436     :return: the object u of rank 1 with *u[j]=1* for *j=index* and *u[j]=0*
437 caltinay 2169 otherwise
438 jfenwick 2625 :rtype: ``numpy.ndarray`` or `escript.Data` of rank 1
439 gross 290 """
440     return kronecker(d)[i]
441    
442     #=========================================================================
443     # global reduction operations (these functions have no symbolic version)
444     #=========================================================================
445     def Lsup(arg):
446 jgs 82 """
447 jfenwick 2625 Returns the Lsup-norm of argument ``arg``. This is the maximum absolute value
448     over all data points. This function is equivalent to ``sup(abs(arg))``.
449 jgs 149
450 jfenwick 2625 :param arg: argument
451     :type arg: ``float``, ``int``, `escript.Data`, ``numpy.ndarray``
452     :return: maximum value of the absolute value of ``arg`` over all components
453 caltinay 2169 and all data points
454 jfenwick 2625 :rtype: ``float``
455     :raise TypeError: if type of ``arg`` cannot be processed
456 jgs 123 """
457 jfenwick 2455 if isinstance(arg,numpy.ndarray):
458 gross 290 return sup(abs(arg))
459     elif isinstance(arg,escript.Data):
460     return arg._Lsup()
461     elif isinstance(arg,float):
462     return abs(arg)
463     elif isinstance(arg,int):
464     return abs(float(arg))
465 jgs 108 else:
466 gross 290 raise TypeError,"Lsup: Unknown argument type."
467 jgs 82
468 gross 290 def sup(arg):
469 jgs 82 """
470 caltinay 2169 Returns the maximum value over all data points.
471 jgs 149
472 jfenwick 2625 :param arg: argument
473     :type arg: ``float``, ``int``, `escript.Data`, ``numpy.ndarray``
474     :return: maximum value of ``arg`` over all components and all data points
475     :rtype: ``float``
476     :raise TypeError: if type of ``arg`` cannot be processed
477 jgs 123 """
478 jfenwick 2455 if isinstance(arg,numpy.ndarray):
479 gross 290 return arg.max()
480     elif isinstance(arg,escript.Data):
481     return arg._sup()
482     elif isinstance(arg,float):
483     return arg
484     elif isinstance(arg,int):
485     return float(arg)
486 jgs 123 else:
487 gross 290 raise TypeError,"sup: Unknown argument type."
488 jgs 82
489 gross 290 def inf(arg):
490 jgs 82 """
491 caltinay 2169 Returns the minimum value over all data points.
492 jgs 149
493 jfenwick 2625 :param arg: argument
494     :type arg: ``float``, ``int``, `escript.Data`, ``numpy.ndarray``
495     :return: minimum value of ``arg`` over all components and all data points
496     :rtype: ``float``
497     :raise TypeError: if type of ``arg`` cannot be processed
498 jgs 123 """
499 jfenwick 2455 if isinstance(arg,numpy.ndarray):
500 gross 290 return arg.min()
501     elif isinstance(arg,escript.Data):
502     return arg._inf()
503     elif isinstance(arg,float):
504     return arg
505     elif isinstance(arg,int):
506     return float(arg)
507 jgs 108 else:
508 gross 290 raise TypeError,"inf: Unknown argument type."
509 jgs 82
510 gross 290
511     #=========================================================================
512     # some little helpers
513     #=========================================================================
514 gross 912 def getRank(arg):
515 jgs 124 """
516 caltinay 2169 Identifies the rank of the argument.
517 gross 912
518 jfenwick 2625 :param arg: an object whose rank is to be returned
519     :type arg: ``numpy.ndarray``, `escript.Data`, ``float``, ``int``,
520     ``Symbol``
521     :return: the rank of the argument
522     :rtype: ``int``
523     :raise TypeError: if type of ``arg`` cannot be processed
524 gross 912 """
525    
526 jfenwick 2455 if isinstance(arg,numpy.ndarray):
527     return arg.ndim
528 gross 912 elif isinstance(arg,escript.Data):
529     return arg.getRank()
530     elif isinstance(arg,float):
531     return 0
532     elif isinstance(arg,int):
533     return 0
534     elif isinstance(arg,Symbol):
535     return arg.getRank()
536     else:
537 caltinay 2169 raise TypeError,"getRank: Unknown argument type."
538    
539 gross 912 def getShape(arg):
540     """
541 caltinay 2169 Identifies the shape of the argument.
542 jgs 149
543 jfenwick 2625 :param arg: an object whose shape is to be returned
544     :type arg: ``numpy.ndarray``, `escript.Data`, ``float``, ``int``,
545     ``Symbol``
546     :return: the shape of the argument
547     :rtype: ``tuple`` of ``int``
548     :raise TypeError: if type of ``arg`` cannot be processed
549 jgs 124 """
550 gross 290
551 jfenwick 2455 if isinstance(arg,numpy.ndarray):
552 gross 290 return arg.shape
553     elif isinstance(arg,escript.Data):
554     return arg.getShape()
555     elif isinstance(arg,float):
556     return ()
557     elif isinstance(arg,int):
558     return ()
559     elif isinstance(arg,Symbol):
560     return arg.getShape()
561 jgs 124 else:
562 caltinay 2169 raise TypeError,"getShape: Cannot identify shape"
563 jgs 124
564 gross 290 def pokeDim(arg):
565 jgs 82 """
566 caltinay 2169 Identifies the spatial dimension of the argument.
567 jgs 149
568 jfenwick 2625 :param arg: an object whose spatial dimension is to be returned
569     :type arg: any
570     :return: the spatial dimension of the argument, if available, or ``None``
571     :rtype: ``int`` or ``None``
572 jgs 123 """
573 gross 290
574     if isinstance(arg,escript.Data):
575     return arg.getFunctionSpace().getDim()
576     elif isinstance(arg,Symbol):
577     return arg.getDim()
578 jgs 123 else:
579 gross 290 return None
580 jgs 82
581 caltinay 2169 def commonShape(arg0, arg1):
582 jgs 82 """
583 jfenwick 2625 Returns a shape to which ``arg0`` can be extended from the right and ``arg1``
584 caltinay 2169 can be extended from the left.
585 jgs 149
586 jfenwick 2625 :param arg0: an object with a shape (see `getShape`)
587     :param arg1: an object with a shape (see `getShape`)
588     :return: the shape of ``arg0`` or ``arg1`` such that the left part equals the
589     shape of ``arg0`` and the right end equals the shape of ``arg1``
590     :rtype: ``tuple`` of ``int``
591     :raise ValueError: if no shape can be found
592 jgs 123 """
593 gross 912 sh0=getShape(arg0)
594     sh1=getShape(arg1)
595 gross 290 if len(sh0)<len(sh1):
596     if not sh0==sh1[:len(sh0)]:
597     raise ValueError,"argument 0 cannot be extended to the shape of argument 1"
598     return sh1
599     elif len(sh0)>len(sh1):
600     if not sh1==sh0[:len(sh1)]:
601     raise ValueError,"argument 1 cannot be extended to the shape of argument 0"
602     return sh0
603 jgs 82 else:
604 gross 290 if not sh0==sh1:
605     raise ValueError,"argument 1 and argument 0 have not the same shape."
606     return sh0
607 jgs 82
608 gross 290 def commonDim(*args):
609 jgs 82 """
610 caltinay 2169 Identifies, if possible, the spatial dimension across a set of objects
611     which may or may not have a spatial dimension.
612 jgs 149
613 jfenwick 2625 :param args: given objects
614     :return: the spatial dimension of the objects with identifiable dimension
615     (see `pokeDim`). If none of the objects has a spatial dimension
616     ``None`` is returned.
617     :rtype: ``int`` or ``None``
618     :raise ValueError: if the objects with identifiable dimension don't have
619 caltinay 2169 the same spatial dimension.
620 jgs 123 """
621 gross 290 out=None
622     for a in args:
623     d=pokeDim(a)
624     if not out==None:
625     if not (d==None or out==d):
626     raise ValueError,"dimension of arguments don't match"
627     else:
628     out=d
629     return out
630 jgs 82
631 gross 290 def testForZero(arg):
632 jgs 150 """
633 caltinay 2169 Tests if the argument is identical to zero.
634 jgs 123
635 jfenwick 2625 :param arg: the object to test for zero
636     :type arg: typically ``numpy.ndarray``, `escript.Data`, ``float``, ``int``
637     :return: True if the argument is identical to zero, False otherwise
638     :rtype: ``bool``
639 jgs 150 """
640 jfenwick 2455 if isinstance(arg,numpy.ndarray):
641 gross 290 return not Lsup(arg)>0.
642 gross 396 elif isinstance(arg,escript.Data):
643 gross 290 return False
644 gross 396 elif isinstance(arg,float):
645     return not Lsup(arg)>0.
646     elif isinstance(arg,int):
647     return not Lsup(arg)>0.
648     elif isinstance(arg,Symbol):
649     return False
650     else:
651     return False
652 jgs 150
653 gross 290 def matchType(arg0=0.,arg1=0.):
654 jgs 150 """
655 jfenwick 2625 Converts ``arg0`` and ``arg1`` both to the same type ``numpy.ndarray`` or
656     `escript.Data` or, if one of ``arg0`` or ``arg1`` is of type `Symbol`, the
657     other one to be of type ``numpy.ndarray`` or `escript.Data`.
658 jgs 150
659 jfenwick 2625 :param arg0: first argument
660     :type arg0: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, ``Symbol``
661     :param arg1: second argument
662     :type arg1: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, ``Symbol``
663     :return: a tuple representing ``arg0`` and ``arg1`` with the same type or
664     with one of them being a `Symbol`
665     :rtype: ``tuple`` of two ``numpy.ndarray``, two `escript.Data`,
666     a ``Symbol`` and one of the types ``numpy.ndarray`` or
667     `escript.Data`
668     :raise TypeError: if type of ``arg0`` or ``arg1`` cannot be processed
669 jgs 150 """
670 jfenwick 2455 if isinstance(arg0,numpy.ndarray):
671     if isinstance(arg1,numpy.ndarray):
672 gross 290 pass
673     elif isinstance(arg1,escript.Data):
674     arg0=escript.Data(arg0,arg1.getFunctionSpace())
675     elif isinstance(arg1,float):
676 jfenwick 2455 arg1=numpy.array(arg1,dtype=numpy.float64)
677 gross 290 elif isinstance(arg1,int):
678 jfenwick 2455 arg1=numpy.array(float(arg1),dtype=numpy.float64)
679 gross 290 elif isinstance(arg1,Symbol):
680     pass
681     else:
682 caltinay 2169 raise TypeError,"function: Unknown type of second argument."
683 gross 290 elif isinstance(arg0,escript.Data):
684 jfenwick 2455 if isinstance(arg1,numpy.ndarray):
685 gross 290 arg1=escript.Data(arg1,arg0.getFunctionSpace())
686     elif isinstance(arg1,escript.Data):
687     pass
688     elif isinstance(arg1,float):
689     arg1=escript.Data(arg1,(),arg0.getFunctionSpace())
690     elif isinstance(arg1,int):
691     arg1=escript.Data(float(arg1),(),arg0.getFunctionSpace())
692     elif isinstance(arg1,Symbol):
693     pass
694     else:
695 caltinay 2169 raise TypeError,"function: Unknown type of second argument."
696 gross 290 elif isinstance(arg0,Symbol):
697 jfenwick 2455 if isinstance(arg1,numpy.ndarray):
698 gross 290 pass
699     elif isinstance(arg1,escript.Data):
700     pass
701     elif isinstance(arg1,float):
702 jfenwick 2455 arg1=numpy.array(arg1,dtype=numpy.float64)
703 gross 290 elif isinstance(arg1,int):
704 jfenwick 2455 arg1=numpy.array(float(arg1),dtype=numpy.float64)
705 gross 290 elif isinstance(arg1,Symbol):
706     pass
707     else:
708 caltinay 2169 raise TypeError,"function: Unknown type of second argument."
709 gross 290 elif isinstance(arg0,float):
710 jfenwick 2455 if isinstance(arg1,numpy.ndarray):
711     arg0=numpy.array(arg0,dtype=numpy.float64)
712 gross 290 elif isinstance(arg1,escript.Data):
713     arg0=escript.Data(arg0,arg1.getFunctionSpace())
714     elif isinstance(arg1,float):
715 jfenwick 2455 arg0=numpy.array(arg0,dtype=numpy.float64)
716     arg1=numpy.array(arg1,dtype=numpy.float64)
717 gross 290 elif isinstance(arg1,int):
718 jfenwick 2455 arg0=numpy.array(arg0,dtype=numpy.float64)
719     arg1=numpy.array(float(arg1),dtype=numpy.float64)
720 gross 290 elif isinstance(arg1,Symbol):
721 jfenwick 2455 arg0=numpy.array(arg0,dtype=numpy.float64)
722 gross 290 else:
723 caltinay 2169 raise TypeError,"function: Unknown type of second argument."
724 gross 290 elif isinstance(arg0,int):
725 jfenwick 2455 if isinstance(arg1,numpy.ndarray):
726     arg0=numpy.array(float(arg0),dtype=numpy.float64)
727 gross 290 elif isinstance(arg1,escript.Data):
728     arg0=escript.Data(float(arg0),arg1.getFunctionSpace())
729     elif isinstance(arg1,float):
730 jfenwick 2455 arg0=numpy.array(float(arg0),dtype=numpy.float64)
731     arg1=numpy.array(arg1,dtype=numpy.float64)
732 gross 290 elif isinstance(arg1,int):
733 jfenwick 2455 arg0=numpy.array(float(arg0),dtype=numpy.float64)
734     arg1=numpy.array(float(arg1),dtype=numpy.float64)
735 gross 290 elif isinstance(arg1,Symbol):
736 jfenwick 2455 arg0=numpy.array(float(arg0),dtype=numpy.float64)
737 gross 290 else:
738 caltinay 2169 raise TypeError,"function: Unknown type of second argument."
739 jgs 150 else:
740 caltinay 2169 raise TypeError,"function: Unknown type of first argument."
741 jgs 150
742 gross 290 return arg0,arg1
743    
744     def matchShape(arg0,arg1):
745 jgs 150 """
746 jfenwick 2625 Returns a representation of ``arg0`` and ``arg1`` which have the same shape.
747 jgs 150
748 jfenwick 2625 :param arg0: first argument
749     :type arg0: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, `Symbol`
750     :param arg1: second argument
751     :type arg1: ``numpy.ndarray``,`escript.Data`,``float``, ``int``, `Symbol`
752     :return: ``arg0`` and ``arg1`` where copies are returned when the shape has
753 caltinay 2169 to be changed
754 jfenwick 2625 :rtype: ``tuple``
755 jgs 150 """
756 gross 290 sh=commonShape(arg0,arg1)
757 gross 912 sh0=getShape(arg0)
758     sh1=getShape(arg1)
759 gross 290 if len(sh0)<len(sh):
760 jfenwick 2455 return outer(arg0,numpy.ones(sh[len(sh0):],numpy.float64)),arg1
761 gross 290 elif len(sh1)<len(sh):
762 jfenwick 2455 return arg0,outer(arg1,numpy.ones(sh[len(sh1):],numpy.float64))
763 caltinay 2169 else:
764 gross 290 return arg0,arg1
765 caltinay 2169
766 gross 290 #=========================================================
767     # symbolic tool box starts here:
768     #=========================================================
769     class Symbol(object):
770     """
771 jfenwick 2625 Symbol class objects provide the same functionality as ``numpy.ndarray``
772     and `escript.Data` objects but they do not have a value and therefore
773 caltinay 2169 cannot be plotted or visualized. The main purpose is the possibility to
774     calculate derivatives with respect to other Symbols used to define a Symbol.
775 jgs 150
776 gross 290 """
777     def __init__(self,shape=(),args=[],dim=None):
778     """
779 caltinay 2169 Creates an instance of a symbol of a given shape. The symbol may depend
780 jfenwick 2625 on a list of arguments ``args`` which may be symbols or any other object.
781 gross 290
782 jfenwick 2625 :param args: the arguments of the symbol
783     :type args: ``list``
784     :param shape: the shape of the symbol
785     :type shape: ``tuple`` of ``int``
786     :param dim: spatial dimension of the symbol. If dim=``None`` the spatial
787 caltinay 2169 dimension is undefined.
788 jfenwick 2625 :type dim: ``None`` or ``int``
789 gross 290
790     """
791     if len(shape)>4:
792 caltinay 2169 raise ValueError,"Symbol only supports tensors up to order 4"
793 gross 290 self.__args=args
794     self.__shape=shape
795     self.__dim=dim
796    
797     def getArgument(self,i=None):
798     """
799 caltinay 2169 Returns the i-th argument of the symbol.
800 gross 290
801 jfenwick 2625 :param i: index of the argument requested
802     :type i: ``int`` or ``None``
803     :raise IndexError: if the requested index does not exist
804     :return: the value of the i-th argument or if i is not specified the
805 caltinay 2169 list of all arguments
806 jfenwick 2625 :rtype: a single object or a list of objects
807 gross 290 """
808     if i==None:
809     return self.__args
810     else:
811     if i<0 or i>=len(self.__args):
812     raise IndexError,"there are only %s arguments"%len(self.__args)
813     return self.__args[i]
814    
815     def getRank(self):
816     """
817 caltinay 2169 Returns the rank of the symbol.
818 gross 290
819 jfenwick 2625 :return: the rank of the symbol. This is length of the shape.
820     :rtype: ``int``
821 gross 290 """
822     return len(self.getShape())
823    
824     def getShape(self):
825     """
826 caltinay 2169 Returns the shape of the symbol.
827 gross 290
828 jfenwick 2625 :return: the shape of the symbol
829     :rtype: ``tuple`` of ``int``
830 gross 290 """
831     return self.__shape
832    
833     def getDim(self):
834     """
835 caltinay 2169 Returns the spatial dimension.
836 gross 290
837 jfenwick 2625 :return: the symbol's spatial dimension
838     :rtype: ``int`` if the dimension is defined, ``None`` otherwise
839 gross 290 """
840     return self.__dim
841 caltinay 2169
842 gross 290 def __str__(self):
843     """
844 caltinay 2169 Returns a string representation of the symbol.
845    
846 jfenwick 2625 :return: a string representation of the object
847     :rtype: ``str``
848 gross 290 """
849     args=[]
850     for arg in self.getArgument():
851     args.append(str(arg))
852     try:
853     out=self.getMyCode(args,format="str")
854     except NotImplementedError:
855     out="<Symbol %s>"%id(self)
856     return out
857 caltinay 2169
858 gross 290 def getSubstitutedArguments(self,argvals):
859     """
860 caltinay 2169 Substitutes symbols in the arguments of this object and returns the
861     result as a list.
862 gross 290
863 jfenwick 2625 :param argvals: `Symbol` and their substitutes. The `Symbol` u in the
864 caltinay 2169 expression defining this object is replaced by
865     argvals[u].
866 jfenwick 2625 :type argvals: ``dict`` with keywords of type `Symbol`
867     :rtype: ``list`` of objects
868     :return: list of the object assigned to the arguments through
869     substitution or for the arguments which are not `Symbol` s the
870 caltinay 2169 value assigned to the argument at instantiation.
871 gross 290 """
872     out=[]
873     for a in self.getArgument():
874     if isinstance(a,Symbol):
875     out.append(a.substitute(argvals))
876     else:
877     out.append(a)
878     return out
879    
880     def getDifferentiatedArguments(self,arg):
881     """
882 caltinay 2169 Applies differentials to the arguments of this object and returns the
883     result as a list.
884 gross 290
885 jfenwick 2625 :param arg: the derivative is calculated with respect to ``arg``
886     :type arg: typically `escript.Symbol` but can also be ``float``,
887     `escript.Data`, ``numpy.ndarray`` depending on the
888 caltinay 2169 involved functions and data
889 jfenwick 2625 :rtype: ``list`` of objects
890     :return: list of object obtained by calculating the derivatives of the
891     arguments with respect to ``arg``
892 gross 290 """
893     out=[]
894     for a in self.getArgument():
895     if isinstance(a,Symbol):
896     out.append(a.substitute(argvals))
897     else:
898 gross 912 s=getShape(s)+arg.getShape()
899 gross 290 if len(s)>0:
900 jfenwick 2455 out.append(numpy.zeros(s),numpy.float64)
901 gross 290 else:
902     out.append(a)
903     return out
904    
905     def isAppropriateValue(self,arg):
906     """
907 jfenwick 2625 Checks if the given argument ``arg`` can be used as a substitution for
908     this object. The method checks the shape of ``arg`` and, if the spatial
909     dimension is defined, the spatial dimension of ``arg``.
910 gross 290
911 jfenwick 2625 :param arg: object to be checked
912     :type arg: ``numpy.ndarray``, `escript.Data`, ``float``, ``int``,
913     ``Symbol``
914     :return: True if ``arg`` is a suitable object to be used for substitution,
915 caltinay 2169 False otherwise
916 jfenwick 2625 :rtype: ``bool``
917 gross 290 """
918 jfenwick 2455 if isinstance(arg,numpy.ndarray):
919 gross 290 return arg.shape==self.getShape()
920     elif isinstance(arg,escript.Data):
921     if self.getDim()==None:
922     return arg.getShape()==self.getShape()
923     elif self.getDim()==arg.getFunctionSpace().getDim():
924     return arg.getShape()==self.getShape()
925     else:
926     return False
927     elif isinstance(arg,Symbol):
928     if self.getDim()==None:
929     return arg.getShape()==self.getShape()
930     elif self.getDim()==arg.getDim():
931     return arg.getShape()==self.getShape()
932     else:
933     return False
934     elif isinstance(arg,float):
935     return ()==self.getShape()
936     elif isinstance(arg,int):
937     return ()==self.getShape()
938     else:
939     return False
940    
941     def getMyCode(self,argstrs,format="escript"):
942     """
943 caltinay 2169 Returns program code that can be used to evaluate the symbol.
944 gross 290
945 jfenwick 2625 :param argstrs: a string for each argument representing the argument
946 caltinay 2169 for the evaluation
947 jfenwick 2625 :type argstrs: ``list`` of ``str``
948     :param format: specifies the format to be used. At the moment only
949 caltinay 2169 "escript", "str" and "text" are supported.
950 jfenwick 2625 :type format: ``str``
951     :return: a piece of program code which can be used to evaluate the
952 caltinay 2169 expression assuming the values for the arguments are available
953 jfenwick 2625 :rtype: ``str``
954     :raise NotImplementedError: if no implementation for the given format
955 caltinay 2169 is available
956 jfenwick 2625 :note: This method has to be overwritten by subclasses.
957 gross 290 """
958     raise NotImplementedError,"no code for %s representation available"%format
959    
960     def substitute(self,argvals):
961 caltinay 2169 """
962     Assigns new values to symbols in the definition of the symbol.
963 gross 290
964 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
965 caltinay 2169 defining this object.
966    
967 jfenwick 2625 :param argvals: new values assigned to symbols
968     :type argvals: ``dict`` with keywords of type `Symbol`
969     :return: result of the substitution process. Operations are executed as
970 caltinay 2169 much as possible.
971 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
972 caltinay 2169 depending on the degree of substitution
973 jfenwick 2625 :note: this method has to be overwritten by a particular `Symbol`
974     :raise NotImplementedError: if no implementation for the given format is
975 caltinay 2169 available
976 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
977 gross 290 """
978     if argvals.has_key(self):
979     arg=argvals[self]
980     if self.isAppropriateValue(arg):
981     return arg
982     else:
983     raise TypeError,"Symbol: new value is not appropriate."
984     else:
985     raise NotImplementedError,"no substitution in %s avialable"%str(self)
986    
987     def diff(self,arg):
988     """
989 jfenwick 2625 Returns the derivative of the symbol with respect to `Symbol` ``arg``.
990 gross 290
991 jfenwick 2625 :param arg: the derivative is calculated with respect to ``arg``
992     :type arg: typically `escript.Symbol` but can also be ``float``,
993     `escript.Data`, ``numpy.ndarray`` depending on the
994 caltinay 2169 involved functions and data
995 jfenwick 2625 :return: derivative with respect to ``arg``
996     :rtype: typically `escript.Symbol` but other types such as ``float``,
997     `escript.Data`, ``numpy.ndarray`` are possible
998     :note: this method is overwritten by a particular `Symbol`.
999 gross 290 """
1000     if arg==self:
1001     return identity(self.getShape())
1002     else:
1003     s=self.getShape()+arg.getShape()
1004     if len(s)>0:
1005 jfenwick 2455 return numpy.zeros(s,numpy.float64)
1006 gross 290 else:
1007     return 0.
1008    
1009     def __neg__(self):
1010     """
1011 caltinay 2169 Returns -self.
1012 gross 290
1013 jfenwick 2625 :return: a `Symbol` representing the negative of the object
1014     :rtype: `DependendSymbol`
1015 gross 290 """
1016     return self*(-1.)
1017    
1018     def __pos__(self):
1019     """
1020 caltinay 2169 Returns +self.
1021 gross 290
1022 jfenwick 2625 :return: a `Symbol` representing the positive of the object
1023     :rtype: `DependendSymbol`
1024 gross 290 """
1025     return self*(1.)
1026    
1027     def __abs__(self):
1028     """
1029 jfenwick 2625 Returns a `Symbol` representing the absolute value of the object.
1030 gross 290 """
1031     return Abs_Symbol(self)
1032    
1033     def __add__(self,other):
1034     """
1035 caltinay 2169 Adds another object to this object.
1036 gross 290
1037 jfenwick 2625 :param other: object to be added to this object
1038     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1039     ``numpy.ndarray``.
1040     :return: a `Symbol` representing the sum of this object and ``other``
1041     :rtype: `DependendSymbol`
1042 gross 290 """
1043     return add(self,other)
1044    
1045     def __radd__(self,other):
1046     """
1047 caltinay 2169 Adds this object to another object.
1048 gross 290
1049 jfenwick 2625 :param other: object to add this object to
1050     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1051     ``numpy.ndarray``
1052     :return: a `Symbol` representing the sum of ``other`` and this object
1053     :rtype: `DependendSymbol`
1054 gross 290 """
1055     return add(other,self)
1056    
1057     def __sub__(self,other):
1058     """
1059 caltinay 2169 Subtracts another object from this object.
1060 gross 290
1061 jfenwick 2625 :param other: object to be subtracted from this object
1062     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1063     ``numpy.ndarray``
1064     :return: a `Symbol` representing the difference of ``other`` and this
1065 caltinay 2169 object
1066 jfenwick 2625 :rtype: `DependendSymbol`
1067 gross 290 """
1068     return add(self,-other)
1069    
1070     def __rsub__(self,other):
1071     """
1072 caltinay 2169 Subtracts this object from another object.
1073 gross 290
1074 jfenwick 2625 :param other: object this object is to be subtracted from
1075     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1076     ``numpy.ndarray``
1077     :return: a `Symbol` representing the difference of this object and
1078     ``other``.
1079     :rtype: `DependendSymbol`
1080 gross 290 """
1081     return add(-self,other)
1082    
1083     def __mul__(self,other):
1084     """
1085 caltinay 2169 Multiplies this object with another object.
1086 gross 290
1087 jfenwick 2625 :param other: object to be mutiplied by this object
1088     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1089     ``numpy.ndarray``
1090     :return: a `Symbol` representing the product of the object and ``other``
1091     :rtype: `DependendSymbol` or 0 if other is identical to zero.
1092 gross 290 """
1093     return mult(self,other)
1094    
1095     def __rmul__(self,other):
1096     """
1097 caltinay 2169 Multiplies another object by this object.
1098 gross 290
1099 jfenwick 2625 :param other: object this object is multiplied with
1100     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1101     ``numpy.ndarray``
1102     :return: a `Symbol` representing the product of ``other`` and the object
1103     :rtype: `DependendSymbol` or 0 if other is identical to zero
1104 gross 290 """
1105     return mult(other,self)
1106    
1107     def __div__(self,other):
1108     """
1109 caltinay 2169 Divides this object by another object.
1110 gross 290
1111 jfenwick 2625 :param other: object dividing this object
1112     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1113     ``numpy.ndarray``
1114     :return: a `Symbol` representing the quotient of this object and
1115     ``other``
1116     :rtype: `DependendSymbol`
1117 gross 290 """
1118     return quotient(self,other)
1119    
1120     def __rdiv__(self,other):
1121     """
1122 caltinay 2169 Divides another object by this object.
1123 gross 290
1124 jfenwick 2625 :param other: object to be divided by this object
1125     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1126     ``numpy.ndarray``
1127     :return: a `Symbol` representing the quotient of ``other`` and this
1128 caltinay 2169 object
1129 jfenwick 2625 :rtype: `DependendSymbol` or 0 if ``other`` is identical to zero
1130 gross 290 """
1131     return quotient(other,self)
1132    
1133     def __pow__(self,other):
1134     """
1135 jfenwick 2625 Raises this object to the power of ``other``.
1136 gross 290
1137 jfenwick 2625 :param other: exponent
1138     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1139     ``numpy.ndarray``
1140     :return: a `Symbol` representing the power of this object to ``other``
1141     :rtype: `DependendSymbol` or 1 if ``other`` is identical to zero
1142 gross 290 """
1143     return power(self,other)
1144    
1145     def __rpow__(self,other):
1146     """
1147 caltinay 2169 Raises an object to the power of this object.
1148 gross 290
1149 jfenwick 2625 :param other: basis
1150     :type other: `escript.Symbol`, ``float``, `escript.Data`,
1151     ``numpy.ndarray``
1152     :return: a `Symbol` representing the power of ``other`` to this object
1153     :rtype: `DependendSymbol` or 0 if ``other`` is identical to zero
1154 gross 290 """
1155     return power(other,self)
1156    
1157 gross 517 def __getitem__(self,index):
1158     """
1159 jfenwick 2625 Returns the slice defined by ``index``.
1160 gross 517
1161 jfenwick 2625 :param index: the slice index
1162     :type index: ``slice`` or ``int`` or a ``tuple`` of them
1163     :return: a `Symbol` representing the slice defined by index
1164     :rtype: `DependendSymbol`
1165 gross 517 """
1166     return GetSlice_Symbol(self,index)
1167    
1168 gross 290 class DependendSymbol(Symbol):
1169     """
1170 jfenwick 2625 DependendSymbol extents `Symbol` by modifying the == operator to allow two
1171     instances to be equal. Two ``DependendSymbol`` s are equal if they have the
1172 caltinay 2169 same shape, the same arguments and one of them has an unspecified spatial
1173     dimension or the spatial dimension is identical.
1174    
1175 gross 720 Example::
1176 caltinay 2169
1177 gross 720 u1=Symbol(shape=(3,4),dim=2,args=[4.])
1178     u2=Symbol(shape=(3,4),dim=2,args=[4.])
1179     print u1==u2
1180     False
1181 caltinay 2169
1182 gross 720 but::
1183 gross 290
1184 gross 720 u1=DependendSymbol(shape=(3,4),dim=2,args=[4.])
1185     u2=DependendSymbol(shape=(3,4),dim=2,args=[4.])
1186 caltinay 2169 u3=DependendSymbol(shape=(2,),dim=2,args=[4.])
1187 gross 720 print u1==u2, u1==u3
1188     True False
1189 gross 290
1190 jfenwick 2625 :note: DependendSymbol should be used as return value of functions with
1191     `Symbol` arguments. This will allow the optimizer to remove
1192 caltinay 2169 redundant function calls.
1193 gross 290 """
1194     def __eq__(self,other):
1195     """
1196 jfenwick 2625 Checks if ``other`` equals self.
1197 gross 290
1198 jfenwick 2625 :param other: any object
1199     :return: True if other has the same class as self and the shape, the
1200 caltinay 2169 spatial dimension and the arguments are equal, False otherwise
1201 jfenwick 2625 :rtype: ``bool``
1202 gross 290 """
1203     if isinstance(other,DependendSymbol):
1204 caltinay 2169 if self.__class__==other.__class__:
1205 gross 290 if self.getShape()==other.getShape():
1206 caltinay 2169 if self.getArgument()==other.getArgument():
1207     if self.getDim()==None or other.getDim()==None or self.getDim()==other.getDim():
1208     return True
1209 gross 290 return False
1210    
1211     def __ne__(self,other):
1212     """
1213 jfenwick 2625 Checks if ``other`` is not equal to self.
1214 gross 290
1215 jfenwick 2625 :param other: any object
1216     :return: False if other has the same class as self and the shape, the
1217 caltinay 2169 spatial dimension and the arguments are equal, True otherwise
1218 jfenwick 2625 :rtype: ``bool``
1219 gross 290 """
1220     return not self==other
1221     #=========================================================
1222 caltinay 2169 # Unary operations preserving the shape
1223 gross 290 #========================================================
1224 gross 517 class GetSlice_Symbol(DependendSymbol):
1225     """
1226 jfenwick 2625 `Symbol` representing getting a slice for a `Symbol`.
1227 gross 517 """
1228     def __init__(self,arg,index):
1229     """
1230 jfenwick 2625 Initialization of the `Symbol` with argument ``arg``.
1231 caltinay 2169
1232 jfenwick 2625 :param arg: argument
1233     :type arg: `Symbol`
1234     :param index: defines index
1235     :type index: ``slice`` or ``int`` or a ``tuple`` of them
1236     :raise IndexError: if length of index is larger than rank of arg or
1237 caltinay 2169 index start or stop is out of range
1238 jfenwick 2625 :raise ValueError: if a step is given
1239 gross 517 """
1240     if not isinstance(index,tuple): index=(index,)
1241     if len(index)>arg.getRank():
1242     raise IndexError,"GetSlice_Symbol: index out of range."
1243     sh=()
1244     index2=()
1245     for i in range(len(index)):
1246     ix=index[i]
1247     if isinstance(ix,int):
1248     if ix<0 or ix>=arg.getShape()[i]:
1249 caltinay 2169 raise IndexError,"GetSlice_Symbol: index out of range."
1250 gross 517 index2=index2+(ix,)
1251     else:
1252     if not ix.step==None:
1253 caltinay 2169 raise ValueError,"GetSlice_Symbol: stepping is not supported."
1254 gross 517 if ix.start==None:
1255     s=0
1256     else:
1257     s=ix.start
1258     if ix.stop==None:
1259     e=arg.getShape()[i]
1260     else:
1261     e=ix.stop
1262     if e>arg.getShape()[i]:
1263     raise IndexError,"GetSlice_Symbol: index out of range."
1264     index2=index2+(slice(s,e),)
1265     if e>s:
1266     sh=sh+(e-s,)
1267     elif s>e:
1268     raise IndexError,"GetSlice_Symbol: slice start must be less or equal slice end"
1269     for i in range(len(index),arg.getRank()):
1270     index2=index2+(slice(0,arg.getShape()[i]),)
1271     sh=sh+(arg.getShape()[i],)
1272     super(GetSlice_Symbol, self).__init__(args=[arg,index2],shape=sh,dim=arg.getDim())
1273    
1274     def getMyCode(self,argstrs,format="escript"):
1275     """
1276 caltinay 2169 Returns program code that can be used to evaluate the symbol.
1277 gross 517
1278 jfenwick 2625 :param argstrs: a string for each argument representing the argument
1279 caltinay 2169 for the evaluation
1280 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1281     :param format: specifies the format to be used. At the moment only
1282 caltinay 2169 "escript", "str" and "text" are supported.
1283 jfenwick 2625 :type format: ``str``
1284     :return: a piece of program code which can be used to evaluate the
1285 caltinay 2169 expression assuming the values for the arguments are available
1286 jfenwick 2625 :rtype: ``str``
1287     :raise NotImplementedError: if no implementation for the given format
1288 caltinay 2169 is available
1289 gross 517 """
1290     if format=="escript" or format=="str" or format=="text":
1291     return "%s.__getitem__(%s)"%(argstrs[0],argstrs[1])
1292     else:
1293     raise NotImplementedError,"GetItem_Symbol does not provide program code for format %s."%format
1294    
1295     def substitute(self,argvals):
1296     """
1297 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
1298 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
1299 caltinay 2169 defining this object.
1300 gross 517
1301 jfenwick 2625 :param argvals: new values assigned to symbols
1302     :type argvals: ``dict`` with keywords of type `Symbol`
1303     :return: result of the substitution process. Operations are executed as
1304 caltinay 2169 much as possible.
1305 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1306 caltinay 2169 depending on the degree of substitution
1307 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
1308 gross 517 """
1309     if argvals.has_key(self):
1310     arg=argvals[self]
1311     if self.isAppropriateValue(arg):
1312     return arg
1313     else:
1314     raise TypeError,"%s: new value is not appropriate."%str(self)
1315     else:
1316     args=self.getSubstitutedArguments(argvals)
1317     arg=args[0]
1318     index=args[1]
1319     return arg.__getitem__(index)
1320    
1321 gross 290 def log10(arg):
1322     """
1323 jfenwick 2625 Returns base-10 logarithm of argument ``arg``.
1324 gross 290
1325 jfenwick 2625 :param arg: argument
1326     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1327     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1328     on the type of ``arg``
1329     :raise TypeError: if the type of the argument is not expected
1330 gross 290 """
1331 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1332     return numpy.log10(arg)
1333 gross 290 elif isinstance(arg,escript.Data):
1334     return arg._log10()
1335     elif isinstance(arg,float):
1336     return math.log10(arg)
1337     elif isinstance(arg,int):
1338     return math.log10(float(arg))
1339     elif isinstance(arg,Symbol):
1340     return log(arg)/log(10.)
1341     else:
1342     raise TypeError,"log10: Unknown argument type."
1343    
1344     def wherePositive(arg):
1345     """
1346 jfenwick 2625 Returns mask of positive values of argument ``arg``.
1347 gross 290
1348 jfenwick 2625 :param arg: argument
1349     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1350     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1351     on the type of ``arg``
1352     :raise TypeError: if the type of the argument is not expected
1353 gross 290 """
1354 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1355     out=numpy.greater(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1356     if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1357 gross 396 return out
1358 gross 290 elif isinstance(arg,escript.Data):
1359     return arg._wherePositive()
1360     elif isinstance(arg,float):
1361     if arg>0:
1362     return 1.
1363     else:
1364     return 0.
1365     elif isinstance(arg,int):
1366     if arg>0:
1367     return 1.
1368     else:
1369     return 0.
1370     elif isinstance(arg,Symbol):
1371     return WherePositive_Symbol(arg)
1372     else:
1373     raise TypeError,"wherePositive: Unknown argument type."
1374    
1375     class WherePositive_Symbol(DependendSymbol):
1376     """
1377 jfenwick 2625 `Symbol` representing the result of the mask of positive values function.
1378 gross 290 """
1379     def __init__(self,arg):
1380     """
1381 jfenwick 2625 Initialization of wherePositive `Symbol` with argument ``arg``.
1382 caltinay 2169
1383 jfenwick 2625 :param arg: argument of function
1384     :type arg: typically `Symbol`
1385 gross 290 """
1386     DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1387    
1388     def getMyCode(self,argstrs,format="escript"):
1389     """
1390 caltinay 2169 Returns program code that can be used to evaluate the symbol.
1391 gross 290
1392 jfenwick 2625 :param argstrs: a string for each argument representing the argument
1393 caltinay 2169 for the evaluation
1394 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1395     :param format: specifies the format to be used. At the moment only
1396 caltinay 2169 "escript", "str" and "text" are supported.
1397 jfenwick 2625 :type format: ``str``
1398     :return: a piece of program code which can be used to evaluate the
1399 caltinay 2169 expression assuming the values for the arguments are available
1400 jfenwick 2625 :rtype: ``str``
1401     :raise NotImplementedError: if no implementation for the given format
1402 caltinay 2169 is available
1403 gross 290 """
1404     if isinstance(argstrs,list):
1405     argstrs=argstrs[0]
1406     if format=="escript" or format=="str" or format=="text":
1407     return "wherePositive(%s)"%argstrs
1408     else:
1409     raise NotImplementedError,"WherePositive_Symbol does not provide program code for format %s."%format
1410    
1411     def substitute(self,argvals):
1412     """
1413 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
1414 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
1415 caltinay 2169 defining this object.
1416 gross 290
1417 jfenwick 2625 :param argvals: new values assigned to symbols
1418     :type argvals: ``dict`` with keywords of type `Symbol`
1419     :return: result of the substitution process. Operations are executed as
1420 caltinay 2169 much as possible.
1421 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1422 caltinay 2169 depending on the degree of substitution
1423 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
1424 gross 290 """
1425     if argvals.has_key(self):
1426     arg=argvals[self]
1427     if self.isAppropriateValue(arg):
1428     return arg
1429     else:
1430     raise TypeError,"%s: new value is not appropriate."%str(self)
1431     else:
1432     arg=self.getSubstitutedArguments(argvals)[0]
1433     return wherePositive(arg)
1434    
1435     def whereNegative(arg):
1436     """
1437 jfenwick 2625 Returns mask of negative values of argument ``arg``.
1438 gross 290
1439 jfenwick 2625 :param arg: argument
1440     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1441     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1442     on the type of ``arg``
1443     :raise TypeError: if the type of the argument is not expected
1444 gross 290 """
1445 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1446     out=numpy.less(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1447     if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1448 gross 396 return out
1449 gross 290 elif isinstance(arg,escript.Data):
1450     return arg._whereNegative()
1451     elif isinstance(arg,float):
1452     if arg<0:
1453     return 1.
1454     else:
1455     return 0.
1456     elif isinstance(arg,int):
1457     if arg<0:
1458     return 1.
1459     else:
1460     return 0.
1461     elif isinstance(arg,Symbol):
1462     return WhereNegative_Symbol(arg)
1463     else:
1464     raise TypeError,"whereNegative: Unknown argument type."
1465    
1466     class WhereNegative_Symbol(DependendSymbol):
1467     """
1468 jfenwick 2625 `Symbol` representing the result of the mask of negative values function.
1469 gross 290 """
1470     def __init__(self,arg):
1471     """
1472 jfenwick 2625 Initialization of whereNegative `Symbol` with argument ``arg``.
1473 caltinay 2169
1474 jfenwick 2625 :param arg: argument of function
1475     :type arg: typically `Symbol`
1476 gross 290 """
1477     DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1478    
1479     def getMyCode(self,argstrs,format="escript"):
1480     """
1481 caltinay 2169 Returns program code that can be used to evaluate the symbol.
1482 gross 290
1483 jfenwick 2625 :param argstrs: a string for each argument representing the argument
1484 caltinay 2169 for the evaluation
1485 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1486     :param format: specifies the format to be used. At the moment only
1487 caltinay 2169 "escript", "str" and "text" are supported.
1488 jfenwick 2625 :type format: ``str``
1489     :return: a piece of program code which can be used to evaluate the
1490 caltinay 2169 expression assuming the values for the arguments are available
1491 jfenwick 2625 :rtype: ``str``
1492     :raise NotImplementedError: if no implementation for the given format
1493 caltinay 2169 is available
1494 gross 290 """
1495     if isinstance(argstrs,list):
1496     argstrs=argstrs[0]
1497     if format=="escript" or format=="str" or format=="text":
1498     return "whereNegative(%s)"%argstrs
1499     else:
1500     raise NotImplementedError,"WhereNegative_Symbol does not provide program code for format %s."%format
1501    
1502     def substitute(self,argvals):
1503     """
1504 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
1505 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
1506 caltinay 2169 defining this object.
1507 gross 290
1508 jfenwick 2625 :param argvals: new values assigned to symbols
1509     :type argvals: ``dict`` with keywords of type `Symbol`
1510     :return: result of the substitution process. Operations are executed as
1511 caltinay 2169 much as possible.
1512 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1513 caltinay 2169 depending on the degree of substitution
1514 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
1515 gross 290 """
1516     if argvals.has_key(self):
1517     arg=argvals[self]
1518     if self.isAppropriateValue(arg):
1519     return arg
1520     else:
1521     raise TypeError,"%s: new value is not appropriate."%str(self)
1522     else:
1523     arg=self.getSubstitutedArguments(argvals)[0]
1524     return whereNegative(arg)
1525    
1526     def whereNonNegative(arg):
1527     """
1528 jfenwick 2625 Returns mask of non-negative values of argument ``arg``.
1529 gross 290
1530 jfenwick 2625 :param arg: argument
1531     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1532     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1533     on the type of ``arg``
1534     :raise TypeError: if the type of the argument is not expected
1535 gross 290 """
1536 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1537     out=numpy.greater_equal(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1538     if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1539 gross 396 return out
1540 gross 290 elif isinstance(arg,escript.Data):
1541     return arg._whereNonNegative()
1542     elif isinstance(arg,float):
1543     if arg<0:
1544     return 0.
1545     else:
1546     return 1.
1547     elif isinstance(arg,int):
1548     if arg<0:
1549     return 0.
1550     else:
1551     return 1.
1552     elif isinstance(arg,Symbol):
1553     return 1.-whereNegative(arg)
1554     else:
1555     raise TypeError,"whereNonNegative: Unknown argument type."
1556    
1557     def whereNonPositive(arg):
1558     """
1559 jfenwick 2625 Returns mask of non-positive values of argument ``arg``.
1560 gross 290
1561 jfenwick 2625 :param arg: argument
1562     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1563     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1564     on the type of ``arg``
1565     :raise TypeError: if the type of the argument is not expected
1566 gross 290 """
1567 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1568     out=numpy.less_equal(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1569     if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1570 gross 396 return out
1571 gross 290 elif isinstance(arg,escript.Data):
1572     return arg._whereNonPositive()
1573     elif isinstance(arg,float):
1574     if arg>0:
1575     return 0.
1576     else:
1577     return 1.
1578     elif isinstance(arg,int):
1579     if arg>0:
1580     return 0.
1581     else:
1582     return 1.
1583     elif isinstance(arg,Symbol):
1584     return 1.-wherePositive(arg)
1585     else:
1586     raise TypeError,"whereNonPositive: Unknown argument type."
1587    
1588 gross 2304 def whereZero(arg,tol=None,adaptTol=True,rtol=math.sqrt(EPSILON)):
1589 gross 290 """
1590 jfenwick 2625 Returns mask of zero entries of argument ``arg``.
1591 gross 290
1592 jfenwick 2625 :param arg: argument
1593     :type arg: ``float``, `escript.Data` , `Symbol` , ``numpy.ndarray``
1594     :param tol: absolute tolerance. Values with absolute value less than tol are accepted
1595     as zero. If ``tol`` is not present ``rtol``*```Lsup` (arg)`` is used.
1596     :type tol: ``float``
1597     :param rtol: relative tolerance used to define the absolute tolerance if ``tol`` is not present.
1598     :type rtol: non-negative ``float``
1599     :rtype: ``float``, `escript.Data` , `Symbol` , ``numpy.ndarray`` depending
1600     on the type of ``arg``
1601     :raise ValueError: if ``rtol`` is non-negative.
1602     :raise TypeError: if the type of the argument is not expected
1603 gross 290 """
1604 gross 2304 if tol == None:
1605     if not isinstance(arg,Symbol):
1606     if rtol<=0: raise ValueError,"rtol must be non-negative."
1607     tol = Lsup(arg)*rtol
1608     else:
1609     tol=0.
1610 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1611     out=numpy.less_equal(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.
1612     if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1613 gross 396 return out
1614 gross 290 elif isinstance(arg,escript.Data):
1615 gross 698 return arg._whereZero(tol)
1616 gross 290 elif isinstance(arg,float):
1617     if abs(arg)<=tol:
1618     return 1.
1619     else:
1620     return 0.
1621     elif isinstance(arg,int):
1622     if abs(float(arg))<=tol:
1623     return 1.
1624     else:
1625     return 0.
1626     elif isinstance(arg,Symbol):
1627     return WhereZero_Symbol(arg,tol)
1628     else:
1629     raise TypeError,"whereZero: Unknown argument type."
1630    
1631     class WhereZero_Symbol(DependendSymbol):
1632     """
1633 jfenwick 2625 `Symbol` representing the result of the mask of zero entries function.
1634 gross 290 """
1635     def __init__(self,arg,tol=0.):
1636     """
1637 jfenwick 2625 Initialization of whereZero `Symbol` with argument ``arg``.
1638 caltinay 2169
1639 jfenwick 2625 :param arg: argument of function
1640     :type arg: typically `Symbol`
1641 gross 290 """
1642     DependendSymbol.__init__(self,args=[arg,tol],shape=arg.getShape(),dim=arg.getDim())
1643    
1644     def getMyCode(self,argstrs,format="escript"):
1645     """
1646 caltinay 2169 Returns program code that can be used to evaluate the symbol.
1647 gross 290
1648 jfenwick 2625 :param argstrs: a string for each argument representing the argument
1649 caltinay 2169 for the evaluation
1650 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1651     :param format: specifies the format to be used. At the moment only
1652 caltinay 2169 "escript", "str" and "text" are supported.
1653 jfenwick 2625 :type format: ``str``
1654     :return: a piece of program code which can be used to evaluate the
1655 caltinay 2169 expression assuming the values for the arguments are available
1656 jfenwick 2625 :rtype: ``str``
1657     :raise NotImplementedError: if no implementation for the given format
1658 caltinay 2169 is available
1659 gross 290 """
1660     if format=="escript" or format=="str" or format=="text":
1661     return "whereZero(%s,tol=%s)"%(argstrs[0],argstrs[1])
1662     else:
1663     raise NotImplementedError,"WhereZero_Symbol does not provide program code for format %s."%format
1664    
1665     def substitute(self,argvals):
1666     """
1667 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
1668 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
1669 caltinay 2169 defining this object.
1670 gross 290
1671 jfenwick 2625 :param argvals: new values assigned to symbols
1672     :type argvals: ``dict`` with keywords of type `Symbol`
1673     :return: result of the substitution process. Operations are executed as
1674 caltinay 2169 much as possible.
1675 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1676 caltinay 2169 depending on the degree of substitution
1677 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
1678 gross 290 """
1679     if argvals.has_key(self):
1680     arg=argvals[self]
1681     if self.isAppropriateValue(arg):
1682     return arg
1683     else:
1684     raise TypeError,"%s: new value is not appropriate."%str(self)
1685     else:
1686     arg=self.getSubstitutedArguments(argvals)
1687     return whereZero(arg[0],arg[1])
1688    
1689     def whereNonZero(arg,tol=0.):
1690     """
1691 jfenwick 2625 Returns mask of values different from zero of argument ``arg``.
1692 gross 290
1693 jfenwick 2625 :param arg: argument
1694     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1695     :param tol: absolute tolerance. Values with absolute value less than tol are accepted
1696     as zero. If ``tol`` is not present ``rtol``*```Lsup` (arg)`` is used.
1697     :type tol: ``float``
1698     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1699     on the type of ``arg``
1700     :raise ValueError: if ``rtol`` is non-negative.
1701     :raise TypeError: if the type of the argument is not expected
1702 gross 290 """
1703 gross 2304 if tol == None:
1704     if not isinstance(arg,Symbol):
1705     if rtol<=0: raise ValueError,"rtol must be non-negative."
1706     tol = Lsup(arg)*rtol
1707     else:
1708     tol=0.
1709 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1710     out=numpy.greater(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.
1711     if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1712 gross 396 return out
1713 gross 290 elif isinstance(arg,escript.Data):
1714 gross 698 return arg._whereNonZero(tol)
1715 gross 290 elif isinstance(arg,float):
1716     if abs(arg)>tol:
1717     return 1.
1718     else:
1719     return 0.
1720     elif isinstance(arg,int):
1721     if abs(float(arg))>tol:
1722     return 1.
1723     else:
1724     return 0.
1725     elif isinstance(arg,Symbol):
1726     return 1.-whereZero(arg,tol)
1727     else:
1728     raise TypeError,"whereNonZero: Unknown argument type."
1729    
1730 ksteube 876 def erf(arg):
1731     """
1732 jfenwick 2625 Returns the error function *erf* of argument ``arg``.
1733 ksteube 876
1734 jfenwick 2625 :param arg: argument
1735     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1736     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1737     on the type of ``arg``
1738     :raise TypeError: if the type of the argument is not expected
1739 ksteube 876 """
1740     if isinstance(arg,escript.Data):
1741     return arg._erf()
1742     else:
1743     raise TypeError,"erf: Unknown argument type."
1744    
1745 gross 290 def sin(arg):
1746     """
1747 jfenwick 2625 Returns sine of argument ``arg``.
1748 gross 290
1749 jfenwick 2625 :param arg: argument
1750     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1751     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1752     on the type of ``arg``
1753     :raise TypeError: if the type of the argument is not expected
1754 gross 290 """
1755 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1756     return numpy.sin(arg)
1757 gross 290 elif isinstance(arg,escript.Data):
1758     return arg._sin()
1759     elif isinstance(arg,float):
1760     return math.sin(arg)
1761     elif isinstance(arg,int):
1762     return math.sin(arg)
1763     elif isinstance(arg,Symbol):
1764     return Sin_Symbol(arg)
1765     else:
1766     raise TypeError,"sin: Unknown argument type."
1767    
1768     class Sin_Symbol(DependendSymbol):
1769     """
1770 jfenwick 2625 `Symbol` representing the result of the sine function.
1771 gross 290 """
1772     def __init__(self,arg):
1773     """
1774 jfenwick 2625 Initialization of sin `Symbol` with argument ``arg``.
1775 caltinay 2169
1776 jfenwick 2625 :param arg: argument of function
1777     :type arg: typically `Symbol`
1778 gross 290 """
1779     DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1780    
1781     def getMyCode(self,argstrs,format="escript"):
1782     """
1783 caltinay 2169 Returns program code that can be used to evaluate the symbol.
1784 gross 290
1785 jfenwick 2625 :param argstrs: a string for each argument representing the argument
1786 caltinay 2169 for the evaluation
1787 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1788     :param format: specifies the format to be used. At the moment only
1789 caltinay 2169 "escript", "str" and "text" are supported.
1790 jfenwick 2625 :type format: ``str``
1791     :return: a piece of program code which can be used to evaluate the
1792 caltinay 2169 expression assuming the values for the arguments are available
1793 jfenwick 2625 :rtype: ``str``
1794     :raise NotImplementedError: if no implementation for the given format
1795 caltinay 2169 is available
1796 gross 290 """
1797     if isinstance(argstrs,list):
1798     argstrs=argstrs[0]
1799     if format=="escript" or format=="str" or format=="text":
1800     return "sin(%s)"%argstrs
1801     else:
1802     raise NotImplementedError,"Sin_Symbol does not provide program code for format %s."%format
1803    
1804     def substitute(self,argvals):
1805     """
1806 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
1807 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
1808 caltinay 2169 defining this object.
1809 gross 290
1810 jfenwick 2625 :param argvals: new values assigned to symbols
1811     :type argvals: ``dict`` with keywords of type `Symbol`
1812     :return: result of the substitution process. Operations are executed as
1813 caltinay 2169 much as possible.
1814 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1815 caltinay 2169 depending on the degree of substitution
1816 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
1817 gross 290 """
1818     if argvals.has_key(self):
1819     arg=argvals[self]
1820     if self.isAppropriateValue(arg):
1821     return arg
1822     else:
1823     raise TypeError,"%s: new value is not appropriate."%str(self)
1824     else:
1825     arg=self.getSubstitutedArguments(argvals)[0]
1826     return sin(arg)
1827    
1828     def diff(self,arg):
1829     """
1830 caltinay 2169 Differential of this object.
1831 gross 290
1832 jfenwick 2625 :param arg: the derivative is calculated with respect to ``arg``
1833     :type arg: `escript.Symbol`
1834     :return: derivative with respect to ``arg``
1835     :rtype: typically `Symbol` but other types such as ``float``,
1836     `escript.Data`, ``numpy.ndarray`` are possible
1837 gross 290 """
1838     if arg==self:
1839     return identity(self.getShape())
1840     else:
1841     myarg=self.getArgument()[0]
1842     val=matchShape(cos(myarg),self.getDifferentiatedArguments(arg)[0])
1843     return val[0]*val[1]
1844    
1845     def cos(arg):
1846     """
1847 jfenwick 2625 Returns cosine of argument ``arg``.
1848 gross 290
1849 jfenwick 2625 :param arg: argument
1850     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1851     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1852     on the type of ``arg``
1853     :raise TypeError: if the type of the argument is not expected
1854 gross 290 """
1855 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1856     return numpy.cos(arg)
1857 gross 290 elif isinstance(arg,escript.Data):
1858     return arg._cos()
1859     elif isinstance(arg,float):
1860     return math.cos(arg)
1861     elif isinstance(arg,int):
1862     return math.cos(arg)
1863     elif isinstance(arg,Symbol):
1864     return Cos_Symbol(arg)
1865     else:
1866     raise TypeError,"cos: Unknown argument type."
1867    
1868     class Cos_Symbol(DependendSymbol):
1869     """
1870 jfenwick 2625 `Symbol` representing the result of the cosine function.
1871 gross 290 """
1872     def __init__(self,arg):
1873     """
1874 jfenwick 2625 Initialization of cos `Symbol` with argument ``arg``.
1875 caltinay 2169
1876 jfenwick 2625 :param arg: argument of function
1877     :type arg: typically `Symbol`
1878 gross 290 """
1879     DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1880    
1881     def getMyCode(self,argstrs,format="escript"):
1882     """
1883 caltinay 2169 Returns program code that can be used to evaluate the symbol.
1884 gross 290
1885 jfenwick 2625 :param argstrs: a string for each argument representing the argument
1886 caltinay 2169 for the evaluation
1887 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1888     :param format: specifies the format to be used. At the moment only
1889 caltinay 2169 "escript", "str" and "text" are supported.
1890 jfenwick 2625 :type format: ``str``
1891     :return: a piece of program code which can be used to evaluate the
1892 caltinay 2169 expression assuming the values for the arguments are available
1893 jfenwick 2625 :rtype: ``str``
1894     :raise NotImplementedError: if no implementation for the given format
1895 caltinay 2169 is available
1896 gross 290 """
1897     if isinstance(argstrs,list):
1898     argstrs=argstrs[0]
1899     if format=="escript" or format=="str" or format=="text":
1900     return "cos(%s)"%argstrs
1901     else:
1902     raise NotImplementedError,"Cos_Symbol does not provide program code for format %s."%format
1903    
1904     def substitute(self,argvals):
1905     """
1906 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
1907 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
1908 caltinay 2169 defining this object.
1909 gross 290
1910 jfenwick 2625 :param argvals: new values assigned to symbols
1911     :type argvals: ``dict`` with keywords of type `Symbol`
1912     :return: result of the substitution process. Operations are executed as
1913 caltinay 2169 much as possible.
1914 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1915 caltinay 2169 depending on the degree of substitution
1916 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
1917 gross 290 """
1918     if argvals.has_key(self):
1919     arg=argvals[self]
1920     if self.isAppropriateValue(arg):
1921     return arg
1922     else:
1923     raise TypeError,"%s: new value is not appropriate."%str(self)
1924     else:
1925     arg=self.getSubstitutedArguments(argvals)[0]
1926     return cos(arg)
1927    
1928     def diff(self,arg):
1929     """
1930 caltinay 2169 Differential of this object.
1931 gross 290
1932 jfenwick 2625 :param arg: the derivative is calculated with respect to ``arg``
1933     :type arg: `escript.Symbol`
1934     :return: derivative with respect to ``arg``
1935     :rtype: typically `Symbol` but other types such as ``float``,
1936     `escript.Data`, ``numpy.ndarray`` are possible
1937 gross 290 """
1938     if arg==self:
1939     return identity(self.getShape())
1940     else:
1941     myarg=self.getArgument()[0]
1942     val=matchShape(-sin(myarg),self.getDifferentiatedArguments(arg)[0])
1943     return val[0]*val[1]
1944    
1945     def tan(arg):
1946     """
1947 jfenwick 2625 Returns tangent of argument ``arg``.
1948 gross 290
1949 jfenwick 2625 :param arg: argument
1950     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1951     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1952     on the type of ``arg``
1953     :raise TypeError: if the type of the argument is not expected
1954 gross 290 """
1955 jfenwick 2455 if isinstance(arg,numpy.ndarray):
1956     return numpy.tan(arg)
1957 gross 290 elif isinstance(arg,escript.Data):
1958     return arg._tan()
1959     elif isinstance(arg,float):
1960     return math.tan(arg)
1961     elif isinstance(arg,int):
1962     return math.tan(arg)
1963     elif isinstance(arg,Symbol):
1964     return Tan_Symbol(arg)
1965     else:
1966     raise TypeError,"tan: Unknown argument type."
1967    
1968     class Tan_Symbol(DependendSymbol):
1969     """
1970 jfenwick 2625 `Symbol` representing the result of the tangent function.
1971 gross 290 """
1972     def __init__(self,arg):
1973     """
1974 jfenwick 2625 Initialization of tan `Symbol` with argument ``arg``.
1975 caltinay 2169
1976 jfenwick 2625 :param arg: argument of function
1977     :type arg: typically `Symbol`
1978 gross 290 """
1979     DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1980    
1981     def getMyCode(self,argstrs,format="escript"):
1982     """
1983 caltinay 2169 Returns program code that can be used to evaluate the symbol.
1984 gross 290
1985 jfenwick 2625 :param argstrs: a string for each argument representing the argument
1986 caltinay 2169 for the evaluation
1987 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1988     :param format: specifies the format to be used. At the moment only
1989 caltinay 2169 "escript", "str" and "text" are supported.
1990 jfenwick 2625 :type format: ``str``
1991     :return: a piece of program code which can be used to evaluate the
1992 caltinay 2169 expression assuming the values for the arguments are available
1993 jfenwick 2625 :rtype: ``str``
1994     :raise NotImplementedError: if no implementation for the given format
1995 caltinay 2169 is available
1996 gross 290 """
1997     if isinstance(argstrs,list):
1998     argstrs=argstrs[0]
1999     if format=="escript" or format=="str" or format=="text":
2000     return "tan(%s)"%argstrs
2001     else:
2002     raise NotImplementedError,"Tan_Symbol does not provide program code for format %s."%format
2003    
2004     def substitute(self,argvals):
2005     """
2006 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
2007 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
2008 caltinay 2169 defining this object.
2009 gross 290
2010 jfenwick 2625 :param argvals: new values assigned to symbols
2011     :type argvals: ``dict`` with keywords of type `Symbol`
2012     :return: result of the substitution process. Operations are executed as
2013 caltinay 2169 much as possible.
2014 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2015 caltinay 2169 depending on the degree of substitution
2016 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
2017 gross 290 """
2018     if argvals.has_key(self):
2019     arg=argvals[self]
2020     if self.isAppropriateValue(arg):
2021     return arg
2022     else:
2023     raise TypeError,"%s: new value is not appropriate."%str(self)
2024     else:
2025     arg=self.getSubstitutedArguments(argvals)[0]
2026     return tan(arg)
2027    
2028     def diff(self,arg):
2029     """
2030 caltinay 2169 Differential of this object.
2031 gross 290
2032 jfenwick 2625 :param arg: the derivative is calculated with respect to ``arg``
2033     :type arg: `escript.Symbol`
2034     :return: derivative with respect to ``arg``
2035     :rtype: typically `Symbol` but other types such as ``float``,
2036     `escript.Data`, ``numpy.ndarray`` are possible
2037 gross 290 """
2038     if arg==self:
2039     return identity(self.getShape())
2040     else:
2041     myarg=self.getArgument()[0]
2042     val=matchShape(1./cos(myarg)**2,self.getDifferentiatedArguments(arg)[0])
2043     return val[0]*val[1]
2044    
2045     def asin(arg):
2046     """
2047 jfenwick 2625 Returns the inverse sine of argument ``arg``.
2048 gross 290
2049 jfenwick 2625 :param arg: argument
2050     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2051     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2052     on the type of ``arg``
2053     :raise TypeError: if the type of the argument is not expected
2054 gross 290 """
2055 jfenwick 2455 if isinstance(arg,numpy.ndarray):
2056     return numpy.arcsin(arg)
2057 gross 290 elif isinstance(arg,escript.Data):
2058     return arg._asin()
2059     elif isinstance(arg,float):
2060     return math.asin(arg)
2061     elif isinstance(arg,int):
2062     return math.asin(arg)
2063     elif isinstance(arg,Symbol):
2064     return Asin_Symbol(arg)
2065     else:
2066     raise TypeError,"asin: Unknown argument type."
2067    
2068     class Asin_Symbol(DependendSymbol):
2069     """
2070 jfenwick 2625 `Symbol` representing the result of the inverse sine function.
2071 gross 290 """
2072     def __init__(self,arg):
2073     """
2074 jfenwick 2625 Initialization of asin `Symbol` with argument ``arg``.
2075 caltinay 2169
2076 jfenwick 2625 :param arg: argument of function
2077     :type arg: typically `Symbol`
2078 gross 290 """
2079     DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2080    
2081     def getMyCode(self,argstrs,format="escript"):
2082     """
2083 caltinay 2169 Returns program code that can be used to evaluate the symbol.
2084 gross 290
2085 jfenwick 2625 :param argstrs: a string for each argument representing the argument
2086 caltinay 2169 for the evaluation
2087 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2088     :param format: specifies the format to be used. At the moment only
2089 caltinay 2169 "escript", "str" and "text" are supported.
2090 jfenwick 2625 :type format: ``str``
2091     :return: a piece of program code which can be used to evaluate the
2092 caltinay 2169 expression assuming the values for the arguments are available
2093 jfenwick 2625 :rtype: ``str``
2094     :raise NotImplementedError: if no implementation for the given format
2095 caltinay 2169 is available
2096 gross 290 """
2097     if isinstance(argstrs,list):
2098     argstrs=argstrs[0]
2099     if format=="escript" or format=="str" or format=="text":
2100     return "asin(%s)"%argstrs
2101     else:
2102     raise NotImplementedError,"Asin_Symbol does not provide program code for format %s."%format
2103    
2104     def substitute(self,argvals):
2105     """
2106 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
2107 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
2108 caltinay 2169 defining this object.
2109 gross 290
2110 jfenwick 2625 :param argvals: new values assigned to symbols
2111     :type argvals: ``dict`` with keywords of type `Symbol`
2112     :return: result of the substitution process. Operations are executed as
2113 caltinay 2169 much as possible.
2114 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2115 caltinay 2169 depending on the degree of substitution
2116 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
2117 gross 290 """
2118     if argvals.has_key(self):
2119     arg=argvals[self]
2120     if self.isAppropriateValue(arg):
2121     return arg
2122     else:
2123     raise TypeError,"%s: new value is not appropriate."%str(self)
2124     else:
2125     arg=self.getSubstitutedArguments(argvals)[0]
2126     return asin(arg)
2127    
2128     def diff(self,arg):
2129     """
2130 caltinay 2169 Differential of this object.
2131 gross 290
2132 jfenwick 2625 :param arg: the derivative is calculated with respect to ``arg``
2133     :type arg: `escript.Symbol`
2134     :return: derivative with respect to ``arg``
2135     :rtype: typically `Symbol` but other types such as ``float``,
2136     `escript.Data`, ``numpy.ndarray`` are possible
2137 gross 290 """
2138     if arg==self:
2139     return identity(self.getShape())
2140     else:
2141     myarg=self.getArgument()[0]
2142     val=matchShape(1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2143     return val[0]*val[1]
2144    
2145     def acos(arg):
2146     """
2147 jfenwick 2625 Returns the inverse cosine of argument ``arg``.
2148 gross 290
2149 jfenwick 2625 :param arg: argument
2150     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2151     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2152     on the type of ``arg``
2153     :raise TypeError: if the type of the argument is not expected
2154 gross 290 """
2155 jfenwick 2455 if isinstance(arg,numpy.ndarray):
2156     return numpy.arccos(arg)
2157 gross 290 elif isinstance(arg,escript.Data):
2158     return arg._acos()
2159     elif isinstance(arg,float):
2160     return math.acos(arg)
2161     elif isinstance(arg,int):
2162     return math.acos(arg)
2163     elif isinstance(arg,Symbol):
2164     return Acos_Symbol(arg)
2165     else:
2166     raise TypeError,"acos: Unknown argument type."
2167    
2168     class Acos_Symbol(DependendSymbol):
2169     """
2170 jfenwick 2625 `Symbol` representing the result of the inverse cosine function.
2171 gross 290 """
2172     def __init__(self,arg):
2173     """
2174 jfenwick 2625 Initialization of acos `Symbol` with argument ``arg``.
2175 caltinay 2169
2176 jfenwick 2625 :param arg: argument of function
2177     :type arg: typically `Symbol`
2178 gross 290 """
2179     DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2180    
2181     def getMyCode(self,argstrs,format="escript"):
2182     """
2183 caltinay 2169 Returns program code that can be used to evaluate the symbol.
2184 gross 290
2185 jfenwick 2625 :param argstrs: a string for each argument representing the argument
2186 caltinay 2169 for the evaluation
2187 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2188     :param format: specifies the format to be used. At the moment only
2189 caltinay 2169 "escript", "str" and "text" are supported.
2190 jfenwick 2625 :type format: ``str``
2191     :return: a piece of program code which can be used to evaluate the
2192 caltinay 2169 expression assuming the values for the arguments are available
2193 jfenwick 2625 :rtype: ``str``
2194     :raise NotImplementedError: if no implementation for the given format
2195 caltinay 2169 is available
2196 gross 290 """
2197     if isinstance(argstrs,list):
2198     argstrs=argstrs[0]
2199     if format=="escript" or format=="str" or format=="text":
2200     return "acos(%s)"%argstrs
2201     else:
2202     raise NotImplementedError,"Acos_Symbol does not provide program code for format %s."%format
2203    
2204     def substitute(self,argvals):
2205     """
2206 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
2207 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
2208 caltinay 2169 defining this object.
2209 gross 290
2210 jfenwick 2625 :param argvals: new values assigned to symbols
2211     :type argvals: ``dict`` with keywords of type `Symbol`
2212     :return: result of the substitution process. Operations are executed as
2213 caltinay 2169 much as possible.
2214 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2215 caltinay 2169 depending on the degree of substitution
2216 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
2217 gross 290 """
2218     if argvals.has_key(self):
2219     arg=argvals[self]
2220     if self.isAppropriateValue(arg):
2221     return arg
2222     else:
2223     raise TypeError,"%s: new value is not appropriate."%str(self)
2224     else:
2225     arg=self.getSubstitutedArguments(argvals)[0]
2226     return acos(arg)
2227    
2228     def diff(self,arg):
2229     """
2230 caltinay 2169 Differential of this object.
2231 gross 290
2232 jfenwick 2625 :param arg: the derivative is calculated with respect to ``arg``
2233     :type arg: `escript.Symbol`
2234     :return: derivative with respect to ``arg``
2235     :rtype: typically `Symbol` but other types such as ``float``,
2236     `escript.Data`, ``numpy.ndarray`` are possible
2237 gross 290 """
2238     if arg==self:
2239     return identity(self.getShape())
2240     else:
2241     myarg=self.getArgument()[0]
2242     val=matchShape(-1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2243     return val[0]*val[1]
2244    
2245     def atan(arg):
2246     """
2247 jfenwick 2625 Returns inverse tangent of argument ``arg``.
2248 gross 290
2249 jfenwick 2625 :param arg: argument
2250     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2251     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2252     on the type of ``arg``
2253     :raise TypeError: if the type of the argument is not expected
2254 gross 290 """
2255 jfenwick 2455 if isinstance(arg,numpy.ndarray):
2256     return numpy.arctan(arg)
2257 gross 290 elif isinstance(arg,escript.Data):
2258     return arg._atan()
2259     elif isinstance(arg,float):
2260     return math.atan(arg)
2261     elif isinstance(arg,int):
2262     return math.atan(arg)
2263     elif isinstance(arg,Symbol):
2264     return Atan_Symbol(arg)
2265     else:
2266     raise TypeError,"atan: Unknown argument type."
2267    
2268     class Atan_Symbol(DependendSymbol):
2269     """
2270 jfenwick 2625 `Symbol` representing the result of the inverse tangent function.
2271 gross 290 """
2272     def __init__(self,arg):
2273     """
2274 jfenwick 2625 Initialization of atan `Symbol` with argument ``arg``.
2275 caltinay 2169
2276 jfenwick 2625 :param arg: argument of function
2277     :type arg: typically `Symbol`
2278 gross 290 """
2279     DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2280    
2281     def getMyCode(self,argstrs,format="escript"):
2282     """
2283 caltinay 2169 Returns program code that can be used to evaluate the symbol.
2284 gross 290
2285 jfenwick 2625 :param argstrs: a string for each argument representing the argument
2286 caltinay 2169 for the evaluation
2287 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2288     :param format: specifies the format to be used. At the moment only
2289 caltinay 2169 "escript", "str" and "text" are supported.
2290 jfenwick 2625 :type format: ``str``
2291     :return: a piece of program code which can be used to evaluate the
2292 caltinay 2169 expression assuming the values for the arguments are available
2293 jfenwick 2625 :rtype: ``str``
2294     :raise NotImplementedError: if no implementation for the given format
2295 caltinay 2169 is available
2296 gross 290 """
2297     if isinstance(argstrs,list):
2298     argstrs=argstrs[0]
2299     if format=="escript" or format=="str" or format=="text":
2300     return "atan(%s)"%argstrs
2301     else:
2302     raise NotImplementedError,"Atan_Symbol does not provide program code for format %s."%format
2303    
2304     def substitute(self,argvals):
2305     """
2306 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
2307 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
2308 caltinay 2169 defining this object.
2309 gross 290
2310 jfenwick 2625 :param argvals: new values assigned to symbols
2311     :type argvals: ``dict`` with keywords of type `Symbol`
2312     :return: result of the substitution process. Operations are executed as
2313 caltinay 2169 much as possible.
2314 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2315 caltinay 2169 depending on the degree of substitution
2316 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
2317 gross 290 """
2318     if argvals.has_key(self):
2319     arg=argvals[self]
2320     if self.isAppropriateValue(arg):
2321     return arg
2322     else:
2323     raise TypeError,"%s: new value is not appropriate."%str(self)
2324     else:
2325     arg=self.getSubstitutedArguments(argvals)[0]
2326     return atan(arg)
2327    
2328     def diff(self,arg):
2329     """
2330 caltinay 2169 Differential of this object.
2331 gross 290
2332 jfenwick 2625 :param arg: the derivative is calculated with respect to ``arg``
2333     :type arg: `escript.Symbol`
2334     :return: derivative with respect to ``arg``
2335     :rtype: typically `Symbol` but other types such as ``float``,
2336     `escript.Data`, ``numpy.ndarray`` are possible
2337 gross 290 """
2338     if arg==self:
2339     return identity(self.getShape())
2340     else:
2341     myarg=self.getArgument()[0]
2342     val=matchShape(1./(1+myarg**2),self.getDifferentiatedArguments(arg)[0])
2343     return val[0]*val[1]
2344    
2345 jgs 150 def sinh(arg):
2346 gross 290 """
2347 jfenwick 2625 Returns the hyperbolic sine of argument ``arg``.
2348 jgs 150
2349 jfenwick 2625 :param arg: argument
2350     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2351     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2352     on the type of ``arg``
2353     :raise TypeError: if the type of the argument is not expected
2354 gross 290 """
2355 jfenwick 2455 if isinstance(arg,numpy.ndarray):
2356     return numpy.sinh(arg)
2357 gross 290 elif isinstance(arg,escript.Data):
2358     return arg._sinh()
2359     elif isinstance(arg,float):
2360     return math.sinh(arg)
2361     elif isinstance(arg,int):
2362     return math.sinh(arg)
2363     elif isinstance(arg,Symbol):
2364     return Sinh_Symbol(arg)
2365     else:
2366     raise TypeError,"sinh: Unknown argument type."
2367 jgs 150
2368 gross 290 class Sinh_Symbol(DependendSymbol):
2369     """
2370 jfenwick 2625 `Symbol` representing the result of the hyperbolic sine function.
2371 gross 290 """
2372     def __init__(self,arg):
2373     """
2374 jfenwick 2625 Initialization of sinh `Symbol` with argument ``arg``.
2375 caltinay 2169
2376 jfenwick 2625 :param arg: argument of function
2377     :type arg: typically `Symbol`
2378 gross 290 """
2379     DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2380    
2381     def getMyCode(self,argstrs,format="escript"):
2382     """
2383 caltinay 2169 Returns program code that can be used to evaluate the symbol.
2384 gross 290
2385 jfenwick 2625 :param argstrs: a string for each argument representing the argument
2386 caltinay 2169 for the evaluation
2387 jfenwick 2625 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2388     :param format: specifies the format to be used. At the moment only
2389 caltinay 2169 "escript", "str" and "text" are supported.
2390 jfenwick 2625 :type format: ``str``
2391     :return: a piece of program code which can be used to evaluate the
2392 caltinay 2169 expression assuming the values for the arguments are available
2393 jfenwick 2625 :rtype: ``str``
2394     :raise NotImplementedError: if no implementation for the given format
2395 caltinay 2169 is available
2396 gross 290 """
2397     if isinstance(argstrs,list):
2398     argstrs=argstrs[0]
2399     if format=="escript" or format=="str" or format=="text":
2400     return "sinh(%s)"%argstrs
2401     else:
2402     raise NotImplementedError,"Sinh_Symbol does not provide program code for format %s."%format
2403    
2404     def substitute(self,argvals):
2405     """
2406 caltinay 2169 Assigns new values to symbols in the definition of the symbol.
2407 jfenwick 2625 The method replaces the `Symbol` u by argvals[u] in the expression
2408 caltinay 2169 defining this object.
2409 gross 290
2410 jfenwick 2625 :param argvals: new values assigned to symbols
2411     :type argvals: ``dict`` with keywords of type `Symbol`
2412     :return: result of the substitution process. Operations are executed as
2413 caltinay 2169 much as possible.
2414 jfenwick 2625 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2415 caltinay 2169 depending on the degree of substitution
2416 jfenwick 2625 :raise TypeError: if a value for a `Symbol` cannot be substituted
2417 gross 290 """
2418     if argvals.has_key(self):
2419     arg=argvals[self]
2420     if self.isAppropriateValue(arg):
2421     return arg
2422     else:
2423     raise TypeError,"%s: new value is not appropriate."%str(self)
2424     else:
2425     arg=self.getSubstitutedArguments(argvals)[0]
2426     return sinh(arg)
2427    
2428     def diff(self,arg):
2429     """
2430 caltinay 2169 Differential of this object.
2431 gross 290
2432 jfenwick 2625 :param arg: the derivative is calculated with respect to ``arg``
2433     :type arg: `escript.Symbol`
2434     :return: derivative with respect to ``arg``
2435     :rtype: typically `Symbol` but other types such as ``float``,
2436     `escript.Data`, ``numpy.ndarray`` are possible
2437 gross 290 """
2438     if arg==self:
2439     return identity(self.getShape())
2440     else:
2441     myarg=self.getArgument()[0]
2442     val=matchShape(cosh(myarg),self.getDifferentiatedArguments(arg)[0])
2443     return val[0]*val[1]
2444    
2445 jgs 150 def cosh(arg):
2446 gross 290 """
2447 jfenwick 2625 Returns the hyperbolic cosine of argument ``arg``.
2448 jgs 150
2449 jfenwick 2625 :param arg: argument
2450     :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2451     :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2452     on the type of ``arg``
2453     :raise TypeError: if the type of the argument is not expected
2454 gross 290 """
2455 jfenwick 2455 if isinstance(arg,numpy.ndarray):
2456     return numpy.cosh(arg)
2457 gross 290 elif isinstance(arg,escript.Data):
2458     return arg._cosh()
2459     elif isinstance(arg,float):
2460     return math.cosh(arg)
2461     elif isinstance(arg,int):
2462     return math.cosh(arg)
2463     elif isinstance(arg,Symbol):
2464     return Cosh_Symbol(arg)
2465     else:
2466     raise TypeError,"cosh: Unknown argument type."
2467 jgs 150
2468 gross 290 class Cosh_Symbol(DependendSymbol):
2469     """
2470 jfenwick 2625 `Symbol` representing the result of the hyperbolic cosine function.
2471 gross 290 """
2472     def __init__(self,arg):
2473     """
2474 jfenwick 2625 Initialization of cosh `Symbol` with argument ``arg``.
2475 caltinay 2169
2476 jfenwick 2625 :param arg: argument of function
2477     :type arg: typically `Symbol`
2478 gross