/[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 813 - (hide annotations)
Mon Aug 21 02:08:47 2006 UTC (13 years, 3 months ago) by ksteube
File MIME type: text/x-python
File size: 210300 byte(s)
Tensor products for Data objects are now computed by a C++ method
C_GeneralTensorProduct, which calls C function matrix_matrix_product
to do the actual calculation.

Can perform product with either input transposed in place, meaning
without first computing the transpose in a separate step.

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