/[escript]/trunk-mpi-branch/escript/py_src/util.py
ViewVC logotype

Annotation of /trunk-mpi-branch/escript/py_src/util.py

Parent Directory Parent Directory | Revision Log Revision Log


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