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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/esys2/escript/py_src/util.py revision 108 by jgs, Thu Jan 27 06:21:59 2005 UTC trunk/escript/py_src/util.py revision 1044 by gross, Mon Mar 19 07:29:31 2007 UTC
# Line 1  Line 1 
1  # $Id$  # $Id$
2    
 ## @file util.py  
   
3  """  """
4  @brief Utility functions for escript  Utility functions for escript
5    
6    @var __author__: name of author
7    @var __copyright__: copyrights
8    @var __license__: licence agreement
9    @var __url__: url entry point on documentation
10    @var __version__: version
11    @var __date__: date of the version
12  """  """
13                                                                                                                                                                                                        
14    __author__="Lutz Gross, l.gross@uq.edu.au"
15    __copyright__="""  Copyright (c) 2006 by ACcESS MNRF
16                        http://www.access.edu.au
17                    Primary Business: Queensland, Australia"""
18    __license__="""Licensed under the Open Software License version 3.0
19                 http://www.opensource.org/licenses/osl-3.0.php"""
20    __url__="http://www.iservo.edu.au/esys/escript"
21    __version__="$Revision$"
22    __date__="$Date$"
23    
24    
25    import math
26  import numarray  import numarray
27  import escript  import escript
28  #  import os
29  #   escript constants (have to be consistent witj utilC.h  from esys.escript import C_GeneralTensorProduct
30  #  
31  UNKNOWN=-1  #=========================================================
32  EPSILON=1.e-15  #   some helpers:
33  Pi=numarray.pi  #=========================================================
34  # some solver options:  def getTagNames(domain):
 NO_REORDERING=0  
 MINIMUM_FILL_IN=1  
 NESTED_DISSECTION=2  
 # solver methods  
 DEFAULT_METHOD=0  
 DIRECT=1  
 CHOLEVSKY=2  
 PCG=3  
 CR=4  
 CGS=5  
 BICGSTAB=6  
 SSOR=7  
 ILU0=8  
 ILUT=9  
 JACOBI=10  
 GMRES=11  
 PRES20=12  
   
 METHOD_KEY="method"  
 SYMMETRY_KEY="symmetric"  
 TOLERANCE_KEY="tolerance"  
   
 # supported file formats:  
 VRML=1  
 PNG=2  
 JPEG=3  
 JPG=3  
 PS=4  
 OOGL=5  
 BMP=6  
 TIFF=7  
 OPENINVENTOR=8  
 RENDERMAN=9  
 PNM=10  
 #  
 # wrapper for various functions: if the argument has attribute the function name  
 # as an argument it calls the correspong methods. Otherwise the coresponsing numarray  
 # function is called.  
 #  
 # functions involving the underlying Domain:  
 #  
 def grad(arg,where=None):  
35      """      """
36      @brief returns the spatial gradient of the Data object arg      returns a list of the tag names used by the domain
37    
38      @param arg: Data object representing the function which gradient to be calculated.      
39      @param where: FunctionSpace in which the gradient will be. If None Function(dom) where dom is the      @param domain: a domain object
40                    domain of the Data object arg.      @type domain: L{escript.Domain}
41        @return: a list of the tag name used by the domain.
42        @rtype: C{list} of C{str}
43      """      """
44      if isinstance(arg,escript.Data):      return [n.strip() for n in domain.showTagNames().split(",") ]
45         if where==None:  
46            return arg.grad()  def insertTagNames(domain,**kwargs):
47         else:      """
48            return arg.grad(where)      inserts tag names into the domain
49    
50        @param domain: a domain object
51        @type domain: C{escript.Domain}
52        @keyword <tag name>: tag key assigned to <tag name>
53        @type <tag name>: C{int}
54        """
55        for  k in kwargs:
56             domain.setTagMap(k,kwargs[k])
57    
58    def insertTaggedValues(target,**kwargs):
59        """
60        inserts tagged values into the tagged using tag names
61    
62        @param target: data to be filled by tagged values
63        @type target: L{escript.Data}
64        @keyword <tag name>: value to be used for <tag name>
65        @type <tag name>: C{float} or {numarray.NumArray}
66        @return: C{target}
67        @rtype: L{escript.Data}
68        """
69        for k in kwargs:
70            target.setTaggedValue(k,kwargs[k])
71        return target
72    
73        
74    def saveVTK(filename,domain=None,**data):
75        """
76        writes a L{Data} objects into a files using the the VTK XML file format.
77    
78        Example::
79    
80           tmp=Scalar(..)
81           v=Vector(..)
82           saveVTK("solution.xml",temperature=tmp,velovity=v)
83    
84        tmp and v are written into "solution.xml" where tmp is named "temperature" and v is named "velovity"
85    
86        @param filename: file name of the output file
87        @type filename: C{str}
88        @param domain: domain of the L{Data} object. If not specified, the domain of the given L{Data} objects is used.
89        @type domain: L{escript.Domain}
90        @keyword <name>: writes the assigned value to the VTK file using <name> as identifier.
91        @type <name>: L{Data} object.
92        @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.
93        """
94        if domain==None:
95           for i in data.keys():
96              if not data[i].isEmpty(): domain=data[i].getFunctionSpace().getDomain()
97        if domain==None:
98            raise ValueError,"no domain detected."
99      else:      else:
100         return arg*0.          domain.saveVTK(filename,data)
101    
102  def integrate(arg,what=None):  def saveDX(filename,domain=None,**data):
103      """      """
104      @brief return the integral if the function represented by Data object arg over its domain.      writes a L{Data} objects into a files using the the DX file format.
105    
106        Example::
107    
108      @param arg         tmp=Scalar(..)
109           v=Vector(..)
110           saveDX("solution.dx",temperature=tmp,velovity=v)
111    
112        tmp and v are written into "solution.dx" where tmp is named "temperature" and v is named "velovity".
113    
114        @param filename: file name of the output file
115        @type filename: C{str}
116        @param domain: domain of the L{Data} object. If not specified, the domain of the given L{Data} objects is used.
117        @type domain: L{escript.Domain}
118        @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.
119        @type <name>: L{Data} object.
120        @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.
121      """      """
122      if not what==None:      if domain==None:
123         arg2=escript.Data(arg,what)         for i in data.keys():
124              if not data[i].isEmpty(): domain=data[i].getFunctionSpace().getDomain()
125        if domain==None:
126            raise ValueError,"no domain detected."
127      else:      else:
128         arg2=arg          domain.saveDX(filename,data)
129      if arg2.getRank()==0:  
130          return arg2.integrate()[0]  def kronecker(d=3):
131       """
132       return the kronecker S{delta}-symbol
133    
134       @param d: dimension or an object that has the C{getDim} method defining the dimension
135       @type d: C{int}, L{escript.Domain} or L{escript.FunctionSpace}
136       @return: the object u of rank 2 with M{u[i,j]=1} for M{i=j} and M{u[i,j]=0} otherwise
137       @rtype: L{numarray.NumArray} or L{escript.Data} of rank 2.
138       """
139       return identityTensor(d)
140    
141    def identity(shape=()):
142       """
143       return the shape x shape identity tensor
144    
145       @param shape: input shape for the identity tensor
146       @type shape: C{tuple} of C{int}
147       @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.
148       @rtype: L{numarray.NumArray} of rank 1, rankk 2 or rank 4.
149       @raise ValueError: if len(shape)>2.
150       """
151       if len(shape)>0:
152          out=numarray.zeros(shape+shape,numarray.Float64)
153          if len(shape)==1:
154              for i0 in range(shape[0]):
155                 out[i0,i0]=1.
156          elif len(shape)==2:
157              for i0 in range(shape[0]):
158                 for i1 in range(shape[1]):
159                    out[i0,i1,i0,i1]=1.
160          else:
161              raise ValueError,"identity: length of shape is restricted to 2."
162       else:
163          out=1.
164       return out
165    
166    def identityTensor(d=3):
167       """
168       return the dxd identity matrix
169    
170       @param d: dimension or an object that has the C{getDim} method defining the dimension
171       @type d: C{int}, L{escript.Domain} or L{escript.FunctionSpace}
172       @return: the object u of rank 2 with M{u[i,j]=1} for M{i=j} and M{u[i,j]=0} otherwise
173       @rtype: L{numarray.NumArray} or L{escript.Data} of rank 2
174       """
175       if isinstance(d,escript.FunctionSpace):
176           return escript.Data(identity((d.getDim(),)),d)
177       elif isinstance(d,escript.Domain):
178           return identity((d.getDim(),))
179       else:
180           return identity((d,))
181    
182    def identityTensor4(d=3):
183       """
184       return the dxdxdxd identity tensor
185    
186       @param d: dimension or an object that has the C{getDim} method defining the dimension
187       @type d: C{int} or any object with a C{getDim} method
188       @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
189       @rtype: L{numarray.NumArray} or L{escript.Data} of rank 4.
190       """
191       if isinstance(d,escript.FunctionSpace):
192           return escript.Data(identity((d.getDim(),d.getDim())),d)
193       elif isinstance(d,escript.Domain):
194           return identity((d.getDim(),d.getDim()))
195       else:
196           return identity((d,d))
197    
198    def unitVector(i=0,d=3):
199       """
200       return a unit vector u of dimension d with nonzero index i:
201    
202       @param i: index
203       @type i: C{int}
204       @param d: dimension or an object that has the C{getDim} method defining the dimension
205       @type d: C{int}, L{escript.Domain} or L{escript.FunctionSpace}
206       @return: the object u of rank 1 with M{u[j]=1} for M{j=i} and M{u[i]=0} otherwise
207       @rtype: L{numarray.NumArray} or L{escript.Data} of rank 1
208       """
209       return kronecker(d)[i]
210    
211    #=========================================================================
212    #   global reduction operations (these functions have no symbolic version)
213    #=========================================================================
214    def Lsup(arg):
215        """
216        returns the Lsup-norm of argument arg. This is the maximum absolute value over all data points.
217        This function is equivalent to sup(abs(arg)).
218    
219        @param arg: argument
220        @type arg: C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
221        @return: maximum value of the absolute value of arg over all components and all data points
222        @rtype: C{float}
223        @raise TypeError: if type of arg cannot be processed
224        """
225        if isinstance(arg,numarray.NumArray):
226            return sup(abs(arg))
227        elif isinstance(arg,escript.Data):
228            return arg._Lsup()
229        elif isinstance(arg,float):
230            return abs(arg)
231        elif isinstance(arg,int):
232            return abs(float(arg))
233      else:      else:
234          return arg2.integrate()        raise TypeError,"Lsup: Unknown argument type."
235    
236  def interpolate(arg,where):  def sup(arg):
237      """      """
238      @brief interpolates the function represented by Data object arg into the FunctionSpace where.      returns the maximum value over all data points.
239    
240      @param arg      @param arg: argument
241      @param where      @type arg: C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
242        @return: maximum value of arg over all components and all data points
243        @rtype: C{float}
244        @raise TypeError: if type of arg cannot be processed
245      """      """
246      if isinstance(arg,escript.Data):      if isinstance(arg,numarray.NumArray):
247         return arg.interpolate(where)          return arg.max()
248        elif isinstance(arg,escript.Data):
249            return arg._sup()
250        elif isinstance(arg,float):
251            return arg
252        elif isinstance(arg,int):
253            return float(arg)
254      else:      else:
255         return arg        raise TypeError,"sup: Unknown argument type."
256    
257  # functions returning Data objects:  def inf(arg):
258        """
259        returns the maximum value over all data points.
260    
261  def transpose(arg,axis=None):      @param arg: argument
262        @type arg: C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
263        @return: minimum value of arg over all components and all data points
264        @rtype: C{float}
265        @raise TypeError: if type of arg cannot be processed
266      """      """
267      @brief returns the transpose of the Data object arg.      if isinstance(arg,numarray.NumArray):
268            return arg.min()
269        elif isinstance(arg,escript.Data):
270            return arg._inf()
271        elif isinstance(arg,float):
272            return arg
273        elif isinstance(arg,int):
274            return float(arg)
275        else:
276          raise TypeError,"inf: Unknown argument type."
277    
278      @param arg  
279    #=========================================================================
280    #   some little helpers
281    #=========================================================================
282    def getRank(arg):
283      """      """
284      if isinstance(arg,escript.Data):      identifies the rank of its argument
285         # hack for transpose  
286         r=arg.getRank()      @param arg: a given object
287         if r!=2: raise ValueError,"Tranpose only avalaible for rank 2 objects"      @type arg: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, C{Symbol}
288         s=arg.getShape()      @return: the rank of the argument
289         out=escript.Data(0.,(s[1],s[0]),arg.getFunctionSpace())      @rtype: C{int}
290         for i in range(s[0]):      @raise TypeError: if type of arg cannot be processed
291            for j in range(s[1]):      """
292               out[j,i]=arg[i,j]  
293         return out      if isinstance(arg,numarray.NumArray):
294         # end hack for transpose          return arg.rank
295         if axis==None: axis=arg.getRank()/2      elif isinstance(arg,escript.Data):
296         return arg.transpose(axis)          return arg.getRank()
297        elif isinstance(arg,float):
298            return 0
299        elif isinstance(arg,int):
300            return 0
301        elif isinstance(arg,Symbol):
302            return arg.getRank()
303      else:      else:
304         if axis==None: axis=arg.rank/2        raise TypeError,"getShape: cannot identify shape"
305         return numarray.transpose(arg,axis=axis)  def getShape(arg):
306        """
307        identifies the shape of its argument
308    
309        @param arg: a given object
310        @type arg: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, C{Symbol}
311        @return: the shape of the argument
312        @rtype: C{tuple} of C{int}
313        @raise TypeError: if type of arg cannot be processed
314        """
315    
316        if isinstance(arg,numarray.NumArray):
317            return arg.shape
318        elif isinstance(arg,escript.Data):
319            return arg.getShape()
320        elif isinstance(arg,float):
321            return ()
322        elif isinstance(arg,int):
323            return ()
324        elif isinstance(arg,Symbol):
325            return arg.getShape()
326        else:
327          raise TypeError,"getShape: cannot identify shape"
328    
329  def trace(arg):  def pokeDim(arg):
330      """      """
331      @brief      identifies the spatial dimension of its argument
332    
333      @param arg      @param arg: a given object
334        @type arg: any
335        @return: the spatial dimension of the argument, if available, or C{None}
336        @rtype: C{int} or C{None}
337      """      """
338    
339      if isinstance(arg,escript.Data):      if isinstance(arg,escript.Data):
340         # hack for trace          return arg.getFunctionSpace().getDim()
341         r=arg.getRank()      elif isinstance(arg,Symbol):
342         if r!=2: raise ValueError,"trace only avalaible for rank 2 objects"          return arg.getDim()
        s=arg.getShape()  
        out=escript.Scalar(0,arg.getFunctionSpace())  
        for i in range(min(s)):  
              out+=arg[i,i]  
        return out  
        # end hack for trace  
        return arg.trace()  
