/[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 608 - (hide annotations)
Tue Mar 21 09:46:06 2006 UTC (13 years, 8 months ago) by elspeth
File MIME type: text/x-python
File size: 194470 byte(s)
moved "import numarray.linear_algebra" to function that uses it, in case it is not installed

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