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