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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 912 - (hide annotations)
Wed Dec 6 03:29:49 2006 UTC (12 years, 10 months ago) by gross
File MIME type: text/x-python
File size: 211633 byte(s)
modellib.WriteVTK has been rewritten. Instead of only three data objects scalar,
vector, tensor it takes now up to 20 data objects data0 ... data19 and writes it into a 
single VTK file. There is also the possibilty to define individiual name tags name0,..., name19.
If no name is given the corresponding attribute name of the Link target is used. 
This simplifies the usage and increases efficiency.



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