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