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