/[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 2142 - (hide annotations)
Tue Dec 9 06:22:57 2008 UTC (10 years, 9 months ago) by jfenwick
File MIME type: text/x-python
File size: 210784 byte(s)
Added showEscriptParams to output a list of available params.

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