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