343      else:      else:
344         return numarray.trace(arg)          return None
345    
346  def exp(arg):  def commonShape(arg0,arg1):
347      """      """
348      @brief      returns a shape to which arg0 can be extendent from the right and arg1 can be extended from the left.
349    
350      @param arg      @param arg0: an object with a shape (see L{getShape})
351        @param arg1: an object with a shape (see L{getShape})
352        @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.
353        @rtype: C{tuple} of C{int}
354        @raise ValueError: if no shape can be found.
355      """      """
356      if isinstance(arg,escript.Data):      sh0=getShape(arg0)
357         return arg.exp()      sh1=getShape(arg1)
358        if len(sh0)<len(sh1):
359           if not sh0==sh1[:len(sh0)]:
360                 raise ValueError,"argument 0 cannot be extended to the shape of argument 1"
361           return sh1
362        elif len(sh0)>len(sh1):
363           if not sh1==sh0[:len(sh1)]:
364                 raise ValueError,"argument 1 cannot be extended to the shape of argument 0"
365           return sh0
366      else:      else:
367         return numarray.exp(arg)         if not sh0==sh1:
368                 raise ValueError,"argument 1 and argument 0 have not the same shape."
369           return sh0
370    
371  def sqrt(arg):  def commonDim(*args):
372      """      """
373      @brief      identifies, if possible, the spatial dimension across a set of objects which may or my not have a spatial dimension.
374    
375      @param arg      @param args: given objects
376        @return: the spatial dimension of the objects with identifiable dimension (see L{pokeDim}). If none the objects has
377                 a spatial dimension C{None} is returned.
378        @rtype: C{int} or C{None}
379        @raise ValueError: if the objects with identifiable dimension don't have the same spatial dimension.
380      """      """
381      if isinstance(arg,escript.Data):      out=None
382         return arg.sqrt()      for a in args:
383           d=pokeDim(a)
384           if not out==None:
385              if not (d==None or out==d):
386                 raise ValueError,"dimension of arguments don't match"
387           else:
388              out=d
389        return out
390    
391    def testForZero(arg):
392        """
393        test the argument for being identical to Zero
394    
395        @param arg: a given object
396        @type arg: typically L{numarray.NumArray},L{escript.Data},C{float}, C{int}
397        @return: True if the argument is identical to zero.
398        @rtype: C{bool}
399        """
400        if isinstance(arg,numarray.NumArray):
401           return not Lsup(arg)>0.
402        elif isinstance(arg,escript.Data):
403           return False
404        elif isinstance(arg,float):
405           return not Lsup(arg)>0.
406        elif isinstance(arg,int):
407           return not Lsup(arg)>0.
408        elif isinstance(arg,Symbol):
409           return False
410      else:      else:
411         return numarray.sqrt(arg)         return False
412    
413  def sin(arg):  def matchType(arg0=0.,arg1=0.):
414      """      """
415      @brief      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}.
416    
417      @param arg      @param arg0: first argument
418        @type arg0: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, C{Symbol}
419        @param arg1: second argument
420        @type arg1: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, C{Symbol}
421        @return: a tuple representing arg0 and arg1 with the same type or with one of them being a L{Symbol}
422        @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}.  
423        @raise TypeError: if type of arg0 or arg1 cannot be processed
424      """      """
425      if isinstance(arg,escript.Data):      if isinstance(arg0,numarray.NumArray):
426         return arg.sin()         if isinstance(arg1,numarray.NumArray):
427              pass
428           elif isinstance(arg1,escript.Data):
429              arg0=escript.Data(arg0,arg1.getFunctionSpace())
430           elif isinstance(arg1,float):
431              arg1=numarray.array(arg1,type=numarray.Float64)
432           elif isinstance(arg1,int):
433              arg1=numarray.array(float(arg1),type=numarray.Float64)
434           elif isinstance(arg1,Symbol):
435              pass
436           else:
437              raise TypeError,"function: Unknown type of second argument."    
438        elif isinstance(arg0,escript.Data):
439           if isinstance(arg1,numarray.NumArray):
440              arg1=escript.Data(arg1,arg0.getFunctionSpace())
441           elif isinstance(arg1,escript.Data):
442              pass
443           elif isinstance(arg1,float):
444              arg1=escript.Data(arg1,(),arg0.getFunctionSpace())
445           elif isinstance(arg1,int):
446              arg1=escript.Data(float(arg1),(),arg0.getFunctionSpace())
447           elif isinstance(arg1,Symbol):
448              pass
449           else:
450              raise TypeError,"function: Unknown type of second argument."    
451        elif isinstance(arg0,Symbol):
452           if isinstance(arg1,numarray.NumArray):
453              pass
454           elif isinstance(arg1,escript.Data):
455              pass
456           elif isinstance(arg1,float):
457              arg1=numarray.array(arg1,type=numarray.Float64)
458           elif isinstance(arg1,int):
459              arg1=numarray.array(float(arg1),type=numarray.Float64)
460           elif isinstance(arg1,Symbol):
461              pass
462           else:
463              raise TypeError,"function: Unknown type of second argument."    
464        elif isinstance(arg0,float):
465           if isinstance(arg1,numarray.NumArray):
466              arg0=numarray.array(arg0,type=numarray.Float64)
467           elif isinstance(arg1,escript.Data):
468              arg0=escript.Data(arg0,arg1.getFunctionSpace())
469           elif isinstance(arg1,float):
470              arg0=numarray.array(arg0,type=numarray.Float64)
471              arg1=numarray.array(arg1,type=numarray.Float64)
472           elif isinstance(arg1,int):
473              arg0=numarray.array(arg0,type=numarray.Float64)
474              arg1=numarray.array(float(arg1),type=numarray.Float64)
475           elif isinstance(arg1,Symbol):
476              arg0=numarray.array(arg0,type=numarray.Float64)
477           else:
478              raise TypeError,"function: Unknown type of second argument."    
479        elif isinstance(arg0,int):
480           if isinstance(arg1,numarray.NumArray):
481              arg0=numarray.array(float(arg0),type=numarray.Float64)
482           elif isinstance(arg1,escript.Data):
483              arg0=escript.Data(float(arg0),arg1.getFunctionSpace())
484           elif isinstance(arg1,float):
485              arg0=numarray.array(float(arg0),type=numarray.Float64)
486              arg1=numarray.array(arg1,type=numarray.Float64)
487           elif isinstance(arg1,int):
488              arg0=numarray.array(float(arg0),type=numarray.Float64)
489              arg1=numarray.array(float(arg1),type=numarray.Float64)
490           elif isinstance(arg1,Symbol):
491              arg0=numarray.array(float(arg0),type=numarray.Float64)
492           else:
493              raise TypeError,"function: Unknown type of second argument."    
494      else:      else:
495         return numarray.sin(arg)        raise TypeError,"function: Unknown type of first argument."    
496    
497        return arg0,arg1
498    
499    def matchShape(arg0,arg1):
500        """
501        return representations of arg0 amd arg1 which ahve the same shape
502    
503        @param arg0: a given object
504        @type arg0: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, L{Symbol}
505        @param arg1: a given object
506        @type arg1: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, L{Symbol}
507        @return: C{arg0} and C{arg1} where copies are returned when the shape has to be changed.
508        @rtype: C{tuple}
509        """
510        sh=commonShape(arg0,arg1)
511        sh0=getShape(arg0)
512        sh1=getShape(arg1)
513        if len(sh0)<len(sh):
514           return outer(arg0,numarray.ones(sh[len(sh0):],numarray.Float64)),arg1
515        elif len(sh1)<len(sh):
516           return arg0,outer(arg1,numarray.ones(sh[len(sh1):],numarray.Float64))
517        else:
518           return arg0,arg1
519    #=========================================================
520    #   symbolic tool box starts here:
521    #=========================================================
522    class Symbol(object):
523       """
524       Symbol class.
525    
526       Symbol class objects provide the same functionality as L{numarray.NumArray} and L{escript.Data} objects
527       but they do not have a value and therefore cannot be plotted or visualize. The main purpose is the possibilty
528       calculate derivatives with respect to other Symbols used to define a Symbol.
529    
530       """
531       def __init__(self,shape=(),args=[],dim=None):
532           """
533           Creates an instance of a symbol of a given shape. The symbol may depending on a list of arguments args which may be
534           symbols or any other object.
535    
536           @param args: the arguments of the symbol.
537           @type args: C{list}
538           @param shape: the shape
539           @type shape: C{tuple} of C{int}
540           @param dim: spatial dimension of the symbol. If dim=C{None} the spatial dimension is undefined.  
541           @type dim: C{None} or C{int}  
542    
543           """
544           if len(shape)>4:
545               raise ValueError,"Symbol supports only tensors up to order 4"
546           self.__args=args
547           self.__shape=shape
548           self.__dim=dim
549    
550       def getArgument(self,i=None):
551           """
552           returns the i-th argument of the symbol
553    
554           @param i: index of the argument requested.
555           @type i: C{int} or C{None}
556           @raise IndexError: if the requested index does not exist
557           @return: the vlaue of the i-th argument or i is not specified the list of all arguments.
558           @rtype: a single object or a list of objects
559           """
560           if i==None:
561              return self.__args
562           else:
563              if i<0 or i>=len(self.__args):
564                 raise IndexError,"there are only %s arguments"%len(self.__args)
565              return self.__args[i]
566    
567       def getRank(self):
568           """
569           the rank of the symbol
570    
571           @return: the rank of the symbol. This is length of the shape
572           @rtype: C{int}
573           """
574           return len(self.getShape())
575    
576       def getShape(self):
577           """
578           the shape of the symbol.
579    
580           @return: the shape of the symbol.
581           @rtype: C{tuple} of C{int}
582           """
583           return self.__shape
584    
585       def getDim(self):
586           """
587           the spatial dimension
588    
589           @return: the spatial dimension
590           @rtype: C{int} if the dimension is defined. Otherwise C{None} is returned.
591           """
592           return self.__dim
593      
594       def __str__(self):
595           """
596           a string representation of the symbol.
597           @return: a string representation of the object
598           @rtype: C{str}
599           """
600           args=[]
601           for arg in self.getArgument():
602              args.append(str(arg))
603           try:
604               out=self.getMyCode(args,format="str")
605           except NotImplementedError:
606               out="<Symbol %s>"%id(self)
607           return out
608          
609       def getSubstitutedArguments(self,argvals):
610           """
611           substitutes symbols in the arguments of this object and returns the result as a list.
612    
613           @param argvals: L{Symbol} and their substitutes. The L{Symbol} u in the expression defining this object is replaced by argvals[u].
614           @type argvals: C{dict} with keywords of type L{Symbol}.
615           @rtype: C{list} of objects
616           @return: list of the object assigned to the arguments through substitution or for the arguments which are not L{Symbol} the value assigned to the argument at instantiation.
617           """
618           out=[]
619           for a in self.getArgument():
620              if isinstance(a,Symbol):
621                 out.append(a.substitute(argvals))
622              else:
623                 out.append(a)
624           return out
625    
626       def getDifferentiatedArguments(self,arg):
627           """
628           applifies differentials to the arguments of this object and returns the result as a list.
629    
630           @param arg: the derivative is calculated with respect to arg
631           @type arg: typically L{escript.Symbol} but can also be C{float}, L{escript.Data}, L{numarray.NumArray} depending the involved functions and data.
632           @rtype: C{list} of objects
633           @return: list of object obtained by calculating the derivatives of the argumenst with respct to arg
634           """
635           out=[]
636           for a in self.getArgument():
637              if isinstance(a,Symbol):
638                 out.append(a.substitute(argvals))
639              else:
640                  s=getShape(s)+arg.getShape()
641                  if len(s)>0:
642                     out.append(numarray.zeros(s),numarray.Float64)
643                  else:
644                     out.append(a)
645           return out
646    
647       def isAppropriateValue(self,arg):
648          """
649          checks if the given argument arg can be used as a substitution of this object. The method checks
650          the shape of arg and, if the spatial dimension is defined, the spatial dimension of arg.    
651    
652          @param arg: a given object
653          @type arg: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, C{Symbol}
654          @return: True if arg is a suitbale object to be used for substitution. Otherwise False is returned.
655          @rtype: C{bool}
656          """
657          if isinstance(arg,numarray.NumArray):
658              return arg.shape==self.getShape()
659          elif isinstance(arg,escript.Data):
660              if self.getDim()==None:
661                  return arg.getShape()==self.getShape()
662              elif self.getDim()==arg.getFunctionSpace().getDim():
663                  return arg.getShape()==self.getShape()
664              else:
665                  return False
666          elif isinstance(arg,Symbol):
667              if self.getDim()==None:
668                  return arg.getShape()==self.getShape()
669              elif self.getDim()==arg.getDim():
670                  return arg.getShape()==self.getShape()
671              else:
672                  return False
673          elif isinstance(arg,float):
674              return ()==self.getShape()
675          elif isinstance(arg,int):
676              return ()==self.getShape()
677          else:
678             return False
679    
680       def getMyCode(self,argstrs,format="escript"):
681           """
682           returns a program code that can be used to evaluate the symbol.
683    
684           @param argstrs: gives for each argument a string representing the argument for the evaluation.
685           @type argstrs: C{list} of C{str}.
686           @param format: specifies the format to be used. At the moment only "escript", "str" and "text" are supported.
687           @type format: C{str}
688           @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
689           @rtype: C{str}
690           @raise NotImplementedError: if no implementation for the given format is available
691           @note: This method has to be overwritten by subclasses.
692           """
693           raise NotImplementedError,"no code for %s representation available"%format
694    
695       def substitute(self,argvals):
696          """  
697          assigns new values to symbols in the definition of the symbol.
698          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
699    
700          @param argvals: new values assigned to symbols
701          @type argvals: C{dict} with keywords of type L{Symbol}.
702          @return: result of the substitution process. Operations are executed as much as possible.
703          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
704          @note: this method has to be overwritten by a particular L{Symbol}
705          @raise NotImplementedError: if no implementation for the given format is available
706          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
707          """
708          if argvals.has_key(self):
709             arg=argvals[self]
710             if self.isAppropriateValue(arg):
711                return arg
712             else:
713                raise TypeError,"Symbol: new value is not appropriate."
714          else:
715             raise NotImplementedError,"no substitution in %s avialable"%str(self)
716    
717       def diff(self,arg):
718           """
719           returns the derivative of the symbol with respect to L{Symbol} arg
720    
721           @param arg: the derivative is calculated with respect to arg
722           @type arg: typically L{escript.Symbol} but can also be C{float}, L{escript.Data}, L{numarray.NumArray} depending the involved functions and data.
723           @return: derivative with respect to C{arg}
724           @rtype: typically L{escript.Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
725           @note: this method is overwritten by a particular L{Symbol}
726           """
727           if arg==self:
728              return identity(self.getShape())
729           else:
730              s=self.getShape()+arg.getShape()
731              if len(s)>0:
732                 return numarray.zeros(s,numarray.Float64)
733              else:
734                 return 0.
735    
736       def __neg__(self):
737           """
738           returns -self.
739    
740           @return:  a L{Symbol} representing the negative of the object
741           @rtype: L{DependendSymbol}
742           """
743           return self*(-1.)
744    
745       def __pos__(self):
746           """
747           returns +self.
748    
749           @return:  a L{Symbol} representing the positive of the object
750           @rtype: L{DependendSymbol}
751           """
752           return self*(1.)
753    
754       def __abs__(self):
755           """
756           returns a L{Symbol} representing the absolute value of the object.
757           """
758           return Abs_Symbol(self)
759    
760       def __add__(self,other):
761           """
762           add another object to this object
763    
764           @param other: object to be added to this object
765           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
766           @return:  a L{Symbol} representing the sum of this object and C{other}
767           @rtype: L{DependendSymbol}
768           """
769           return add(self,other)
770    
771       def __radd__(self,other):
772           """
773           add this object to another object
774    
775           @param other: object this object is added to
776           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
777           @return: a L{Symbol} representing the sum of C{other} and this object object
778           @rtype: L{DependendSymbol}
779           """
780           return add(other,self)
781    
782       def __sub__(self,other):
783           """
784           subtracts another object from this object
785    
786           @param other: object to be subtracted from this object
787           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
788           @return: a L{Symbol} representing the difference of C{other} and this object
789           @rtype: L{DependendSymbol}
790           """
791           return add(self,-other)
792    
793       def __rsub__(self,other):
794           """
795           subtracts this object from another object
796    
797           @param other: object this object is been subtracted from
798           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
799           @return: a L{Symbol} representing the difference of this object and C{other}.
800           @rtype: L{DependendSymbol}
801           """
802           return add(-self,other)
803    
804       def __mul__(self,other):
805           """
806           multiplies this object with other object
807    
808           @param other: object to be mutiplied by this object
809           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
810           @return: a L{Symbol} representing the product of the object and C{other}.
811           @rtype: L{DependendSymbol} or 0 if other is identical to zero.
812           """
813           return mult(self,other)
814    
815       def __rmul__(self,other):
816           """
817           multiplies this object with other object
818    
819           @param other: object this object is multiplied with
820           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
821           @return: a L{Symbol} representing the product of C{other} and the object.
822           @rtype: L{DependendSymbol} or 0 if other is identical to zero.
823           """
824           return mult(other,self)
825    
826       def __div__(self,other):
827           """
828           divides this object by other object
829    
830           @param other: object dividing this object
831           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
832           @return: a L{Symbol} representing the quotient of this object and C{other}
833           @rtype: L{DependendSymbol}
834           """
835           return quotient(self,other)
836    
837       def __rdiv__(self,other):
838           """
839           divides this object by other object
840    
841           @param other: object dividing this object
842           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
843           @return: a L{Symbol} representing the quotient of C{other} and this object
844           @rtype: L{DependendSymbol} or 0 if C{other} is identical to zero.
845           """
846           return quotient(other,self)
847    
848       def __pow__(self,other):
849           """
850           raises this object to the power of other
851    
852           @param other: exponent
853           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
854           @return: a L{Symbol} representing the power of this object to C{other}
855           @rtype: L{DependendSymbol} or 1 if C{other} is identical to zero.
856           """
857           return power(self,other)
858    
859       def __rpow__(self,other):
860           """
861           raises an object to the power of this object
862    
863           @param other: basis
864           @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
865           @return: a L{Symbol} representing the power of C{other} to this object
866           @rtype: L{DependendSymbol} or 0 if C{other} is identical to zero.
867           """
868           return power(other,self)
869    
870       def __getitem__(self,index):
871           """
872           returns the slice defined by index
873    
874           @param index: defines a
875           @type index: C{slice} or C{int} or a C{tuple} of them
876           @return: a L{Symbol} representing the slice defined by index
877           @rtype: L{DependendSymbol}
878           """
879           return GetSlice_Symbol(self,index)
880    
881    class DependendSymbol(Symbol):
882       """
883       DependendSymbol extents L{Symbol} by modifying the == operator to allow two instances to be equal.
884       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  
885      
886       Example::
887      
888         u1=Symbol(shape=(3,4),dim=2,args=[4.])
889         u2=Symbol(shape=(3,4),dim=2,args=[4.])
890         print u1==u2
891         False
892      
893       but::
894    
895         u1=DependendSymbol(shape=(3,4),dim=2,args=[4.])
896         u2=DependendSymbol(shape=(3,4),dim=2,args=[4.])
897         u3=DependendSymbol(shape=(2,),dim=2,args=[4.])  
898         print u1==u2, u1==u3
899         True False
900    
901       @note: DependendSymbol should be used as return value of functions with L{Symbol} arguments. This will allow the optimizer to remove redundant function calls.
902       """
903       def __eq__(self,other):
904          """
905          checks if other equals self
906    
907          @param other: any object
908          @return: True if other has the same class like self, and the shape, the spatial diemsnion and the arguments are equal.
909          @rtype: C{bool}
910          """
911          if isinstance(other,DependendSymbol):
912             if self.__class__==other.__class__:  
913                if self.getShape()==other.getShape():
914                  if self.getArgument()==other.getArgument():
915                     if self.getDim()==None or other.getDim()==None or self.getDim()==other.getDim():
916                        return True
917          return False
918    
919       def __ne__(self,other):
920          """
921          checks if other equals self
922    
923          @param other: any object
924          @return: Flase if other has the same class like self, and the shape, the spatial diemsnion and the arguments are equal.
925          @rtype: C{bool}
926          """
927          return not self==other
928    #=========================================================
929    #  Unary operations prserving the shape
930    #========================================================
931    class GetSlice_Symbol(DependendSymbol):
932       """
933       L{Symbol} representing getting a slice for a L{Symbol}
934       """
935       def __init__(self,arg,index):
936          """
937          initialization of wherePositive L{Symbol} with argument arg
938          @param arg: argument
939          @type arg: L{Symbol}.
940          @param index: defines index
941          @type index: C{slice} or C{int} or a C{tuple} of them
942          @raises IndexError: if length of index is larger than rank of arg or a index start or stop is out of range
943          @raises ValueError: if a step is given
944          """
945          if not isinstance(index,tuple): index=(index,)
946          if len(index)>arg.getRank():
947               raise IndexError,"GetSlice_Symbol: index out of range."
948          sh=()
949          index2=()
950          for i in range(len(index)):
951             ix=index[i]
952             if isinstance(ix,int):
953                if ix<0 or ix>=arg.getShape()[i]:
954                   raise ValueError,"GetSlice_Symbol: index out of range."
955                index2=index2+(ix,)
956             else:
957               if not ix.step==None:
958                 raise ValueError,"GetSlice_Symbol: steping is not supported."
959               if ix.start==None:
960                  s=0
961               else:
962                  s=ix.start
963               if ix.stop==None:
964                  e=arg.getShape()[i]
965               else:
966                  e=ix.stop
967                  if e>arg.getShape()[i]:
968                     raise IndexError,"GetSlice_Symbol: index out of range."
969               index2=index2+(slice(s,e),)
970               if e>s:
971                   sh=sh+(e-s,)
972               elif s>e:
973                   raise IndexError,"GetSlice_Symbol: slice start must be less or equal slice end"
974          for i in range(len(index),arg.getRank()):
975              index2=index2+(slice(0,arg.getShape()[i]),)
976              sh=sh+(arg.getShape()[i],)
977          super(GetSlice_Symbol, self).__init__(args=[arg,index2],shape=sh,dim=arg.getDim())
978    
979       def getMyCode(self,argstrs,format="escript"):
980          """
981          returns a program code that can be used to evaluate the symbol.
982    
983          @param argstrs: gives for each argument a string representing the argument for the evaluation.
984          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
985          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
986          @type format: C{str}
987          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
988          @rtype: C{str}
989          @raise NotImplementedError: if the requested format is not available
990          """
991          if format=="escript" or format=="str"  or format=="text":
992             return "%s.__getitem__(%s)"%(argstrs[0],argstrs[1])
993          else:
994             raise NotImplementedError,"GetItem_Symbol does not provide program code for format %s."%format
995    
996       def substitute(self,argvals):
997          """
998          assigns new values to symbols in the definition of the symbol.
999          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1000    
1001          @param argvals: new values assigned to symbols
1002          @type argvals: C{dict} with keywords of type L{Symbol}.
1003          @return: result of the substitution process. Operations are executed as much as possible.
1004          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1005          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1006          """
1007          if argvals.has_key(self):
1008             arg=argvals[self]
1009             if self.isAppropriateValue(arg):
1010                return arg
1011             else:
1012                raise TypeError,"%s: new value is not appropriate."%str(self)
1013          else:
1014             args=self.getSubstitutedArguments(argvals)
1015             arg=args[0]
1016             index=args[1]
1017             return arg.__getitem__(index)
1018    
1019    def log10(arg):
1020       """
1021       returns base-10 logarithm of argument arg
1022    
1023       @param arg: argument
1024       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1025       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1026       @raises TypeError: if the type of the argument is not expected.
1027       """
1028       if isinstance(arg,numarray.NumArray):
1029          return numarray.log10(arg)
1030       elif isinstance(arg,escript.Data):
1031          return arg._log10()
1032       elif isinstance(arg,float):
1033          return math.log10(arg)
1034       elif isinstance(arg,int):
1035          return math.log10(float(arg))
1036       elif isinstance(arg,Symbol):
1037          return log(arg)/log(10.)
1038       else:
1039          raise TypeError,"log10: Unknown argument type."
1040    
1041    def wherePositive(arg):
1042       """
1043       returns mask of positive values of argument arg
1044    
1045       @param arg: argument
1046       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1047       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1048       @raises TypeError: if the type of the argument is not expected.
1049       """
1050       if isinstance(arg,numarray.NumArray):
1051          out=numarray.greater(arg,numarray.zeros(arg.shape,numarray.Float64))*1.
1052          if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1053          return out
1054       elif isinstance(arg,escript.Data):
1055          return arg._wherePositive()
1056       elif isinstance(arg,float):
1057          if arg>0:
1058            return 1.
1059          else:
1060            return 0.
1061       elif isinstance(arg,int):
1062          if arg>0:
1063            return 1.
1064          else:
1065            return 0.
1066       elif isinstance(arg,Symbol):
1067          return WherePositive_Symbol(arg)
1068       else:
1069          raise TypeError,"wherePositive: Unknown argument type."
1070    
1071    class WherePositive_Symbol(DependendSymbol):
1072       """
1073       L{Symbol} representing the result of the mask of positive values function
1074       """
1075       def __init__(self,arg):
1076          """
1077          initialization of wherePositive L{Symbol} with argument arg
1078          @param arg: argument of function
1079          @type arg: typically L{Symbol}.
1080          """
1081          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1082    
1083       def getMyCode(self,argstrs,format="escript"):
1084          """
1085          returns a program code that can be used to evaluate the symbol.
1086    
1087          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1088          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1089          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1090          @type format: C{str}
1091          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1092          @rtype: C{str}
1093          @raise NotImplementedError: if the requested format is not available
1094          """
1095          if isinstance(argstrs,list):
1096              argstrs=argstrs[0]
1097          if format=="escript" or format=="str"  or format=="text":
1098             return "wherePositive(%s)"%argstrs
1099          else:
1100             raise NotImplementedError,"WherePositive_Symbol does not provide program code for format %s."%format
1101    
1102       def substitute(self,argvals):
1103          """
1104          assigns new values to symbols in the definition of the symbol.
1105          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1106    
1107          @param argvals: new values assigned to symbols
1108          @type argvals: C{dict} with keywords of type L{Symbol}.
1109          @return: result of the substitution process. Operations are executed as much as possible.
1110          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1111          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1112          """
1113          if argvals.has_key(self):
1114             arg=argvals[self]
1115             if self.isAppropriateValue(arg):
1116                return arg
1117             else:
1118                raise TypeError,"%s: new value is not appropriate."%str(self)
1119          else:
1120             arg=self.getSubstitutedArguments(argvals)[0]
1121             return wherePositive(arg)
1122    
1123    def whereNegative(arg):
1124       """
1125       returns mask of positive values of argument arg
1126    
1127       @param arg: argument
1128       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1129       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1130       @raises TypeError: if the type of the argument is not expected.
1131       """
1132       if isinstance(arg,numarray.NumArray):
1133          out=numarray.less(arg,numarray.zeros(arg.shape,numarray.Float64))*1.
1134          if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1135          return out
1136       elif isinstance(arg,escript.Data):
1137          return arg._whereNegative()
1138       elif isinstance(arg,float):
1139          if arg<0:
1140            return 1.
1141          else:
1142            return 0.
1143       elif isinstance(arg,int):
1144          if arg<0:
1145            return 1.
1146          else:
1147            return 0.
1148       elif isinstance(arg,Symbol):
1149          return WhereNegative_Symbol(arg)
1150       else:
1151          raise TypeError,"whereNegative: Unknown argument type."
1152    
1153    class WhereNegative_Symbol(DependendSymbol):
1154       """
1155       L{Symbol} representing the result of the mask of positive values function
1156       """
1157       def __init__(self,arg):
1158          """
1159          initialization of whereNegative L{Symbol} with argument arg
1160          @param arg: argument of function
1161          @type arg: typically L{Symbol}.
1162          """
1163          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1164    
1165       def getMyCode(self,argstrs,format="escript"):
1166          """
1167          returns a program code that can be used to evaluate the symbol.
1168    
1169          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1170          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1171          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1172          @type format: C{str}
1173          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1174          @rtype: C{str}
1175          @raise NotImplementedError: if the requested format is not available
1176          """
1177          if isinstance(argstrs,list):
1178              argstrs=argstrs[0]
1179          if format=="escript" or format=="str"  or format=="text":
1180             return "whereNegative(%s)"%argstrs
1181          else:
1182             raise NotImplementedError,"WhereNegative_Symbol does not provide program code for format %s."%format
1183    
1184       def substitute(self,argvals):
1185          """
1186          assigns new values to symbols in the definition of the symbol.
1187          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1188    
1189          @param argvals: new values assigned to symbols
1190          @type argvals: C{dict} with keywords of type L{Symbol}.
1191          @return: result of the substitution process. Operations are executed as much as possible.
1192          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1193          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1194          """
1195          if argvals.has_key(self):
1196             arg=argvals[self]
1197             if self.isAppropriateValue(arg):
1198                return arg
1199             else:
1200                raise TypeError,"%s: new value is not appropriate."%str(self)
1201          else:
1202             arg=self.getSubstitutedArguments(argvals)[0]
1203             return whereNegative(arg)
1204    
1205    def whereNonNegative(arg):
1206       """
1207       returns mask of non-negative values of argument arg
1208    
1209       @param arg: argument
1210       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1211       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1212       @raises TypeError: if the type of the argument is not expected.
1213       """
1214       if isinstance(arg,numarray.NumArray):
1215          out=numarray.greater_equal(arg,numarray.zeros(arg.shape,numarray.Float64))*1.
1216          if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1217          return out
1218       elif isinstance(arg,escript.Data):
1219          return arg._whereNonNegative()
1220       elif isinstance(arg,float):
1221          if arg<0:
1222            return 0.
1223          else:
1224            return 1.
1225       elif isinstance(arg,int):
1226          if arg<0:
1227            return 0.
1228          else:
1229            return 1.
1230       elif isinstance(arg,Symbol):
1231          return 1.-whereNegative(arg)
1232       else:
1233          raise TypeError,"whereNonNegative: Unknown argument type."
1234    
1235    def whereNonPositive(arg):
1236       """
1237       returns mask of non-positive values of argument arg
1238    
1239       @param arg: argument
1240       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1241       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1242       @raises TypeError: if the type of the argument is not expected.
1243       """
1244       if isinstance(arg,numarray.NumArray):
1245          out=numarray.less_equal(arg,numarray.zeros(arg.shape,numarray.Float64))*1.
1246          if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1247          return out
1248       elif isinstance(arg,escript.Data):
1249          return arg._whereNonPositive()
1250       elif isinstance(arg,float):
1251          if arg>0:
1252            return 0.
1253          else:
1254            return 1.
1255       elif isinstance(arg,int):
1256          if arg>0:
1257            return 0.
1258          else:
1259            return 1.
1260       elif isinstance(arg,Symbol):
1261          return 1.-wherePositive(arg)
1262       else:
1263          raise TypeError,"whereNonPositive: Unknown argument type."
1264    
1265    def whereZero(arg,tol=0.):
1266       """
1267       returns mask of zero entries of argument arg
1268    
1269       @param arg: argument
1270       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1271       @param tol: tolerance. values with absolute value less then tol are accepted as zero.
1272       @type tol: C{float}
1273       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1274       @raises TypeError: if the type of the argument is not expected.
1275       """
1276       if isinstance(arg,numarray.NumArray):
1277          out=numarray.less_equal(abs(arg)-tol,numarray.zeros(arg.shape,numarray.Float64))*1.
1278          if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1279          return out
1280       elif isinstance(arg,escript.Data):
1281          return arg._whereZero(tol)
1282       elif isinstance(arg,float):
1283          if abs(arg)<=tol:
1284            return 1.
1285          else:
1286            return 0.
1287       elif isinstance(arg,int):
1288          if abs(float(arg))<=tol:
1289            return 1.
1290          else:
1291            return 0.
1292       elif isinstance(arg,Symbol):
1293          return WhereZero_Symbol(arg,tol)
1294       else:
1295          raise TypeError,"whereZero: Unknown argument type."
1296    
1297    class WhereZero_Symbol(DependendSymbol):
1298       """
1299       L{Symbol} representing the result of the mask of zero entries function
1300       """
1301       def __init__(self,arg,tol=0.):
1302          """
1303          initialization of whereZero L{Symbol} with argument arg
1304          @param arg: argument of function
1305          @type arg: typically L{Symbol}.
1306          """
1307          DependendSymbol.__init__(self,args=[arg,tol],shape=arg.getShape(),dim=arg.getDim())
1308    
1309       def getMyCode(self,argstrs,format="escript"):
1310          """
1311          returns a program code that can be used to evaluate the symbol.
1312    
1313          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1314          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1315          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1316          @type format: C{str}
1317          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1318          @rtype: C{str}
1319          @raise NotImplementedError: if the requested format is not available
1320          """
1321          if format=="escript" or format=="str"  or format=="text":
1322             return "whereZero(%s,tol=%s)"%(argstrs[0],argstrs[1])
1323          else:
1324             raise NotImplementedError,"WhereZero_Symbol does not provide program code for format %s."%format
1325    
1326       def substitute(self,argvals):
1327          """
1328          assigns new values to symbols in the definition of the symbol.
1329          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1330    
1331          @param argvals: new values assigned to symbols
1332          @type argvals: C{dict} with keywords of type L{Symbol}.
1333          @return: result of the substitution process. Operations are executed as much as possible.
1334          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1335          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1336          """
1337          if argvals.has_key(self):
1338             arg=argvals[self]
1339             if self.isAppropriateValue(arg):
1340                return arg
1341             else:
1342                raise TypeError,"%s: new value is not appropriate."%str(self)
1343          else:
1344             arg=self.getSubstitutedArguments(argvals)
1345             return whereZero(arg[0],arg[1])
1346    
1347    def whereNonZero(arg,tol=0.):
1348       """
1349       returns mask of values different from zero of argument arg
1350    
1351       @param arg: argument
1352       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1353       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1354       @raises TypeError: if the type of the argument is not expected.
1355       """
1356       if isinstance(arg,numarray.NumArray):
1357          out=numarray.greater(abs(arg)-tol,numarray.zeros(arg.shape,numarray.Float64))*1.
1358          if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1359          return out
1360       elif isinstance(arg,escript.Data):
1361          return arg._whereNonZero(tol)
1362       elif isinstance(arg,float):
1363          if abs(arg)>tol:
1364            return 1.
1365          else:
1366            return 0.
1367       elif isinstance(arg,int):
1368          if abs(float(arg))>tol:
1369            return 1.
1370          else:
1371            return 0.
1372       elif isinstance(arg,Symbol):
1373          return 1.-whereZero(arg,tol)
1374       else:
1375          raise TypeError,"whereNonZero: Unknown argument type."
1376    
1377    def erf(arg):
1378       """
1379       returns erf of argument arg
1380    
1381       @param arg: argument
1382       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1383       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1384       @raises TypeError: if the type of the argument is not expected.
1385       """
1386       if isinstance(arg,escript.Data):
1387          return arg._erf()
1388       else:
1389          raise TypeError,"erf: Unknown argument type."
1390    
1391    def sin(arg):
1392       """
1393       returns sine of argument arg
1394    
1395       @param arg: argument
1396       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1397       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1398       @raises TypeError: if the type of the argument is not expected.
1399       """
1400       if isinstance(arg,numarray.NumArray):
1401          return numarray.sin(arg)
1402       elif isinstance(arg,escript.Data):
1403          return arg._sin()
1404       elif isinstance(arg,float):
1405          return math.sin(arg)
1406       elif isinstance(arg,int):
1407          return math.sin(arg)
1408       elif isinstance(arg,Symbol):
1409          return Sin_Symbol(arg)
1410       else:
1411          raise TypeError,"sin: Unknown argument type."
1412    
1413    class Sin_Symbol(DependendSymbol):
1414       """
1415       L{Symbol} representing the result of the sine function
1416       """
1417       def __init__(self,arg):
1418          """
1419          initialization of sin L{Symbol} with argument arg
1420          @param arg: argument of function
1421          @type arg: typically L{Symbol}.
1422          """
1423          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1424    
1425       def getMyCode(self,argstrs,format="escript"):
1426          """
1427          returns a program code that can be used to evaluate the symbol.
1428    
1429          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1430          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1431          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1432          @type format: C{str}
1433          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1434          @rtype: C{str}
1435          @raise NotImplementedError: if the requested format is not available
1436          """
1437          if isinstance(argstrs,list):
1438              argstrs=argstrs[0]
1439          if format=="escript" or format=="str"  or format=="text":
1440             return "sin(%s)"%argstrs
1441          else:
1442             raise NotImplementedError,"Sin_Symbol does not provide program code for format %s."%format
1443    
1444       def substitute(self,argvals):
1445          """
1446          assigns new values to symbols in the definition of the symbol.
1447          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1448    
1449          @param argvals: new values assigned to symbols
1450          @type argvals: C{dict} with keywords of type L{Symbol}.
1451          @return: result of the substitution process. Operations are executed as much as possible.
1452          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1453          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1454          """
1455          if argvals.has_key(self):
1456             arg=argvals[self]
1457             if self.isAppropriateValue(arg):
1458                return arg
1459             else:
1460                raise TypeError,"%s: new value is not appropriate."%str(self)
1461          else:
1462             arg=self.getSubstitutedArguments(argvals)[0]
1463             return sin(arg)
1464    
1465       def diff(self,arg):
1466          """
1467          differential of this object
1468    
1469          @param arg: the derivative is calculated with respect to arg
1470          @type arg: L{escript.Symbol}
1471          @return: derivative with respect to C{arg}
1472          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1473          """
1474          if arg==self:
1475             return identity(self.getShape())
1476          else:
1477             myarg=self.getArgument()[0]
1478             val=matchShape(cos(myarg),self.getDifferentiatedArguments(arg)[0])
1479             return val[0]*val[1]
1480    
1481    def cos(arg):
1482       """
1483       returns cosine of argument arg
1484    
1485       @param arg: argument
1486       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1487       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1488       @raises TypeError: if the type of the argument is not expected.
1489       """
1490       if isinstance(arg,numarray.NumArray):
1491          return numarray.cos(arg)
1492       elif isinstance(arg,escript.Data):
1493          return arg._cos()
1494       elif isinstance(arg,float):
1495          return math.cos(arg)
1496       elif isinstance(arg,int):
1497          return math.cos(arg)
1498       elif isinstance(arg,Symbol):
1499          return Cos_Symbol(arg)
1500       else:
1501          raise TypeError,"cos: Unknown argument type."
1502    
1503    class Cos_Symbol(DependendSymbol):
1504       """
1505       L{Symbol} representing the result of the cosine function
1506       """
1507       def __init__(self,arg):
1508          """
1509          initialization of cos L{Symbol} with argument arg
1510          @param arg: argument of function
1511          @type arg: typically L{Symbol}.
1512          """
1513          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1514    
1515       def getMyCode(self,argstrs,format="escript"):
1516          """
1517          returns a program code that can be used to evaluate the symbol.
1518    
1519          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1520          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1521          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1522          @type format: C{str}
1523          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1524          @rtype: C{str}
1525          @raise NotImplementedError: if the requested format is not available
1526          """
1527          if isinstance(argstrs,list):
1528              argstrs=argstrs[0]
1529          if format=="escript" or format=="str"  or format=="text":
1530             return "cos(%s)"%argstrs
1531          else:
1532             raise NotImplementedError,"Cos_Symbol does not provide program code for format %s."%format
1533    
1534       def substitute(self,argvals):
1535          """
1536          assigns new values to symbols in the definition of the symbol.
1537          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1538    
1539          @param argvals: new values assigned to symbols
1540          @type argvals: C{dict} with keywords of type L{Symbol}.
1541          @return: result of the substitution process. Operations are executed as much as possible.
1542          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1543          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1544          """
1545          if argvals.has_key(self):
1546             arg=argvals[self]
1547             if self.isAppropriateValue(arg):
1548                return arg
1549             else:
1550                raise TypeError,"%s: new value is not appropriate."%str(self)
1551          else:
1552             arg=self.getSubstitutedArguments(argvals)[0]
1553             return cos(arg)
1554    
1555       def diff(self,arg):
1556          """
1557          differential of this object
1558    
1559          @param arg: the derivative is calculated with respect to arg
1560          @type arg: L{escript.Symbol}
1561          @return: derivative with respect to C{arg}
1562          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1563          """
1564          if arg==self:
1565             return identity(self.getShape())
1566          else:
1567             myarg=self.getArgument()[0]
1568             val=matchShape(-sin(myarg),self.getDifferentiatedArguments(arg)[0])
1569             return val[0]*val[1]
1570    
1571  def tan(arg):  def tan(arg):
1572       """
1573       returns tangent of argument arg
1574    
1575       @param arg: argument
1576       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1577       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1578       @raises TypeError: if the type of the argument is not expected.
1579       """
1580       if isinstance(arg,numarray.NumArray):
1581          return numarray.tan(arg)
1582       elif isinstance(arg,escript.Data):
1583          return arg._tan()
1584       elif isinstance(arg,float):
1585          return math.tan(arg)
1586       elif isinstance(arg,int):
1587          return math.tan(arg)
1588       elif isinstance(arg,Symbol):
1589          return Tan_Symbol(arg)
1590       else:
1591          raise TypeError,"tan: Unknown argument type."
1592    
1593    class Tan_Symbol(DependendSymbol):
1594       """
1595       L{Symbol} representing the result of the tangent function
1596       """
1597       def __init__(self,arg):
1598          """
1599          initialization of tan L{Symbol} with argument arg
1600          @param arg: argument of function
1601          @type arg: typically L{Symbol}.
1602          """
1603          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1604    
1605       def getMyCode(self,argstrs,format="escript"):
1606          """
1607          returns a program code that can be used to evaluate the symbol.
1608    
1609          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1610          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1611          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1612          @type format: C{str}
1613          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1614          @rtype: C{str}
1615          @raise NotImplementedError: if the requested format is not available
1616          """
1617          if isinstance(argstrs,list):
1618              argstrs=argstrs[0]
1619          if format=="escript" or format=="str"  or format=="text":
1620             return "tan(%s)"%argstrs
1621          else:
1622             raise NotImplementedError,"Tan_Symbol does not provide program code for format %s."%format
1623    
1624       def substitute(self,argvals):
1625          """
1626          assigns new values to symbols in the definition of the symbol.
1627          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1628    
1629          @param argvals: new values assigned to symbols
1630          @type argvals: C{dict} with keywords of type L{Symbol}.
1631          @return: result of the substitution process. Operations are executed as much as possible.
1632          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1633          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1634          """
1635          if argvals.has_key(self):
1636             arg=argvals[self]
1637             if self.isAppropriateValue(arg):
1638                return arg
1639             else:
1640                raise TypeError,"%s: new value is not appropriate."%str(self)
1641          else:
1642             arg=self.getSubstitutedArguments(argvals)[0]
1643             return tan(arg)
1644    
1645       def diff(self,arg):
1646          """
1647          differential of this object
1648    
1649          @param arg: the derivative is calculated with respect to arg
1650          @type arg: L{escript.Symbol}
1651          @return: derivative with respect to C{arg}
1652          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1653          """
1654          if arg==self:
1655             return identity(self.getShape())
1656          else:
1657             myarg=self.getArgument()[0]
1658             val=matchShape(1./cos(myarg)**2,self.getDifferentiatedArguments(arg)[0])
1659             return val[0]*val[1]
1660    
1661    def asin(arg):
1662       """
1663       returns inverse sine of argument arg
1664    
1665       @param arg: argument
1666       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1667       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1668       @raises TypeError: if the type of the argument is not expected.
1669       """
1670       if isinstance(arg,numarray.NumArray):
1671          return numarray.arcsin(arg)
1672       elif isinstance(arg,escript.Data):
1673          return arg._asin()
1674       elif isinstance(arg,float):
1675          return math.asin(arg)
1676       elif isinstance(arg,int):
1677          return math.asin(arg)
1678       elif isinstance(arg,Symbol):
1679          return Asin_Symbol(arg)
1680       else:
1681          raise TypeError,"asin: Unknown argument type."
1682    
1683    class Asin_Symbol(DependendSymbol):
1684       """
1685       L{Symbol} representing the result of the inverse sine function
1686       """
1687       def __init__(self,arg):
1688          """
1689          initialization of asin L{Symbol} with argument arg
1690          @param arg: argument of function
1691          @type arg: typically L{Symbol}.
1692          """
1693          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1694    
1695       def getMyCode(self,argstrs,format="escript"):
1696          """
1697          returns a program code that can be used to evaluate the symbol.
1698    
1699          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1700          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1701          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1702          @type format: C{str}
1703          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1704          @rtype: C{str}
1705          @raise NotImplementedError: if the requested format is not available
1706          """
1707          if isinstance(argstrs,list):
1708              argstrs=argstrs[0]
1709          if format=="escript" or format=="str"  or format=="text":
1710             return "asin(%s)"%argstrs
1711          else:
1712             raise NotImplementedError,"Asin_Symbol does not provide program code for format %s."%format
1713    
1714       def substitute(self,argvals):
1715          """
1716          assigns new values to symbols in the definition of the symbol.
1717          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1718    
1719          @param argvals: new values assigned to symbols
1720          @type argvals: C{dict} with keywords of type L{Symbol}.
1721          @return: result of the substitution process. Operations are executed as much as possible.
1722          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1723          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1724          """
1725          if argvals.has_key(self):
1726             arg=argvals[self]
1727             if self.isAppropriateValue(arg):
1728                return arg
1729             else:
1730                raise TypeError,"%s: new value is not appropriate."%str(self)
1731          else:
1732             arg=self.getSubstitutedArguments(argvals)[0]
1733             return asin(arg)
1734    
1735       def diff(self,arg):
1736          """
1737          differential of this object
1738    
1739          @param arg: the derivative is calculated with respect to arg
1740          @type arg: L{escript.Symbol}
1741          @return: derivative with respect to C{arg}
1742          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1743          """
1744          if arg==self:
1745             return identity(self.getShape())
1746          else:
1747             myarg=self.getArgument()[0]
1748             val=matchShape(1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
1749             return val[0]*val[1]
1750    
1751    def acos(arg):
1752       """
1753       returns inverse cosine of argument arg
1754    
1755       @param arg: argument
1756       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1757       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1758       @raises TypeError: if the type of the argument is not expected.
1759       """
1760       if isinstance(arg,numarray.NumArray):
1761          return numarray.arccos(arg)
1762       elif isinstance(arg,escript.Data):
1763          return arg._acos()
1764       elif isinstance(arg,float):
1765          return math.acos(arg)
1766       elif isinstance(arg,int):
1767          return math.acos(arg)
1768       elif isinstance(arg,Symbol):
1769          return Acos_Symbol(arg)
1770       else:
1771          raise TypeError,"acos: Unknown argument type."
1772    
1773    class Acos_Symbol(DependendSymbol):
1774       """
1775       L{Symbol} representing the result of the inverse cosine function
1776       """
1777       def __init__(self,arg):
1778          """
1779          initialization of acos L{Symbol} with argument arg
1780          @param arg: argument of function
1781          @type arg: typically L{Symbol}.
1782          """
1783          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1784    
1785       def getMyCode(self,argstrs,format="escript"):
1786          """
1787          returns a program code that can be used to evaluate the symbol.
1788    
1789          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1790          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1791          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1792          @type format: C{str}
1793          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1794          @rtype: C{str}
1795          @raise NotImplementedError: if the requested format is not available
1796          """
1797          if isinstance(argstrs,list):
1798              argstrs=argstrs[0]
1799          if format=="escript" or format=="str"  or format=="text":
1800             return "acos(%s)"%argstrs
1801          else:
1802             raise NotImplementedError,"Acos_Symbol does not provide program code for format %s."%format
1803    
1804       def substitute(self,argvals):
1805          """
1806          assigns new values to symbols in the definition of the symbol.
1807          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1808    
1809          @param argvals: new values assigned to symbols
1810          @type argvals: C{dict} with keywords of type L{Symbol}.
1811          @return: result of the substitution process. Operations are executed as much as possible.
1812          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1813          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1814          """
1815          if argvals.has_key(self):
1816             arg=argvals[self]
1817             if self.isAppropriateValue(arg):
1818                return arg
1819             else:
1820                raise TypeError,"%s: new value is not appropriate."%str(self)
1821          else:
1822             arg=self.getSubstitutedArguments(argvals)[0]
1823             return acos(arg)
1824    
1825       def diff(self,arg):
1826          """
1827          differential of this object
1828    
1829          @param arg: the derivative is calculated with respect to arg
1830          @type arg: L{escript.Symbol}
1831          @return: derivative with respect to C{arg}
1832          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1833          """
1834          if arg==self:
1835             return identity(self.getShape())
1836          else:
1837             myarg=self.getArgument()[0]
1838             val=matchShape(-1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
1839             return val[0]*val[1]
1840    
1841    def atan(arg):
1842       """
1843       returns inverse tangent of argument arg
1844    
1845       @param arg: argument
1846       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1847       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1848       @raises TypeError: if the type of the argument is not expected.
1849       """
1850       if isinstance(arg,numarray.NumArray):
1851          return numarray.arctan(arg)
1852       elif isinstance(arg,escript.Data):
1853          return arg._atan()
1854       elif isinstance(arg,float):
1855          return math.atan(arg)
1856       elif isinstance(arg,int):
1857          return math.atan(arg)
1858       elif isinstance(arg,Symbol):
1859          return Atan_Symbol(arg)
1860       else:
1861          raise TypeError,"atan: Unknown argument type."
1862    
1863    class Atan_Symbol(DependendSymbol):
1864       """
1865       L{Symbol} representing the result of the inverse tangent function
1866       """
1867       def __init__(self,arg):
1868          """
1869          initialization of atan L{Symbol} with argument arg
1870          @param arg: argument of function
1871          @type arg: typically L{Symbol}.
1872          """
1873          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1874    
1875       def getMyCode(self,argstrs,format="escript"):
1876          """
1877          returns a program code that can be used to evaluate the symbol.
1878    
1879          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1880          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1881          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1882          @type format: C{str}
1883          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1884          @rtype: C{str}
1885          @raise NotImplementedError: if the requested format is not available
1886          """
1887          if isinstance(argstrs,list):
1888              argstrs=argstrs[0]
1889          if format=="escript" or format=="str"  or format=="text":
1890             return "atan(%s)"%argstrs
1891          else:
1892             raise NotImplementedError,"Atan_Symbol does not provide program code for format %s."%format
1893    
1894       def substitute(self,argvals):
1895          """
1896          assigns new values to symbols in the definition of the symbol.
1897          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1898    
1899          @param argvals: new values assigned to symbols
1900          @type argvals: C{dict} with keywords of type L{Symbol}.
1901          @return: result of the substitution process. Operations are executed as much as possible.
1902          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1903          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1904          """
1905          if argvals.has_key(self):
1906             arg=argvals[self]
1907             if self.isAppropriateValue(arg):
1908                return arg
1909             else:
1910                raise TypeError,"%s: new value is not appropriate."%str(self)
1911          else:
1912             arg=self.getSubstitutedArguments(argvals)[0]
1913             return atan(arg)
1914    
1915       def diff(self,arg):
1916          """
1917          differential of this object
1918    
1919          @param arg: the derivative is calculated with respect to arg
1920          @type arg: L{escript.Symbol}
1921          @return: derivative with respect to C{arg}
1922          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1923          """
1924          if arg==self:
1925             return identity(self.getShape())
1926          else:
1927             myarg=self.getArgument()[0]
1928             val=matchShape(1./(1+myarg**2),self.getDifferentiatedArguments(arg)[0])
1929             return val[0]*val[1]
1930    
1931    def sinh(arg):
1932       """
1933       returns hyperbolic sine of argument arg
1934    
1935       @param arg: argument
1936       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1937       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1938       @raises TypeError: if the type of the argument is not expected.
1939       """
1940       if isinstance(arg,numarray.NumArray):
1941          return numarray.sinh(arg)
1942       elif isinstance(arg,escript.Data):
1943          return arg._sinh()
1944       elif isinstance(arg,float):
1945          return math.sinh(arg)
1946       elif isinstance(arg,int):
1947          return math.sinh(arg)
1948       elif isinstance(arg,Symbol):
1949          return Sinh_Symbol(arg)
1950       else:
1951          raise TypeError,"sinh: Unknown argument type."
1952    
1953    class Sinh_Symbol(DependendSymbol):
1954       """
1955       L{Symbol} representing the result of the hyperbolic sine function
1956       """
1957       def __init__(self,arg):
1958          """
1959          initialization of sinh L{Symbol} with argument arg
1960          @param arg: argument of function
1961          @type arg: typically L{Symbol}.
1962          """
1963          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1964    
1965       def getMyCode(self,argstrs,format="escript"):
1966          """
1967          returns a program code that can be used to evaluate the symbol.
1968    
1969          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1970          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1971          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1972          @type format: C{str}
1973          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1974          @rtype: C{str}
1975          @raise NotImplementedError: if the requested format is not available
1976          """
1977          if isinstance(argstrs,list):
1978              argstrs=argstrs[0]
1979          if format=="escript" or format=="str"  or format=="text":
1980             return "sinh(%s)"%argstrs
1981          else:
1982             raise NotImplementedError,"Sinh_Symbol does not provide program code for format %s."%format
1983    
1984       def substitute(self,argvals):
1985          """
1986          assigns new values to symbols in the definition of the symbol.
1987          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1988    
1989          @param argvals: new values assigned to symbols
1990          @type argvals: C{dict} with keywords of type L{Symbol}.
1991          @return: result of the substitution process. Operations are executed as much as possible.
1992          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1993          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1994          """
1995          if argvals.has_key(self):
1996             arg=argvals[self]
1997             if self.isAppropriateValue(arg):
1998                return arg
1999             else:
2000                raise TypeError,"%s: new value is not appropriate."%str(self)
2001          else:
2002             arg=self.getSubstitutedArguments(argvals)[0]
2003             return sinh(arg)
2004    
2005       def diff(self,arg):
2006          """
2007          differential of this object
2008    
2009          @param arg: the derivative is calculated with respect to arg
2010          @type arg: L{escript.Symbol}
2011          @return: derivative with respect to C{arg}
2012          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2013          """
2014          if arg==self:
2015             return identity(self.getShape())
2016          else:
2017             myarg=self.getArgument()[0]
2018             val=matchShape(cosh(myarg),self.getDifferentiatedArguments(arg)[0])
2019             return val[0]*val[1]
2020    
2021    def cosh(arg):
2022       """
2023       returns hyperbolic cosine of argument arg
2024    
2025       @param arg: argument
2026       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2027       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2028       @raises TypeError: if the type of the argument is not expected.
2029       """
2030       if isinstance(arg,numarray.NumArray):
2031          return numarray.cosh(arg)
2032       elif isinstance(arg,escript.Data):
2033          return arg._cosh()
2034       elif isinstance(arg,float):
2035          return math.cosh(arg)
2036       elif isinstance(arg,int):
2037          return math.cosh(arg)
2038       elif isinstance(arg,Symbol):
2039          return Cosh_Symbol(arg)
2040       else:
2041          raise TypeError,"cosh: Unknown argument type."
2042    
2043    class Cosh_Symbol(DependendSymbol):
2044       """
2045       L{Symbol} representing the result of the hyperbolic cosine function
2046       """
2047       def __init__(self,arg):
2048          """
2049          initialization of cosh L{Symbol} with argument arg
2050          @param arg: argument of function
2051          @type arg: typically L{Symbol}.
2052          """
2053          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2054    
2055       def getMyCode(self,argstrs,format="escript"):
2056          """
2057          returns a program code that can be used to evaluate the symbol.
2058    
2059          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2060          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2061          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2062          @type format: C{str}
2063          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2064          @rtype: C{str}
2065          @raise NotImplementedError: if the requested format is not available
2066          """
2067          if isinstance(argstrs,list):
2068              argstrs=argstrs[0]
2069          if format=="escript" or format=="str"  or format=="text":
2070             return "cosh(%s)"%argstrs
2071          else:
2072             raise NotImplementedError,"Cosh_Symbol does not provide program code for format %s."%format
2073    
2074       def substitute(self,argvals):
2075          """
2076          assigns new values to symbols in the definition of the symbol.
2077          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2078    
2079          @param argvals: new values assigned to symbols
2080          @type argvals: C{dict} with keywords of type L{Symbol}.
2081          @return: result of the substitution process. Operations are executed as much as possible.
2082          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2083          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2084          """
2085          if argvals.has_key(self):
2086             arg=argvals[self]
2087             if self.isAppropriateValue(arg):
2088                return arg
2089             else:
2090                raise TypeError,"%s: new value is not appropriate."%str(self)
2091          else:
2092             arg=self.getSubstitutedArguments(argvals)[0]
2093             return cosh(arg)
2094    
2095       def diff(self,arg):
2096          """
2097          differential of this object
2098    
2099          @param arg: the derivative is calculated with respect to arg
2100          @type arg: L{escript.Symbol}
2101          @return: derivative with respect to C{arg}
2102          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2103          """
2104          if arg==self:
2105             return identity(self.getShape())
2106          else:
2107             myarg=self.getArgument()[0]
2108             val=matchShape(sinh(myarg),self.getDifferentiatedArguments(arg)[0])
2109             return val[0]*val[1]
2110    
2111    def tanh(arg):
2112       """
2113       returns hyperbolic tangent of argument arg
2114    
2115       @param arg: argument
2116       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2117       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2118       @raises TypeError: if the type of the argument is not expected.
2119       """
2120       if isinstance(arg,numarray.NumArray):
2121          return numarray.tanh(arg)
2122       elif isinstance(arg,escript.Data):
2123          return arg._tanh()
2124       elif isinstance(arg,float):
2125          return math.tanh(arg)
2126       elif isinstance(arg,int):
2127          return math.tanh(arg)
2128       elif isinstance(arg,Symbol):
2129          return Tanh_Symbol(arg)
2130       else:
2131          raise TypeError,"tanh: Unknown argument type."
2132    
2133    class Tanh_Symbol(DependendSymbol):
2134       """
2135       L{Symbol} representing the result of the hyperbolic tangent function
2136       """
2137       def __init__(self,arg):
2138          """
2139          initialization of tanh L{Symbol} with argument arg
2140          @param arg: argument of function
2141          @type arg: typically L{Symbol}.
2142          """
2143          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2144    
2145       def getMyCode(self,argstrs,format="escript"):
2146          """
2147          returns a program code that can be used to evaluate the symbol.
2148    
2149          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2150          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2151          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2152          @type format: C{str}
2153          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2154          @rtype: C{str}
2155          @raise NotImplementedError: if the requested format is not available
2156          """
2157          if isinstance(argstrs,list):
2158              argstrs=argstrs[0]
2159          if format=="escript" or format=="str"  or format=="text":
2160             return "tanh(%s)"%argstrs
2161          else:
2162             raise NotImplementedError,"Tanh_Symbol does not provide program code for format %s."%format
2163    
2164       def substitute(self,argvals):
2165          """
2166          assigns new values to symbols in the definition of the symbol.
2167          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2168    
2169          @param argvals: new values assigned to symbols
2170          @type argvals: C{dict} with keywords of type L{Symbol}.
2171          @return: result of the substitution process. Operations are executed as much as possible.
2172          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2173          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2174          """
2175          if argvals.has_key(self):
2176             arg=argvals[self]
2177             if self.isAppropriateValue(arg):
2178                return arg
2179             else:
2180                raise TypeError,"%s: new value is not appropriate."%str(self)
2181          else:
2182             arg=self.getSubstitutedArguments(argvals)[0]
2183             return tanh(arg)
2184    
2185       def diff(self,arg):
2186          """
2187          differential of this object
2188    
2189          @param arg: the derivative is calculated with respect to arg
2190          @type arg: L{escript.Symbol}
2191          @return: derivative with respect to C{arg}
2192          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2193          """
2194          if arg==self:
2195             return identity(self.getShape())
2196          else:
2197             myarg=self.getArgument()[0]
2198             val=matchShape(1./cosh(myarg)**2,self.getDifferentiatedArguments(arg)[0])
2199             return val[0]*val[1]
2200    
2201    def asinh(arg):
2202       """
2203       returns inverse hyperbolic sine of argument arg
2204    
2205       @param arg: argument
2206       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2207       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2208       @raises TypeError: if the type of the argument is not expected.
2209       """
2210       if isinstance(arg,numarray.NumArray):
2211          return numarray.arcsinh(arg)
2212       elif isinstance(arg,escript.Data):
2213          return arg._asinh()
2214       elif isinstance(arg,float):
2215          return numarray.arcsinh(arg)
2216       elif isinstance(arg,int):
2217          return numarray.arcsinh(float(arg))
2218       elif isinstance(arg,Symbol):
2219          return Asinh_Symbol(arg)
2220       else:
2221          raise TypeError,"asinh: Unknown argument type."
2222    
2223    class Asinh_Symbol(DependendSymbol):
2224       """
2225       L{Symbol} representing the result of the inverse hyperbolic sine function
2226       """
2227       def __init__(self,arg):
2228          """
2229          initialization of asinh L{Symbol} with argument arg
2230          @param arg: argument of function
2231          @type arg: typically L{Symbol}.
2232          """
2233          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2234    
2235       def getMyCode(self,argstrs,format="escript"):
2236          """
2237          returns a program code that can be used to evaluate the symbol.
2238    
2239          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2240          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2241          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2242          @type format: C{str}
2243          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2244          @rtype: C{str}
2245          @raise NotImplementedError: if the requested format is not available
2246          """
2247          if isinstance(argstrs,list):
2248              argstrs=argstrs[0]
2249          if format=="escript" or format=="str"  or format=="text":
2250             return "asinh(%s)"%argstrs
2251          else:
2252             raise NotImplementedError,"Asinh_Symbol does not provide program code for format %s."%format
2253    
2254       def substitute(self,argvals):
2255          """
2256          assigns new values to symbols in the definition of the symbol.
2257          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2258    
2259          @param argvals: new values assigned to symbols
2260          @type argvals: C{dict} with keywords of type L{Symbol}.
2261          @return: result of the substitution process. Operations are executed as much as possible.
2262          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2263          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2264          """
2265          if argvals.has_key(self):
2266             arg=argvals[self]
2267             if self.isAppropriateValue(arg):
2268                return arg
2269             else:
2270                raise TypeError,"%s: new value is not appropriate."%str(self)
2271          else:
2272             arg=self.getSubstitutedArguments(argvals)[0]
2273             return asinh(arg)
2274    
2275       def diff(self,arg):
2276          """
2277          differential of this object
2278    
2279          @param arg: the derivative is calculated with respect to arg
2280          @type arg: L{escript.Symbol}
2281          @return: derivative with respect to C{arg}
2282          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2283          """
2284          if arg==self:
2285             return identity(self.getShape())
2286          else:
2287             myarg=self.getArgument()[0]
2288             val=matchShape(1./sqrt(myarg**2+1),self.getDifferentiatedArguments(arg)[0])
2289             return val[0]*val[1]
2290    
2291    def acosh(arg):
2292       """
2293       returns inverse hyperolic cosine of argument arg
2294    
2295       @param arg: argument
2296       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2297       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2298       @raises TypeError: if the type of the argument is not expected.
2299       """
2300       if isinstance(arg,numarray.NumArray):
2301          return numarray.arccosh(arg)
2302       elif isinstance(arg,escript.Data):
2303          return arg._acosh()
2304       elif isinstance(arg,float):
2305          return numarray.arccosh(arg)
2306       elif isinstance(arg,int):
2307          return numarray.arccosh(float(arg))
2308       elif isinstance(arg,Symbol):
2309          return Acosh_Symbol(arg)
2310       else:
2311          raise TypeError,"acosh: Unknown argument type."
2312    
2313    class Acosh_Symbol(DependendSymbol):
2314       """
2315       L{Symbol} representing the result of the inverse hyperolic cosine function
2316       """
2317       def __init__(self,arg):
2318          """
2319          initialization of acosh L{Symbol} with argument arg
2320          @param arg: argument of function
2321          @type arg: typically L{Symbol}.
2322          """
2323          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2324    
2325       def getMyCode(self,argstrs,format="escript"):
2326          """
2327          returns a program code that can be used to evaluate the symbol.
2328    
2329          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2330          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2331          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2332          @type format: C{str}
2333          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2334          @rtype: C{str}
2335          @raise NotImplementedError: if the requested format is not available
2336          """
2337          if isinstance(argstrs,list):
2338              argstrs=argstrs[0]
2339          if format=="escript" or format=="str"  or format=="text":
2340             return "acosh(%s)"%argstrs
2341          else:
2342             raise NotImplementedError,"Acosh_Symbol does not provide program code for format %s."%format
2343    
2344       def substitute(self,argvals):
2345          """
2346          assigns new values to symbols in the definition of the symbol.
2347          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2348    
2349          @param argvals: new values assigned to symbols
2350          @type argvals: C{dict} with keywords of type L{Symbol}.
2351          @return: result of the substitution process. Operations are executed as much as possible.
2352          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2353          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2354          """
2355          if argvals.has_key(self):
2356             arg=argvals[self]
2357             if self.isAppropriateValue(arg):
2358                return arg
2359             else:
2360                raise TypeError,"%s: new value is not appropriate."%str(self)
2361          else:
2362             arg=self.getSubstitutedArguments(argvals)[0]
2363             return acosh(arg)
2364    
2365       def diff(self,arg):
2366          """
2367          differential of this object
2368    
2369          @param arg: the derivative is calculated with respect to arg
2370          @type arg: L{escript.Symbol}
2371          @return: derivative with respect to C{arg}
2372          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2373          """
2374          if arg==self:
2375             return identity(self.getShape())
2376          else:
2377             myarg=self.getArgument()[0]
2378             val=matchShape(1./sqrt(myarg**2-1),self.getDifferentiatedArguments(arg)[0])
2379             return val[0]*val[1]
2380    
2381    def atanh(arg):
2382       """
2383       returns inverse hyperbolic tangent of argument arg
2384    
2385       @param arg: argument
2386       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2387       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2388       @raises TypeError: if the type of the argument is not expected.
2389       """
2390       if isinstance(arg,numarray.NumArray):
2391          return numarray.arctanh(arg)
2392       elif isinstance(arg,escript.Data):
2393          return arg._atanh()
2394       elif isinstance(arg,float):
2395          return numarray.arctanh(arg)
2396       elif isinstance(arg,int):
2397          return numarray.arctanh(float(arg))
2398       elif isinstance(arg,Symbol):
2399          return Atanh_Symbol(arg)
2400       else:
2401          raise TypeError,"atanh: Unknown argument type."
2402    
2403    class Atanh_Symbol(DependendSymbol):
2404       """
2405       L{Symbol} representing the result of the inverse hyperbolic tangent function
2406       """
2407       def __init__(self,arg):
2408          """
2409          initialization of atanh L{Symbol} with argument arg
2410          @param arg: argument of function
2411          @type arg: typically L{Symbol}.
2412          """
2413          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2414    
2415       def getMyCode(self,argstrs,format="escript"):
2416          """
2417          returns a program code that can be used to evaluate the symbol.
2418    
2419          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2420          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2421          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2422          @type format: C{str}
2423          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2424          @rtype: C{str}
2425          @raise NotImplementedError: if the requested format is not available
2426          """
2427          if isinstance(argstrs,list):
2428              argstrs=argstrs[0]
2429          if format=="escript" or format=="str"  or format=="text":
2430             return "atanh(%s)"%argstrs
2431          else:
2432             raise NotImplementedError,"Atanh_Symbol does not provide program code for format %s."%format
2433    
2434       def substitute(self,argvals):
2435          """
2436          assigns new values to symbols in the definition of the symbol.
2437          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2438    
2439          @param argvals: new values assigned to symbols
2440          @type argvals: C{dict} with keywords of type L{Symbol}.
2441          @return: result of the substitution process. Operations are executed as much as possible.
2442          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2443          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2444          """
2445          if argvals.has_key(self):
2446             arg=argvals[self]
2447             if self.isAppropriateValue(arg):
2448                return arg
2449             else:
2450                raise TypeError,"%s: new value is not appropriate."%str(self)
2451          else:
2452             arg=self.getSubstitutedArguments(argvals)[0]
2453             return atanh(arg)
2454    
2455       def diff(self,arg):
2456          """
2457          differential of this object
2458    
2459          @param arg: the derivative is calculated with respect to arg
2460          @type arg: L{escript.Symbol}
2461          @return: derivative with respect to C{arg}
2462          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2463          """
2464          if arg==self:
2465             return identity(self.getShape())
2466          else:
2467             myarg=self.getArgument()[0]
2468             val=matchShape(1./(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2469             return val[0]*val[1]
2470    
2471    def exp(arg):
2472       """
2473       returns exponential of argument arg
2474    
2475       @param arg: argument
2476       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2477       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2478       @raises TypeError: if the type of the argument is not expected.
2479       """
2480       if isinstance(arg,numarray.NumArray):
2481          return numarray.exp(arg)
2482       elif isinstance(arg,escript.Data):
2483          return arg._exp()
2484       elif isinstance(arg,float):
2485          return math.exp(arg)
2486       elif isinstance(arg,int):
2487          return math.exp(arg)
2488       elif isinstance(arg,Symbol):
2489          return Exp_Symbol(arg)
2490       else:
2491          raise TypeError,"exp: Unknown argument type."
2492    
2493    class Exp_Symbol(DependendSymbol):
2494       """
2495       L{Symbol} representing the result of the exponential function
2496       """
2497       def __init__(self,arg):
2498          """
2499          initialization of exp L{Symbol} with argument arg
2500          @param arg: argument of function
2501          @type arg: typically L{Symbol}.
2502          """
2503          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2504    
2505       def getMyCode(self,argstrs,format="escript"):
2506          """
2507          returns a program code that can be used to evaluate the symbol.
2508    
2509          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2510          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2511          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2512          @type format: C{str}
2513          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2514          @rtype: C{str}
2515          @raise NotImplementedError: if the requested format is not available
2516          """
2517          if isinstance(argstrs,list):
2518              argstrs=argstrs[0]
2519          if format=="escript" or format=="str"  or format=="text":
2520             return "exp(%s)"%argstrs
2521          else:
2522             raise NotImplementedError,"Exp_Symbol does not provide program code for format %s."%format
2523    
2524       def substitute(self,argvals):
2525          """
2526          assigns new values to symbols in the definition of the symbol.
2527          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2528    
2529          @param argvals: new values assigned to symbols
2530          @type argvals: C{dict} with keywords of type L{Symbol}.
2531          @return: result of the substitution process. Operations are executed as much as possible.
2532          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2533          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2534          """
2535          if argvals.has_key(self):
2536             arg=argvals[self]
2537             if self.isAppropriateValue(arg):
2538                return arg
2539             else:
2540                raise TypeError,"%s: new value is not appropriate."%str(self)
2541          else:
2542             arg=self.getSubstitutedArguments(argvals)[0]
2543             return exp(arg)
2544    
2545       def diff(self,arg):
2546          """
2547          differential of this object
2548    
2549          @param arg: the derivative is calculated with respect to arg
2550          @type arg: L{escript.Symbol}
2551          @return: derivative with respect to C{arg}
2552          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2553          """
2554          if arg==self:
2555             return identity(self.getShape())
2556          else:
2557             myarg=self.getArgument()[0]
2558             val=matchShape(self,self.getDifferentiatedArguments(arg)[0])
2559             return val[0]*val[1]
2560    
2561    def sqrt(arg):
2562       """
2563       returns square root of argument arg
2564    
2565       @param arg: argument
2566       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2567       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2568       @raises TypeError: if the type of the argument is not expected.
2569       """
2570       if isinstance(arg,numarray.NumArray):
2571          return numarray.sqrt(arg)
2572       elif isinstance(arg,escript.Data):
2573          return arg._sqrt()
2574       elif isinstance(arg,float):
2575          return math.sqrt(arg)
2576       elif isinstance(arg,int):
2577          return math.sqrt(arg)
2578       elif isinstance(arg,Symbol):
2579          return Sqrt_Symbol(arg)
2580       else:
2581          raise TypeError,"sqrt: Unknown argument type."
2582    
2583    class Sqrt_Symbol(DependendSymbol):
2584       """
2585       L{Symbol} representing the result of the square root function
2586       """
2587       def __init__(self,arg):
2588          """
2589          initialization of sqrt L{Symbol} with argument arg
2590          @param arg: argument of function
2591          @type arg: typically L{Symbol}.
2592          """
2593          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2594    
2595       def getMyCode(self,argstrs,format="escript"):
2596          """
2597          returns a program code that can be used to evaluate the symbol.
2598    
2599          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2600          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2601          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2602          @type format: C{str}
2603          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2604          @rtype: C{str}
2605          @raise NotImplementedError: if the requested format is not available
2606          """
2607          if isinstance(argstrs,list):
2608              argstrs=argstrs[0]
2609          if format=="escript" or format=="str"  or format=="text":
2610             return "sqrt(%s)"%argstrs
2611          else:
2612             raise NotImplementedError,"Sqrt_Symbol does not provide program code for format %s."%format
2613    
2614       def substitute(self,argvals):
2615          """
2616          assigns new values to symbols in the definition of the symbol.
2617          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2618    
2619          @param argvals: new values assigned to symbols
2620          @type argvals: C{dict} with keywords of type L{Symbol}.
2621          @return: result of the substitution process. Operations are executed as much as possible.
2622          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2623          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2624          """
2625          if argvals.has_key(self):
2626             arg=argvals[self]
2627             if self.isAppropriateValue(arg):
2628                return arg
2629             else:
2630                raise TypeError,"%s: new value is not appropriate."%str(self)
2631          else:
2632             arg=self.getSubstitutedArguments(argvals)[0]
2633             return sqrt(arg)
2634    
2635       def diff(self,arg):
2636          """
2637          differential of this object
2638    
2639          @param arg: the derivative is calculated with respect to arg
2640          @type arg: L{escript.Symbol}
2641          @return: derivative with respect to C{arg}
2642          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2643          """
2644          if arg==self:
2645             return identity(self.getShape())
2646          else:
2647             myarg=self.getArgument()[0]
2648             val=matchShape(0.5/self,self.getDifferentiatedArguments(arg)[0])
2649             return val[0]*val[1]
2650    
2651    def log(arg):
2652       """
2653       returns natural logarithm of argument arg
2654    
2655       @param arg: argument
2656       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2657       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2658       @raises TypeError: if the type of the argument is not expected.
2659       """
2660       if isinstance(arg,numarray.NumArray):
2661          return numarray.log(arg)
2662       elif isinstance(arg,escript.Data):
2663          return arg._log()
2664       elif isinstance(arg,float):
2665          return math.log(arg)
2666       elif isinstance(arg,int):
2667          return math.log(arg)
2668       elif isinstance(arg,Symbol):
2669          return Log_Symbol(arg)
2670       else:
2671          raise TypeError,"log: Unknown argument type."
2672    
2673    class Log_Symbol(DependendSymbol):
2674       """
2675       L{Symbol} representing the result of the natural logarithm function
2676       """
2677       def __init__(self,arg):
2678          """
2679          initialization of log L{Symbol} with argument arg
2680          @param arg: argument of function
2681          @type arg: typically L{Symbol}.
2682          """
2683          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2684    
2685       def getMyCode(self,argstrs,format="escript"):
2686          """
2687          returns a program code that can be used to evaluate the symbol.
2688    
2689          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2690          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2691          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2692          @type format: C{str}
2693          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2694          @rtype: C{str}
2695          @raise NotImplementedError: if the requested format is not available
2696          """
2697          if isinstance(argstrs,list):
2698              argstrs=argstrs[0]
2699          if format=="escript" or format=="str"  or format=="text":
2700             return "log(%s)"%argstrs
2701          else:
2702             raise NotImplementedError,"Log_Symbol does not provide program code for format %s."%format
2703    
2704       def substitute(self,argvals):
2705          """
2706          assigns new values to symbols in the definition of the symbol.
2707          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2708    
2709          @param argvals: new values assigned to symbols
2710          @type argvals: C{dict} with keywords of type L{Symbol}.
2711          @return: result of the substitution process. Operations are executed as much as possible.
2712          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2713          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2714          """
2715          if argvals.has_key(self):
2716             arg=argvals[self]
2717             if self.isAppropriateValue(arg):
2718                return arg
2719             else:
2720                raise TypeError,"%s: new value is not appropriate."%str(self)
2721          else:
2722             arg=self.getSubstitutedArguments(argvals)[0]
2723             return log(arg)
2724    
2725       def diff(self,arg):
2726          """
2727          differential of this object
2728    
2729          @param arg: the derivative is calculated with respect to arg
2730          @type arg: L{escript.Symbol}
2731          @return: derivative with respect to C{arg}
2732          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2733          """
2734          if arg==self:
2735             return identity(self.getShape())
2736          else:
2737             myarg=self.getArgument()[0]
2738             val=matchShape(1./arg,self.getDifferentiatedArguments(arg)[0])
2739             return val[0]*val[1]
2740    
2741    def sign(arg):
2742       """
2743       returns sign of argument arg
2744    
2745       @param arg: argument
2746       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2747       @rtype: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2748       @raises TypeError: if the type of the argument is not expected.
2749       """
2750       if isinstance(arg,numarray.NumArray):
2751          return wherePositive(arg)-whereNegative(arg)
2752       elif isinstance(arg,escript.Data):
2753          return arg._sign()
2754       elif isinstance(arg,float):
2755          if arg>0:
2756            return 1.
2757          elif arg<0:
2758            return -1.
2759          else:
2760            return 0.
2761       elif isinstance(arg,int):
2762          if float(arg)>0:
2763            return 1.
2764          elif float(arg)<0:
2765            return -1.
2766          else:
2767            return 0.
2768       elif isinstance(arg,Symbol):
2769          return wherePositive(arg)-whereNegative(arg)
2770       else:
2771          raise TypeError,"sign: Unknown argument type."
2772    
2773    class Abs_Symbol(DependendSymbol):
2774       """
2775       L{Symbol} representing the result of the absolute value function
2776       """
2777       def __init__(self,arg):
2778          """
2779          initialization of abs L{Symbol} with argument arg
2780          @param arg: argument of function
2781          @type arg: typically L{Symbol}.
2782          """
2783          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2784    
2785       def getMyCode(self,argstrs,format="escript"):
2786          """
2787          returns a program code that can be used to evaluate the symbol.
2788    
2789          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2790          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2791          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2792          @type format: C{str}
2793          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2794          @rtype: C{str}
2795          @raise NotImplementedError: if the requested format is not available
2796          """
2797          if isinstance(argstrs,list):
2798              argstrs=argstrs[0]
2799          if format=="escript" or format=="str"  or format=="text":
2800             return "abs(%s)"%argstrs
2801          else:
2802             raise NotImplementedError,"Abs_Symbol does not provide program code for format %s."%format
2803    
2804       def substitute(self,argvals):
2805          """
2806          assigns new values to symbols in the definition of the symbol.
2807          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2808    
2809          @param argvals: new values assigned to symbols
2810          @type argvals: C{dict} with keywords of type L{Symbol}.
2811          @return: result of the substitution process. Operations are executed as much as possible.
2812          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2813          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2814          """
2815          if argvals.has_key(self):
2816             arg=argvals[self]
2817             if self.isAppropriateValue(arg):
2818                return arg
2819             else:
2820                raise TypeError,"%s: new value is not appropriate."%str(self)
2821          else:
2822             arg=self.getSubstitutedArguments(argvals)[0]
2823             return abs(arg)
2824    
2825       def diff(self,arg):
2826          """
2827          differential of this object
2828    
2829          @param arg: the derivative is calculated with respect to arg
2830          @type arg: L{escript.Symbol}
2831          @return: derivative with respect to C{arg}
2832          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2833          """
2834          if arg==self:
2835             return identity(self.getShape())
2836          else:
2837             myarg=self.getArgument()[0]
2838             val=matchShape(sign(myarg),self.getDifferentiatedArguments(arg)[0])
2839             return val[0]*val[1]
2840    
2841    def minval(arg):
2842       """
2843       returns minimum value over all components of arg at each data point
2844    
2845       @param arg: argument
2846       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2847       @rtype: C{float}, L{escript.Data}, L{Symbol} depending on the type of arg.
2848       @raises TypeError: if the type of the argument is not expected.
2849       """
2850       if isinstance(arg,numarray.NumArray):
2851          if arg.rank==0:
2852             return float(arg)
2853          else:
2854             return arg.min()
2855       elif isinstance(arg,escript.Data):
2856          return arg._minval()
2857       elif isinstance(arg,float):
2858          return arg
2859       elif isinstance(arg,int):
2860          return float(arg)
2861       elif isinstance(arg,Symbol):
2862          return Minval_Symbol(arg)
2863       else:
2864          raise TypeError,"minval: Unknown argument type."
2865    
2866    class Minval_Symbol(DependendSymbol):
2867       """
2868       L{Symbol} representing the result of the minimum value function
2869       """
2870       def __init__(self,arg):
2871          """
2872          initialization of minimum value L{Symbol} with argument arg
2873          @param arg: argument of function
2874          @type arg: typically L{Symbol}.
2875          """
2876          DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
2877    
2878       def getMyCode(self,argstrs,format="escript"):
2879          """
2880          returns a program code that can be used to evaluate the symbol.
2881    
2882          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2883          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2884          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2885          @type format: C{str}
2886          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2887          @rtype: C{str}
2888          @raise NotImplementedError: if the requested format is not available
2889          """
2890          if isinstance(argstrs,list):
2891              argstrs=argstrs[0]
2892          if format=="escript" or format=="str"  or format=="text":
2893             return "minval(%s)"%argstrs
2894          else:
2895             raise NotImplementedError,"Minval_Symbol does not provide program code for format %s."%format
2896    
2897       def substitute(self,argvals):
2898          """
2899          assigns new values to symbols in the definition of the symbol.
2900          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2901    
2902          @param argvals: new values assigned to symbols
2903          @type argvals: C{dict} with keywords of type L{Symbol}.
2904          @return: result of the substitution process. Operations are executed as much as possible.
2905          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2906          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2907          """
2908          if argvals.has_key(self):
2909             arg=argvals[self]
2910             if self.isAppropriateValue(arg):
2911                return arg
2912             else:
2913                raise TypeError,"%s: new value is not appropriate."%str(self)
2914          else:
2915             arg=self.getSubstitutedArguments(argvals)[0]
2916             return minval(arg)
2917    
2918    def maxval(arg):
2919       """
2920       returns maximum value over all components of arg at each data point
2921    
2922       @param arg: argument
2923       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2924       @rtype: C{float}, L{escript.Data}, L{Symbol} depending on the type of arg.
2925       @raises TypeError: if the type of the argument is not expected.
2926       """
2927       if isinstance(arg,numarray.NumArray):
2928          if arg.rank==0:
2929             return float(arg)
2930          else:
2931             return arg.max()
2932       elif isinstance(arg,escript.Data):
2933          return arg._maxval()
2934       elif isinstance(arg,float):
2935          return arg
2936       elif isinstance(arg,int):
2937          return float(arg)
2938       elif isinstance(arg,Symbol):
2939          return Maxval_Symbol(arg)
2940       else:
2941          raise TypeError,"maxval: Unknown argument type."
2942    
2943    class Maxval_Symbol(DependendSymbol):
2944       """
2945       L{Symbol} representing the result of the maximum value function
2946       """
2947       def __init__(self,arg):
2948          """
2949          initialization of maximum value L{Symbol} with argument arg
2950          @param arg: argument of function
2951          @type arg: typically L{Symbol}.
2952          """
2953          DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
2954    
2955       def getMyCode(self,argstrs,format="escript"):
2956          """
2957          returns a program code that can be used to evaluate the symbol.
2958    
2959          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2960          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2961          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2962          @type format: C{str}
2963          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2964          @rtype: C{str}
2965          @raise NotImplementedError: if the requested format is not available
2966          """
2967          if isinstance(argstrs,list):
2968              argstrs=argstrs[0]
2969          if format=="escript" or format=="str"  or format=="text":
2970             return "maxval(%s)"%argstrs
2971          else:
2972             raise NotImplementedError,"Maxval_Symbol does not provide program code for format %s."%format
2973    
2974       def substitute(self,argvals):
2975          """
2976          assigns new values to symbols in the definition of the symbol.
2977          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2978    
2979          @param argvals: new values assigned to symbols
2980          @type argvals: C{dict} with keywords of type L{Symbol}.
2981          @return: result of the substitution process. Operations are executed as much as possible.
2982          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2983          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2984          """
2985          if argvals.has_key(self):
2986             arg=argvals[self]
2987             if self.isAppropriateValue(arg):
2988                return arg
2989             else:
2990                raise TypeError,"%s: new value is not appropriate."%str(self)
2991          else:
2992             arg=self.getSubstitutedArguments(argvals)[0]
2993             return maxval(arg)
2994    
2995    def length(arg):
2996       """
2997       returns length/Euclidean norm of argument arg at each data point
2998    
2999       @param arg: argument
3000       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
3001       @rtype: C{float}, L{escript.Data}, L{Symbol} depending on the type of arg.
3002       """
3003       return sqrt(inner(arg,arg))
3004    
3005    def trace(arg,axis_offset=0):
3006       """
3007       returns the trace of arg which the sum of arg[k,k] over k.
3008    
3009       @param arg: argument
3010       @type arg: L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
3011       @param axis_offset: C{axis_offset} to components to sum over. C{axis_offset} must be non-negative and less than the rank of arg +1. The dimensions on component
3012                      C{axis_offset} and axis_offset+1 must be equal.
3013       @type axis_offset: C{int}
3014       @return: trace of arg. The rank of the returned object is minus 2 of the rank of arg.
3015       @rtype: L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
3016       """
3017       if isinstance(arg,numarray.NumArray):
3018          sh=arg.shape
3019          if len(sh)<2:
3020            raise ValueError,"rank of argument must be greater than 1"
3021          if axis_offset<0 or axis_offset>len(sh)-2:
3022            raise ValueError,"axis_offset must be between 0 and %s"%len(sh)-2
3023          s1=1
3024          for i in range(axis_offset): s1*=sh[i]
3025          s2=1
3026          for i in range(axis_offset+2,len(sh)): s2*=sh[i]
3027          if not sh[axis_offset] == sh[axis_offset+1]:
3028            raise ValueError,"dimensions of component %s and %s must match."%(axis_offset.axis_offset+1)
3029          arg_reshaped=numarray.reshape(arg,(s1,sh[axis_offset],sh[axis_offset],s2))
3030          out=numarray.zeros([s1,s2],numarray.Float64)
3031          for i1 in range(s1):
3032            for i2 in range(s2):
3033                for j in range(sh[axis_offset]): out[i1,i2]+=arg_reshaped[i1,j,j,i2]
3034          out.resize(sh[:axis_offset]+sh[axis_offset+2:])
3035          return out
3036       elif isinstance(arg,escript.Data):
3037          if arg.getRank()<2:
3038            raise ValueError,"rank of argument must be greater than 1"
3039          if axis_offset<0 or axis_offset>arg.getRank()-2:
3040            raise ValueError,"axis_offset must be between 0 and %s"%arg.getRank()-2
3041          s=list(arg.getShape())        
3042          if not s[axis_offset] == s[axis_offset+1]:
3043            raise ValueError,"dimensions of component %s and %s must match."%(axis_offset.axis_offset+1)
3044          return arg._trace(axis_offset)
3045       elif isinstance(arg,float):
3046          raise TypeError,"illegal argument type float."
3047       elif isinstance(arg,int):
3048          raise TypeError,"illegal argument type int."
3049       elif isinstance(arg,Symbol):
3050          return Trace_Symbol(arg,axis_offset)
3051       else:
3052          raise TypeError,"Unknown argument type."
3053    
3054    class Trace_Symbol(DependendSymbol):
3055       """
3056       L{Symbol} representing the result of the trace function
3057       """
3058       def __init__(self,arg,axis_offset=0):
3059          """
3060          initialization of trace L{Symbol} with argument arg
3061          @param arg: argument of function
3062          @type arg: L{Symbol}.
3063          @param axis_offset: C{axis_offset} to components to sum over. C{axis_offset} must be non-negative and less than the rank of arg +1. The dimensions on component
3064                      C{axis_offset} and axis_offset+1 must be equal.
3065          @type axis_offset: C{int}
3066          """
3067          if arg.getRank()<2:
3068            raise ValueError,"rank of argument must be greater than 1"
3069          if axis_offset<0 or axis_offset>arg.getRank()-2:
3070            raise ValueError,"axis_offset must be between 0 and %s"%arg.getRank()-2
3071          s=list(arg.getShape())        
3072          if not s[axis_offset] == s[axis_offset+1]:
3073            raise ValueError,"dimensions of component %s and %s must match."%(axis_offset.axis_offset+1)
3074          super(Trace_Symbol,self).__init__(args=[arg,axis_offset],shape=tuple(s[0:axis_offset]+s[axis_offset+2:]),dim=arg.getDim())
3075    
3076       def getMyCode(self,argstrs,format="escript"):
3077          """
3078          returns a program code that can be used to evaluate the symbol.
3079    
3080          @param argstrs: gives for each argument a string representing the argument for the evaluation.
3081          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
3082          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
3083          @type format: C{str}
3084          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
3085          @rtype: C{str}
3086          @raise NotImplementedError: if the requested format is not available
3087          """
3088          if format=="escript" or format=="str"  or format=="text":
3089             return "trace(%s,axis_offset=%s)"%(argstrs[0],argstrs[1])
3090          else:
3091             raise NotImplementedError,"Trace_Symbol does not provide program code for format %s."%format
3092    
3093       def substitute(self,argvals):
3094          """
3095          assigns new values to symbols in the definition of the symbol.
3096          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
3097    
3098          @param argvals: new values assigned to symbols
3099          @type argvals: C{dict} with keywords of type L{Symbol}.
3100          @return: result of the substitution process. Operations are executed as much as possible.
3101          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
3102          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
3103          """
3104          if argvals.has_key(self):
3105             arg=argvals[self]
3106             if self.isAppropriateValue(arg):
3107                return arg
3108             else:
3109                raise TypeError,"%s: new value is not appropriate."%str(self)
3110          else:
3111             arg=self.getSubstitutedArguments(argvals)
3112             return trace(arg[0],axis_offset=arg[1])
3113    
3114       def diff(self,arg):
3115          """
3116          differential of this object
3117    
3118          @param arg: the derivative is calculated with respect to arg
3119          @type arg: L{escript.Symbol}
3120          @return: derivative with respect to C{arg}
3121          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
3122          """
3123          if arg==self:
3124             return identity(self.getShape())
3125          else:
3126             return trace(self.getDifferentiatedArguments(arg)[0],axis_offset=self.getArgument()[1])
3127    
3128    def transpose(arg,axis_offset=None):
3129       """
3130       returns the transpose of arg by swaping the first C{axis_offset} and the last rank-axis_offset components.
3131    
3132       @param arg: argument
3133       @type arg: L{escript.Data}, L{Symbol}, L{numarray.NumArray}, C{float}, C{int}
3134       @param axis_offset: the first C{axis_offset} components are swapped with rest. If C{axis_offset} must be non-negative and less or equal the rank of arg.
3135                           if C{axis_offset} is not present C{int(r/2)} where r is the rank of arg is used.
3136       @type axis_offset: C{int}
3137       @return: transpose of arg
3138       @rtype: L{escript.Data}, L{Symbol}, L{numarray.NumArray},C{float}, C{int} depending on the type of arg.
3139       """
3140       if isinstance(arg,numarray.NumArray):
3141          if axis_offset==None: axis_offset=int(arg.rank/2)
3142          return numarray.transpose(arg,axes=range(axis_offset,arg.rank)+range(0,axis_offset))
3143       elif isinstance(arg,escript.Data):
3144          r=arg.getRank()
3145          if axis_offset==None: axis_offset=int(r/2)
3146          if axis_offset<0 or axis_offset>r:
3147            raise ValueError,"axis_offset must be between 0 and %s"%r
3148          return arg._transpose(axis_offset)
3149       elif isinstance(arg,float):
3150          if not ( axis_offset==0 or axis_offset==None):
3151            raise ValueError,"axis_offset must be 0 for float argument"
3152          return arg
3153       elif isinstance(arg,int):
3154          if not ( axis_offset==0 or axis_offset==None):
3155            raise ValueError,"axis_offset must be 0 for int argument"
3156          return float(arg)
3157       elif isinstance(arg,Symbol):
3158          if axis_offset==None: axis_offset=int(arg.getRank()/2)
3159          return Transpose_Symbol(arg,axis_offset)
3160       else:
3161          raise TypeError,"Unknown argument type."
3162    
3163    class Transpose_Symbol(DependendSymbol):
3164       """
3165       L{Symbol} representing the result of the transpose function
3166       """
3167       def __init__(self,arg,axis_offset=None):
3168          """
3169          initialization of transpose L{Symbol} with argument arg
3170    
3171          @param arg: argument of function
3172          @type arg: L{Symbol}.
3173          @param axis_offset: the first C{axis_offset} components are swapped with rest. If C{axis_offset} must be non-negative and less or equal the rank of arg.
3174                           if C{axis_offset} is not present C{int(r/2)} where r is the rank of arg is used.
3175          @type axis_offset: C{int}
3176          """
3177          if axis_offset==None: axis_offset=int(arg.getRank()/2)
3178          if axis_offset<0 or axis_offset>arg.getRank():
3179            raise ValueError,"axis_offset must be between 0 and %s"%arg.getRank()
3180          s=arg.getShape()
3181          super(Transpose_Symbol,self).__init__(args=[arg,axis_offset],shape=s[axis_offset:]+s[:axis_offset],dim=arg.getDim())
3182    
3183       def getMyCode(self,argstrs,format="escript"):
3184          """
3185          returns a program code that can be used to evaluate the symbol.
3186    
3187          @param argstrs: gives for each argument a string representing the argument for the evaluation.
3188          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
3189          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
3190          @type format: C{str}
3191          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
3192          @rtype: C{str}
3193          @raise NotImplementedError: if the requested format is not available
3194          """
3195          if format=="escript" or format=="str"  or format=="text":
3196             return "transpose(%s,axis_offset=%s)"%(argstrs[0],argstrs[1])
3197          else:
3198             raise NotImplementedError,"Transpose_Symbol does not provide program code for format %s."%format
3199    
3200       def substitute(self,argvals):
3201          """
3202          assigns new values to symbols in the definition of the symbol.
3203          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
3204    
3205          @param argvals: new values assigned to symbols
3206          @type argvals: C{dict} with keywords of type L{Symbol}.
3207          @return: result of the substitution process. Operations are executed as much as possible.
3208          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
3209          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
3210          """
3211          if argvals.has_key(self):
3212             arg=argvals[self]
3213             if self.isAppropriateValue(arg):
3214                return arg
3215             else:
3216                raise TypeError,"%s: new value is not appropriate."%str(self)
3217          else:
3218             arg=self.getSubstitutedArguments(argvals)
3219             return transpose(arg[0],axis_offset=arg[1])
3220    
3221       def diff(self,arg):
3222          """
3223          differential of this object
3224    
3225          @param arg: the derivative is calculated with respect to arg
3226          @type arg: L{escript.Symbol}
3227          @return: derivative with respect to C{arg}
3228          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
3229          """
3230          if arg==self:
3231             return identity(self.getShape())
3232          else:
3233             return transpose(self.getDifferentiatedArguments(arg)[0],axis_offset=self.getArgument()[1])
3234    
3235    def swap_axes(arg,axis0=0,axis1=1):
3236       """
3237       returns the swap of arg by swaping the components axis0 and axis1
3238    
3239       @param arg: argument
3240       @type arg: L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
3241       @param axis0: axis. C{axis0} must be non-negative and less than the rank of arg.
3242       @type axis0: C{int}
3243       @param axis1: axis. C{axis1} must be non-negative and less than the rank of arg.
3244       @type axis1: C{int}
3245       @return: C{arg} with swaped components
3246       @rtype: L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
3247       """
3248       if axis0 > axis1:
3249          axis0,axis1=axis1,axis0
3250       if isinstance(arg,numarray.NumArray):
3251          return numarray.swapaxes(arg,axis0,axis1)
3252       elif isinstance(arg,escript.Data):
3253          return arg._swap_axes(axis0,axis1)
3254       elif isinstance(arg,float):
3255          raise TyepError,"float argument is not supported."
3256       elif isinstance(arg,int):
3257          raise TyepError,"int argument is not supported."
3258       elif isinstance(arg,Symbol):
3259          return SwapAxes_Symbol(arg,axis0,axis1)
3260       else:
3261          raise TypeError,"Unknown argument type."
3262    
3263    class SwapAxes_Symbol(DependendSymbol):
3264       """
3265       L{Symbol} representing the result of the swap function
3266       """
3267       def __init__(self,arg,axis0=0,axis1=1):
3268          """
3269          initialization of swap L{Symbol} with argument arg
3270    
3271          @param arg: argument
3272          @type arg: L{Symbol}.
3273          @param axis0: axis. C{axis0} must be non-negative and less than the rank of arg.
3274          @type axis0: C{int}
3275          @param axis1: axis. C{axis1} must be non-negative and less than the rank of arg.
3276          @type axis1: C{int}
3277          """
3278          if arg.getRank()<2:
3279             raise ValueError,"argument must have at least rank 2."
3280          if axis0<0 or axis0>arg.getRank()-1:
3281             raise ValueError,"axis0 must be between 0 and %s"%arg.getRank()-1
3282          if axis1<0 or axis1>arg.getRank()-1:
3283             raise ValueError,"axis1 must be between 0 and %s"%arg.getRank()-1
3284          if axis0 == axis1:
3285             raise ValueError,"axis indices must be different."
3286          if axis0 > axis1:
3287             axis0,axis1=axis1,axis0
3288          s=arg.getShape()
3289          s_out=[]
3290          for i in range(len(s)):
3291             if i == axis0:
3292                s_out.append(s[axis1])
3293             elif i == axis1:
3294                s_out.append(s[axis0])
3295             else:
3296                s_out.append(s[i])
3297          super(SwapAxes_Symbol,self).__init__(args=[arg,axis0,axis1],shape=tuple(s_out),dim=arg.getDim())
3298    
3299       def getMyCode(self,argstrs,format="escript"):
3300          """
3301          returns a program code that can be used to evaluate the symbol.
3302    
3303          @param argstrs: gives for each argument a string representing the argument for the evaluation.
3304          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
3305          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
3306          @type format: C{str}
3307          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
3308          @rtype: C{str}
3309          @raise NotImplementedError: if the requested format is not available
3310          """
3311          if format=="escript" or format=="str"  or format=="text":
3312             return "swap(%s,axis_offset=%s)"%(argstrs[0],argstrs[1])
3313          else:
3314             raise NotImplementedError,"SwapAxes_Symbol does not provide program code for format %s."%format
3315    
3316       def substitute(self,argvals):
3317          """
3318          assigns new values to symbols in the definition of the symbol.
3319          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
3320    
3321          @param argvals: new values assigned to symbols
3322          @type argvals: C{dict} with keywords of type L{Symbol}.
3323          @return: result of the substitution process. Operations are executed as much as possible.
3324          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
3325          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
3326          """
3327          if argvals.has_key(self):
3328             arg=argvals[self]
3329             if self.isAppropriateValue(arg):
3330                return arg
3331             else:
3332                raise TypeError,"%s: new value is not appropriate."%str(self)
3333          else:
3334             arg=self.getSubstitutedArguments(argvals)
3335             return swap_axes(arg[0],axis0=arg[1],axis1=arg[2])
3336    
3337       def diff(self,arg):
3338          """
3339          differential of this object
3340    
3341          @param arg: the derivative is calculated with respect to arg
3342          @type arg: L{escript.Symbol}
3343          @return: derivative with respect to C{arg}
3344          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
3345          """
3346          if arg==self:
3347             return identity(self.getShape())
3348          else:
3349             return swap_axes(self.getDifferentiatedArguments(arg)[0],axis0=self.getArgument()[1],axis1=self.getArgument()[2])
3350    
3351    def symmetric(arg):
3352