/[escript]/trunk-mpi-branch/escript/py_src/util.py
ViewVC logotype

Annotation of /trunk-mpi-branch/escript/py_src/util.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1286 - (hide annotations)
Tue Sep 4 02:11:15 2007 UTC (12 years ago) by gross
File MIME type: text/x-python
File size: 213693 byte(s)
Tests for solving systems of PDEs with various solvers added. In particular solving systems with a direct solver (MKL) was not done in a best way as a matrix pattern was created twice. This problem should be fixed now. A message is printed to inform about a pattern unrolling. I leave the message in there for now to check that unrolling called only if appropriate. 

There is also a function now which turns face tags into node tags. 


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