/[escript]/trunk/escript/py_src/util.py
ViewVC logotype

Annotation of /trunk/escript/py_src/util.py

Parent Directory Parent Directory | Revision Log Revision Log


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