/[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 102 by jgs, Wed Dec 15 07:08:39 2004 UTC trunk/escript/py_src/util.py revision 353 by gross, Wed Dec 14 04:13:59 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           saveDX("solution.dx",temperature=tmp,velovity=v)
104    
105        tmp and v are written into "solution.dx" where tmp is named "temperature" and v is named "velovity".
106    
107        @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 interpolates the function represented by Data object arg into the FunctionSpace where.      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      @param where     """
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      return arg.interpolate(where)      returns the Lsup-norm of argument arg. This is the maximum absolute value over all data points.
206        This function is equivalent to sup(abs(arg)).
207    
208  # functions returning Data objects:      @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:
223          raise TypeError,"Lsup: Unknown argument type."
224    
225  def transpose(arg,axis=None):  def sup(arg):
226      """      """
227      @brief returns the transpose of the Data object arg.      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         if axis==None: axis=arg.getRank()/2      @rtype: C{float}
233         return arg.transpose(axis)      @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         if axis==None: axis=arg.rank/2        raise TypeError,"sup: Unknown argument type."
        return numarray.transpose(arg,axis=axis)  
245    
246  def trace(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.trace()      @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.trace(arg)        raise TypeError,"inf: Unknown argument type."
266    
 def exp(arg):  
     """  
     @brief  
267    
268      @param arg  #=========================================================================
269      """  #   some little helpers
270      if isinstance(arg,escript.Data):  #=========================================================================
271         return arg.exp()  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.exp(arg)        raise TypeError,"pokeShape: cannot identify shape"
294    
295  def sqrt(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.sqrt()          return arg.getFunctionSpace().getDim()
307        elif isinstance(arg,Symbol):
308            return arg.getDim()
309      else:      else:
310         return numarray.sqrt(arg)          return None
311    
312  def sin(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.sin()      @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:
333           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 testForZero(arg):
358        """
359        test the argument for being identical to Zero
360    
361        @param arg: a given object
362        @type arg: typically L{numarray.NumArray},L{escript.Data},C{float}, C{int}
363        @return : True if the argument is identical to zero.
364        @rtype : C{bool}
365        """
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.sin(arg)        raise TypeError,"function: Unknown type of first argument."    
454    
455  def tan(arg):      return arg0,arg1
     """  
     @brief  
456    
457      @param arg  def matchShape(arg0,arg1):
458      """      """
459      if isinstance(arg,escript.Data):      
460         return arg.tan()  
461      else:      If shape is not given the shape "largest" shape of args is used.
462         return numarray.tan(arg)  
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          if arg.rank==0:
911             if arg>0:
912               return numarray.array(1.)
913             else:
914               return numarray.array(0.)
915          else:
916             return numarray.greater(arg,numarray.zeros(arg.shape,numarray.Float))
917       elif isinstance(arg,escript.Data):
918          return arg._wherePositive()
919       elif isinstance(arg,float):
920          if arg>0:
921            return 1.
922          else:
923            return 0.
924       elif isinstance(arg,int):
925          if arg>0:
926            return 1.
927          else:
928            return 0.
929       elif isinstance(arg,Symbol):
930          return WherePositive_Symbol(arg)
931       else:
932          raise TypeError,"wherePositive: Unknown argument type."
933    
934    class WherePositive_Symbol(DependendSymbol):
935       """
936       L{Symbol} representing the result of the mask of positive values function
937       """
938       def __init__(self,arg):
939          """
940          initialization of wherePositive L{Symbol} with argument arg
941          @param arg: argument of function
942          @type arg: typically L{Symbol}.
943          """
944          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
945    
946       def getMyCode(self,argstrs,format="escript"):
947          """
948          returns a program code that can be used to evaluate the symbol.
949    
950          @param argstrs: gives for each argument a string representing the argument for the evaluation.
951          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
952          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
953          @type format: C{str}
954          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
955          @rtype: C{str}
956          @raise: NotImplementedError: if the requested format is not available
957          """
958          if isinstance(argstrs,list):
959              argstrs=argstrs[0]
960          if format=="escript" or format=="str"  or format=="text":
961             return "wherePositive(%s)"%argstrs
962          else:
963             raise NotImplementedError,"WherePositive_Symbol does not provide program code for format %s."%format
964    
965       def substitute(self,argvals):
966          """
967          assigns new values to symbols in the definition of the symbol.
968          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
969    
970          @param argvals: new values assigned to symbols
971          @type argvals: C{dict} with keywords of type L{Symbol}.
972          @return: result of the substitution process. Operations are executed as much as possible.
973          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
974          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
975          """
976          if argvals.has_key(self):
977             arg=argvals[self]
978             if self.isAppropriateValue(arg):
979                return arg
980             else:
981                raise TypeError,"%s: new value is not appropriate."%str(self)
982          else:
983             arg=self.getSubstitutedArguments(argvals)[0]
984             return wherePositive(arg)
985    
986    def whereNegative(arg):
987       """
988       returns mask of positive values of argument arg
989    
990       @param arg: argument
991       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
992       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
993       @raises TypeError: if the type of the argument is not expected.
994       """
995       if isinstance(arg,numarray.NumArray):
996          if arg.rank==0:
997             if arg<0:
998               return numarray.array(1.)
999             else:
1000               return numarray.array(0.)
1001          else:
1002             return numarray.less(arg,numarray.zeros(arg.shape,numarray.Float))
1003       elif isinstance(arg,escript.Data):
1004          return arg._whereNegative()
1005       elif isinstance(arg,float):
1006          if arg<0:
1007            return 1.
1008          else:
1009            return 0.
1010       elif isinstance(arg,int):
1011          if arg<0:
1012            return 1.
1013          else:
1014            return 0.
1015       elif isinstance(arg,Symbol):
1016          return WhereNegative_Symbol(arg)
1017       else:
1018          raise TypeError,"whereNegative: Unknown argument type."
1019    
1020    class WhereNegative_Symbol(DependendSymbol):
1021       """
1022       L{Symbol} representing the result of the mask of positive values function
1023       """
1024       def __init__(self,arg):
1025          """
1026          initialization of whereNegative L{Symbol} with argument arg
1027          @param arg: argument of function
1028          @type arg: typically L{Symbol}.
1029          """
1030          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1031    
1032       def getMyCode(self,argstrs,format="escript"):
1033          """
1034          returns a program code that can be used to evaluate the symbol.
1035    
1036          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1037          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1038          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1039          @type format: C{str}
1040          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1041          @rtype: C{str}
1042          @raise: NotImplementedError: if the requested format is not available
1043          """
1044          if isinstance(argstrs,list):
1045              argstrs=argstrs[0]
1046          if format=="escript" or format=="str"  or format=="text":
1047             return "whereNegative(%s)"%argstrs
1048          else:
1049             raise NotImplementedError,"WhereNegative_Symbol does not provide program code for format %s."%format
1050    
1051       def substitute(self,argvals):
1052          """
1053          assigns new values to symbols in the definition of the symbol.
1054          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1055    
1056          @param argvals: new values assigned to symbols
1057          @type argvals: C{dict} with keywords of type L{Symbol}.
1058          @return: result of the substitution process. Operations are executed as much as possible.
1059          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1060          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1061          """
1062          if argvals.has_key(self):
1063             arg=argvals[self]
1064             if self.isAppropriateValue(arg):
1065                return arg
1066             else:
1067                raise TypeError,"%s: new value is not appropriate."%str(self)
1068          else:
1069             arg=self.getSubstitutedArguments(argvals)[0]
1070             return whereNegative(arg)
1071    
1072    def whereNonNegative(arg):
1073       """
1074       returns mask of non-negative values of argument arg
1075    
1076       @param arg: argument
1077       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1078       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1079       @raises TypeError: if the type of the argument is not expected.
1080       """
1081       if isinstance(arg,numarray.NumArray):
1082          if arg.rank==0:
1083             if arg<0:
1084               return numarray.array(0.)
1085             else:
1086               return numarray.array(1.)
1087          else:
1088             return numarray.greater_equal(arg,numarray.zeros(arg.shape,numarray.Float))
1089       elif isinstance(arg,escript.Data):
1090          return arg._whereNonNegative()
1091       elif isinstance(arg,float):
1092          if arg<0:
1093            return 0.
1094          else:
1095            return 1.
1096       elif isinstance(arg,int):
1097          if arg<0:
1098            return 0.
1099          else:
1100            return 1.
1101       elif isinstance(arg,Symbol):
1102          return 1.-whereNegative(arg)
1103       else:
1104          raise TypeError,"whereNonNegative: Unknown argument type."
1105    
1106    def whereNonPositive(arg):
1107       """
1108       returns mask of non-positive values of argument arg
1109    
1110       @param arg: argument
1111       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1112       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1113       @raises TypeError: if the type of the argument is not expected.
1114       """
1115       if isinstance(arg,numarray.NumArray):
1116          if arg.rank==0:
1117             if arg>0:
1118               return numarray.array(0.)
1119             else:
1120               return numarray.array(1.)
1121          else:
1122             return numarray.less_equal(arg,numarray.zeros(arg.shape,numarray.Float))*1.
1123       elif isinstance(arg,escript.Data):
1124          return arg._whereNonPositive()
1125       elif isinstance(arg,float):
1126          if arg>0:
1127            return 0.
1128          else:
1129            return 1.
1130       elif isinstance(arg,int):
1131          if arg>0:
1132            return 0.
1133          else:
1134            return 1.
1135       elif isinstance(arg,Symbol):
1136          return 1.-wherePositive(arg)
1137       else:
1138          raise TypeError,"whereNonPositive: Unknown argument type."
1139    
1140    def whereZero(arg,tol=0.):
1141       """
1142       returns mask of zero entries of argument arg
1143    
1144       @param arg: argument
1145       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1146       @param tol: tolerance. values with absolute value less then tol are accepted as zero.
1147       @type tol: C{float}
1148       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1149       @raises TypeError: if the type of the argument is not expected.
1150       """
1151       if isinstance(arg,numarray.NumArray):
1152          if arg.rank==0:
1153             if abs(arg)<=tol:
1154               return numarray.array(1.)
1155             else:
1156               return numarray.array(0.)
1157          else:
1158             return numarray.less_equal(abs(arg)-tol,numarray.zeros(arg.shape,numarray.Float))*1.
1159       elif isinstance(arg,escript.Data):
1160          if tol>0.:
1161             return whereNegative(abs(arg)-tol)
1162          else:
1163             return arg._whereZero()
1164       elif isinstance(arg,float):
1165          if abs(arg)<=tol:
1166            return 1.
1167          else:
1168            return 0.
1169       elif isinstance(arg,int):
1170          if abs(float(arg))<=tol:
1171            return 1.
1172          else:
1173            return 0.
1174       elif isinstance(arg,Symbol):
1175          return WhereZero_Symbol(arg,tol)
1176       else:
1177          raise TypeError,"whereZero: Unknown argument type."
1178    
1179    class WhereZero_Symbol(DependendSymbol):
1180       """
1181       L{Symbol} representing the result of the mask of zero entries function
1182       """
1183       def __init__(self,arg,tol=0.):
1184          """
1185          initialization of whereZero L{Symbol} with argument arg
1186          @param arg: argument of function
1187          @type arg: typically L{Symbol}.
1188          """
1189          DependendSymbol.__init__(self,args=[arg,tol],shape=arg.getShape(),dim=arg.getDim())
1190    
1191       def getMyCode(self,argstrs,format="escript"):
1192          """
1193          returns a program code that can be used to evaluate the symbol.
1194    
1195          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1196          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1197          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1198          @type format: C{str}
1199          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1200          @rtype: C{str}
1201          @raise: NotImplementedError: if the requested format is not available
1202          """
1203          if format=="escript" or format=="str"  or format=="text":
1204             return "whereZero(%s,tol=%s)"%(argstrs[0],argstrs[1])
1205          else:
1206             raise NotImplementedError,"WhereZero_Symbol does not provide program code for format %s."%format
1207    
1208       def substitute(self,argvals):
1209          """
1210          assigns new values to symbols in the definition of the symbol.
1211          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1212    
1213          @param argvals: new values assigned to symbols
1214          @type argvals: C{dict} with keywords of type L{Symbol}.
1215          @return: result of the substitution process. Operations are executed as much as possible.
1216          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1217          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1218          """
1219          if argvals.has_key(self):
1220             arg=argvals[self]
1221             if self.isAppropriateValue(arg):
1222                return arg
1223             else:
1224                raise TypeError,"%s: new value is not appropriate."%str(self)
1225          else:
1226             arg=self.getSubstitutedArguments(argvals)
1227             return whereZero(arg[0],arg[1])
1228    
1229    def whereNonZero(arg,tol=0.):
1230       """
1231       returns mask of values different from zero of argument arg
1232    
1233       @param arg: argument
1234       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1235       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1236       @raises TypeError: if the type of the argument is not expected.
1237       """
1238       if isinstance(arg,numarray.NumArray):
1239          if arg.rank==0:
1240            if abs(arg)>tol:
1241               return numarray.array(1.)
1242            else:
1243               return numarray.array(0.)
1244          else:
1245             return numarray.greater(abs(arg)-tol,numarray.zeros(arg.shape,numarray.Float))*1.
1246       elif isinstance(arg,escript.Data):
1247          if tol>0.:
1248             return 1.-whereZero(arg,tol)
1249          else:
1250             return arg._whereNonZero()
1251       elif isinstance(arg,float):
1252          if abs(arg)>tol:
1253            return 1.
1254          else:
1255            return 0.
1256       elif isinstance(arg,int):
1257          if abs(float(arg))>tol:
1258            return 1.
1259          else:
1260            return 0.
1261       elif isinstance(arg,Symbol):
1262          return 1.-whereZero(arg,tol)
1263       else:
1264          raise TypeError,"whereNonZero: Unknown argument type."
1265    
1266    def sin(arg):
1267       """
1268       returns sine of argument arg
1269    
1270       @param arg: argument
1271       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1272       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1273       @raises TypeError: if the type of the argument is not expected.
1274       """
1275       if isinstance(arg,numarray.NumArray):
1276          return numarray.sin(arg)
1277       elif isinstance(arg,escript.Data):
1278          return arg._sin()
1279       elif isinstance(arg,float):
1280          return math.sin(arg)
1281       elif isinstance(arg,int):
1282          return math.sin(arg)
1283       elif isinstance(arg,Symbol):
1284          return Sin_Symbol(arg)
1285       else:
1286          raise TypeError,"sin: Unknown argument type."
1287    
1288    class Sin_Symbol(DependendSymbol):
1289       """
1290       L{Symbol} representing the result of the sine function
1291       """
1292       def __init__(self,arg):
1293          """
1294          initialization of sin L{Symbol} with argument arg
1295          @param arg: argument of function
1296          @type arg: typically L{Symbol}.
1297          """
1298          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1299    
1300       def getMyCode(self,argstrs,format="escript"):
1301          """
1302          returns a program code that can be used to evaluate the symbol.
1303    
1304          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1305          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1306          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1307          @type format: C{str}
1308          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1309          @rtype: C{str}
1310          @raise: NotImplementedError: if the requested format is not available
1311          """
1312          if isinstance(argstrs,list):
1313              argstrs=argstrs[0]
1314          if format=="escript" or format=="str"  or format=="text":
1315             return "sin(%s)"%argstrs
1316          else:
1317             raise NotImplementedError,"Sin_Symbol does not provide program code for format %s."%format
1318    
1319       def substitute(self,argvals):
1320          """
1321          assigns new values to symbols in the definition of the symbol.
1322          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1323    
1324          @param argvals: new values assigned to symbols
1325          @type argvals: C{dict} with keywords of type L{Symbol}.
1326          @return: result of the substitution process. Operations are executed as much as possible.
1327          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1328          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1329          """
1330          if argvals.has_key(self):
1331             arg=argvals[self]
1332             if self.isAppropriateValue(arg):
1333                return arg
1334             else:
1335                raise TypeError,"%s: new value is not appropriate."%str(self)
1336          else:
1337             arg=self.getSubstitutedArguments(argvals)[0]
1338             return sin(arg)
1339    
1340       def diff(self,arg):
1341          """
1342          differential of this object
1343    
1344          @param arg: the derivative is calculated with respect to arg
1345          @type arg: L{escript.Symbol}
1346          @return: derivative with respect to C{arg}
1347          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1348          """
1349          if arg==self:
1350             return identity(self.getShape())
1351          else:
1352             myarg=self.getArgument()[0]
1353             val=matchShape(cos(myarg),self.getDifferentiatedArguments(arg)[0])
1354             return val[0]*val[1]
1355    
1356  def cos(arg):  def cos(arg):
1357      """     """
1358      @brief     returns cosine of argument arg
1359    
1360      @param arg     @param arg: argument
1361      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1362      if isinstance(arg,escript.Data):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1363         return arg.cos()     @raises TypeError: if the type of the argument is not expected.
1364      else:     """
1365         return numarray.cos(arg)     if isinstance(arg,numarray.NumArray):
1366          return numarray.cos(arg)
1367       elif isinstance(arg,escript.Data):
1368          return arg._cos()
1369       elif isinstance(arg,float):
1370          return math.cos(arg)
1371       elif isinstance(arg,int):
1372          return math.cos(arg)
1373       elif isinstance(arg,Symbol):
1374          return Cos_Symbol(arg)
1375       else:
1376          raise TypeError,"cos: Unknown argument type."
1377    
1378    class Cos_Symbol(DependendSymbol):
1379       """
1380       L{Symbol} representing the result of the cosine function
1381       """
1382       def __init__(self,arg):
1383          """
1384          initialization of cos L{Symbol} with argument arg
1385          @param arg: argument of function
1386          @type arg: typically L{Symbol}.
1387          """
1388          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1389    
1390       def getMyCode(self,argstrs,format="escript"):
1391          """
1392          returns a program code that can be used to evaluate the symbol.
1393    
1394          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1395          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1396          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1397          @type format: C{str}
1398          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1399          @rtype: C{str}
1400          @raise: NotImplementedError: if the requested format is not available
1401          """
1402          if isinstance(argstrs,list):
1403              argstrs=argstrs[0]
1404          if format=="escript" or format=="str"  or format=="text":
1405             return "cos(%s)"%argstrs
1406          else:
1407             raise NotImplementedError,"Cos_Symbol does not provide program code for format %s."%format
1408    
1409       def substitute(self,argvals):
1410          """
1411          assigns new values to symbols in the definition of the symbol.
1412          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1413    
1414          @param argvals: new values assigned to symbols
1415          @type argvals: C{dict} with keywords of type L{Symbol}.
1416          @return: result of the substitution process. Operations are executed as much as possible.
1417          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1418          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1419          """
1420          if argvals.has_key(self):
1421             arg=argvals[self]
1422             if self.isAppropriateValue(arg):
1423                return arg
1424             else:
1425                raise TypeError,"%s: new value is not appropriate."%str(self)
1426          else:
1427             arg=self.getSubstitutedArguments(argvals)[0]
1428             return cos(arg)
1429    
1430       def diff(self,arg):
1431          """
1432          differential of this object
1433    
1434          @param arg: the derivative is calculated with respect to arg
1435          @type arg: L{escript.Symbol}
1436          @return: derivative with respect to C{arg}
1437          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1438          """
1439          if arg==self:
1440             return identity(self.getShape())
1441          else:
1442             myarg=self.getArgument()[0]
1443             val=matchShape(-sin(myarg),self.getDifferentiatedArguments(arg)[0])
1444             return val[0]*val[1]
1445    
1446    def tan(arg):
1447       """
1448       returns tangent of argument arg
1449    
1450       @param arg: argument
1451       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1452       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1453       @raises TypeError: if the type of the argument is not expected.
1454       """
1455       if isinstance(arg,numarray.NumArray):
1456          return numarray.tan(arg)
1457       elif isinstance(arg,escript.Data):
1458          return arg._tan()
1459       elif isinstance(arg,float):
1460          return math.tan(arg)
1461       elif isinstance(arg,int):
1462          return math.tan(arg)
1463       elif isinstance(arg,Symbol):
1464          return Tan_Symbol(arg)
1465       else:
1466          raise TypeError,"tan: Unknown argument type."
1467    
1468    class Tan_Symbol(DependendSymbol):
1469       """
1470       L{Symbol} representing the result of the tangent function
1471       """
1472       def __init__(self,arg):
1473          """
1474          initialization of tan L{Symbol} with argument arg
1475          @param arg: argument of function
1476          @type arg: typically L{Symbol}.
1477          """
1478          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1479    
1480       def getMyCode(self,argstrs,format="escript"):
1481          """
1482          returns a program code that can be used to evaluate the symbol.
1483    
1484          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1485          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1486          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1487          @type format: C{str}
1488          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1489          @rtype: C{str}
1490          @raise: NotImplementedError: if the requested format is not available
1491          """
1492          if isinstance(argstrs,list):
1493              argstrs=argstrs[0]
1494          if format=="escript" or format=="str"  or format=="text":
1495             return "tan(%s)"%argstrs
1496          else:
1497             raise NotImplementedError,"Tan_Symbol does not provide program code for format %s."%format
1498    
1499       def substitute(self,argvals):
1500          """
1501          assigns new values to symbols in the definition of the symbol.
1502          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1503    
1504          @param argvals: new values assigned to symbols
1505          @type argvals: C{dict} with keywords of type L{Symbol}.
1506          @return: result of the substitution process. Operations are executed as much as possible.
1507          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1508          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1509          """
1510          if argvals.has_key(self):
1511             arg=argvals[self]
1512             if self.isAppropriateValue(arg):
1513                return arg
1514             else:
1515                raise TypeError,"%s: new value is not appropriate."%str(self)
1516          else:
1517             arg=self.getSubstitutedArguments(argvals)[0]
1518             return tan(arg)
1519    
1520       def diff(self,arg):
1521          """
1522          differential of this object
1523    
1524          @param arg: the derivative is calculated with respect to arg
1525          @type arg: L{escript.Symbol}
1526          @return: derivative with respect to C{arg}
1527          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1528          """
1529          if arg==self:
1530             return identity(self.getShape())
1531          else:
1532             myarg=self.getArgument()[0]
1533             val=matchShape(1./cos(myarg)**2,self.getDifferentiatedArguments(arg)[0])
1534             return val[0]*val[1]
1535    
1536    def asin(arg):
1537       """
1538       returns inverse sine of argument arg
1539    
1540       @param arg: argument
1541       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1542       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1543       @raises TypeError: if the type of the argument is not expected.
1544       """
1545       if isinstance(arg,numarray.NumArray):
1546          return numarray.arcsin(arg)
1547       elif isinstance(arg,escript.Data):
1548          return arg._asin()
1549       elif isinstance(arg,float):
1550          return math.asin(arg)
1551       elif isinstance(arg,int):
1552          return math.asin(arg)
1553       elif isinstance(arg,Symbol):
1554          return Asin_Symbol(arg)
1555       else:
1556          raise TypeError,"asin: Unknown argument type."
1557    
1558    class Asin_Symbol(DependendSymbol):
1559       """
1560       L{Symbol} representing the result of the inverse sine function
1561       """
1562       def __init__(self,arg):
1563          """
1564          initialization of asin L{Symbol} with argument arg
1565          @param arg: argument of function
1566          @type arg: typically L{Symbol}.
1567          """
1568          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1569    
1570       def getMyCode(self,argstrs,format="escript"):
1571          """
1572          returns a program code that can be used to evaluate the symbol.
1573    
1574          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1575          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1576          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1577          @type format: C{str}
1578          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1579          @rtype: C{str}
1580          @raise: NotImplementedError: if the requested format is not available
1581          """
1582          if isinstance(argstrs,list):
1583              argstrs=argstrs[0]
1584          if format=="escript" or format=="str"  or format=="text":
1585             return "asin(%s)"%argstrs
1586          else:
1587             raise NotImplementedError,"Asin_Symbol does not provide program code for format %s."%format
1588    
1589       def substitute(self,argvals):
1590          """
1591          assigns new values to symbols in the definition of the symbol.
1592          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1593    
1594          @param argvals: new values assigned to symbols
1595          @type argvals: C{dict} with keywords of type L{Symbol}.
1596          @return: result of the substitution process. Operations are executed as much as possible.
1597          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1598          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1599          """
1600          if argvals.has_key(self):
1601             arg=argvals[self]
1602             if self.isAppropriateValue(arg):
1603                return arg
1604             else:
1605                raise TypeError,"%s: new value is not appropriate."%str(self)
1606          else:
1607             arg=self.getSubstitutedArguments(argvals)[0]
1608             return asin(arg)
1609    
1610       def diff(self,arg):
1611          """
1612          differential of this object
1613    
1614          @param arg: the derivative is calculated with respect to arg
1615          @type arg: L{escript.Symbol}
1616          @return: derivative with respect to C{arg}
1617          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1618          """
1619          if arg==self:
1620             return identity(self.getShape())
1621          else:
1622             myarg=self.getArgument()[0]
1623             val=matchShape(1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
1624             return val[0]*val[1]
1625    
1626    def acos(arg):
1627       """
1628       returns inverse cosine of argument arg
1629    
1630       @param arg: argument
1631       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1632       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1633       @raises TypeError: if the type of the argument is not expected.
1634       """
1635       if isinstance(arg,numarray.NumArray):
1636          return numarray.arccos(arg)
1637       elif isinstance(arg,escript.Data):
1638          return arg._acos()
1639       elif isinstance(arg,float):
1640          return math.acos(arg)
1641       elif isinstance(arg,int):
1642          return math.acos(arg)
1643       elif isinstance(arg,Symbol):
1644          return Acos_Symbol(arg)
1645       else:
1646          raise TypeError,"acos: Unknown argument type."
1647    
1648    class Acos_Symbol(DependendSymbol):
1649       """
1650       L{Symbol} representing the result of the inverse cosine function
1651       """
1652       def __init__(self,arg):
1653          """
1654          initialization of acos L{Symbol} with argument arg
1655          @param arg: argument of function
1656          @type arg: typically L{Symbol}.
1657          """
1658          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1659    
1660       def getMyCode(self,argstrs,format="escript"):
1661          """
1662          returns a program code that can be used to evaluate the symbol.
1663    
1664          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1665          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1666          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1667          @type format: C{str}
1668          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1669          @rtype: C{str}
1670          @raise: NotImplementedError: if the requested format is not available
1671          """
1672          if isinstance(argstrs,list):
1673              argstrs=argstrs[0]
1674          if format=="escript" or format=="str"  or format=="text":
1675             return "acos(%s)"%argstrs
1676          else:
1677             raise NotImplementedError,"Acos_Symbol does not provide program code for format %s."%format
1678    
1679       def substitute(self,argvals):
1680          """
1681          assigns new values to symbols in the definition of the symbol.
1682          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1683    
1684          @param argvals: new values assigned to symbols
1685          @type argvals: C{dict} with keywords of type L{Symbol}.
1686          @return: result of the substitution process. Operations are executed as much as possible.
1687          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1688          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1689          """
1690          if argvals.has_key(self):
1691             arg=argvals[self]
1692             if self.isAppropriateValue(arg):
1693                return arg
1694             else:
1695                raise TypeError,"%s: new value is not appropriate."%str(self)
1696          else:
1697             arg=self.getSubstitutedArguments(argvals)[0]
1698             return acos(arg)
1699    
1700       def diff(self,arg):
1701          """
1702          differential of this object
1703    
1704          @param arg: the derivative is calculated with respect to arg
1705          @type arg: L{escript.Symbol}
1706          @return: derivative with respect to C{arg}
1707          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1708          """
1709          if arg==self:
1710             return identity(self.getShape())
1711          else:
1712             myarg=self.getArgument()[0]
1713             val=matchShape(-1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
1714             return val[0]*val[1]
1715    
1716    def atan(arg):
1717       """
1718       returns inverse tangent of argument arg
1719    
1720       @param arg: argument
1721       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1722       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1723       @raises TypeError: if the type of the argument is not expected.
1724       """
1725       if isinstance(arg,numarray.NumArray):
1726          return numarray.arctan(arg)
1727       elif isinstance(arg,escript.Data):
1728          return arg._atan()
1729       elif isinstance(arg,float):
1730          return math.atan(arg)
1731       elif isinstance(arg,int):
1732          return math.atan(arg)
1733       elif isinstance(arg,Symbol):
1734          return Atan_Symbol(arg)
1735       else:
1736          raise TypeError,"atan: Unknown argument type."
1737    
1738    class Atan_Symbol(DependendSymbol):
1739       """
1740       L{Symbol} representing the result of the inverse tangent function
1741       """
1742       def __init__(self,arg):
1743          """
1744          initialization of atan L{Symbol} with argument arg
1745          @param arg: argument of function
1746          @type arg: typically L{Symbol}.
1747          """
1748          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1749    
1750       def getMyCode(self,argstrs,format="escript"):
1751          """
1752          returns a program code that can be used to evaluate the symbol.
1753    
1754          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1755          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1756          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1757          @type format: C{str}
1758          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1759          @rtype: C{str}
1760          @raise: NotImplementedError: if the requested format is not available
1761          """
1762          if isinstance(argstrs,list):
1763              argstrs=argstrs[0]
1764          if format=="escript" or format=="str"  or format=="text":
1765             return "atan(%s)"%argstrs
1766          else:
1767             raise NotImplementedError,"Atan_Symbol does not provide program code for format %s."%format
1768    
1769       def substitute(self,argvals):
1770          """
1771          assigns new values to symbols in the definition of the symbol.
1772          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1773    
1774          @param argvals: new values assigned to symbols
1775          @type argvals: C{dict} with keywords of type L{Symbol}.
1776          @return: result of the substitution process. Operations are executed as much as possible.
1777          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1778          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1779          """
1780          if argvals.has_key(self):
1781             arg=argvals[self]
1782             if self.isAppropriateValue(arg):
1783                return arg
1784             else:
1785                raise TypeError,"%s: new value is not appropriate."%str(self)
1786          else:
1787             arg=self.getSubstitutedArguments(argvals)[0]
1788             return atan(arg)
1789    
1790       def diff(self,arg):
1791          """
1792          differential of this object
1793    
1794          @param arg: the derivative is calculated with respect to arg
1795          @type arg: L{escript.Symbol}
1796          @return: derivative with respect to C{arg}
1797          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1798          """
1799          if arg==self:
1800             return identity(self.getShape())
1801          else:
1802             myarg=self.getArgument()[0]
1803             val=matchShape(1./(1+myarg**2),self.getDifferentiatedArguments(arg)[0])
1804             return val[0]*val[1]
1805    
1806    def sinh(arg):
1807       """
1808       returns hyperbolic sine of argument arg
1809    
1810       @param arg: argument
1811       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1812       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1813       @raises TypeError: if the type of the argument is not expected.
1814       """
1815       if isinstance(arg,numarray.NumArray):
1816          return numarray.sinh(arg)
1817       elif isinstance(arg,escript.Data):
1818          return arg._sinh()
1819       elif isinstance(arg,float):
1820          return math.sinh(arg)
1821       elif isinstance(arg,int):
1822          return math.sinh(arg)
1823       elif isinstance(arg,Symbol):
1824          return Sinh_Symbol(arg)
1825       else:
1826          raise TypeError,"sinh: Unknown argument type."
1827    
1828    class Sinh_Symbol(DependendSymbol):
1829       """
1830       L{Symbol} representing the result of the hyperbolic sine function
1831       """
1832       def __init__(self,arg):
1833          """
1834          initialization of sinh L{Symbol} with argument arg
1835          @param arg: argument of function
1836          @type arg: typically L{Symbol}.
1837          """
1838          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1839    
1840       def getMyCode(self,argstrs,format="escript"):
1841          """
1842          returns a program code that can be used to evaluate the symbol.
1843    
1844          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1845          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1846          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1847          @type format: C{str}
1848          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1849          @rtype: C{str}
1850          @raise: NotImplementedError: if the requested format is not available
1851          """
1852          if isinstance(argstrs,list):
1853              argstrs=argstrs[0]
1854          if format=="escript" or format=="str"  or format=="text":
1855             return "sinh(%s)"%argstrs
1856          else:
1857             raise NotImplementedError,"Sinh_Symbol does not provide program code for format %s."%format
1858    
1859       def substitute(self,argvals):
1860          """
1861          assigns new values to symbols in the definition of the symbol.
1862          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1863    
1864          @param argvals: new values assigned to symbols
1865          @type argvals: C{dict} with keywords of type L{Symbol}.
1866          @return: result of the substitution process. Operations are executed as much as possible.
1867          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1868          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1869          """
1870          if argvals.has_key(self):
1871             arg=argvals[self]
1872             if self.isAppropriateValue(arg):
1873                return arg
1874             else:
1875                raise TypeError,"%s: new value is not appropriate."%str(self)
1876          else:
1877             arg=self.getSubstitutedArguments(argvals)[0]
1878             return sinh(arg)
1879    
1880       def diff(self,arg):
1881          """
1882          differential of this object
1883    
1884          @param arg: the derivative is calculated with respect to arg
1885          @type arg: L{escript.Symbol}
1886          @return: derivative with respect to C{arg}
1887          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1888          """
1889          if arg==self:
1890             return identity(self.getShape())
1891          else:
1892             myarg=self.getArgument()[0]
1893             val=matchShape(cosh(myarg),self.getDifferentiatedArguments(arg)[0])
1894             return val[0]*val[1]
1895    
1896    def cosh(arg):
1897       """
1898       returns hyperbolic cosine of argument arg
1899    
1900       @param arg: argument
1901       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1902       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1903       @raises TypeError: if the type of the argument is not expected.
1904       """
1905       if isinstance(arg,numarray.NumArray):
1906          return numarray.cosh(arg)
1907       elif isinstance(arg,escript.Data):
1908          return arg._cosh()
1909       elif isinstance(arg,float):
1910          return math.cosh(arg)
1911       elif isinstance(arg,int):
1912          return math.cosh(arg)
1913       elif isinstance(arg,Symbol):
1914          return Cosh_Symbol(arg)
1915       else:
1916          raise TypeError,"cosh: Unknown argument type."
1917    
1918    class Cosh_Symbol(DependendSymbol):
1919       """
1920       L{Symbol} representing the result of the hyperbolic cosine function
1921       """
1922       def __init__(self,arg):
1923          """
1924          initialization of cosh L{Symbol} with argument arg
1925          @param arg: argument of function
1926          @type arg: typically L{Symbol}.
1927          """
1928          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1929    
1930       def getMyCode(self,argstrs,format="escript"):
1931          """
1932          returns a program code that can be used to evaluate the symbol.
1933    
1934          @param argstrs: gives for each argument a string representing the argument for the evaluation.
1935          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1936          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1937          @type format: C{str}
1938          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1939          @rtype: C{str}
1940          @raise: NotImplementedError: if the requested format is not available
1941          """
1942          if isinstance(argstrs,list):
1943              argstrs=argstrs[0]
1944          if format=="escript" or format=="str"  or format=="text":
1945             return "cosh(%s)"%argstrs
1946          else:
1947             raise NotImplementedError,"Cosh_Symbol does not provide program code for format %s."%format
1948    
1949       def substitute(self,argvals):
1950          """
1951          assigns new values to symbols in the definition of the symbol.
1952          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1953    
1954          @param argvals: new values assigned to symbols
1955          @type argvals: C{dict} with keywords of type L{Symbol}.
1956          @return: result of the substitution process. Operations are executed as much as possible.
1957          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1958          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1959          """
1960          if argvals.has_key(self):
1961             arg=argvals[self]
1962             if self.isAppropriateValue(arg):
1963                return arg
1964             else:
1965                raise TypeError,"%s: new value is not appropriate."%str(self)
1966          else:
1967             arg=self.getSubstitutedArguments(argvals)[0]
1968             return cosh(arg)
1969    
1970       def diff(self,arg):
1971          """
1972          differential of this object
1973    
1974          @param arg: the derivative is calculated with respect to arg
1975          @type arg: L{escript.Symbol}
1976          @return: derivative with respect to C{arg}
1977          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
1978          """
1979          if arg==self:
1980             return identity(self.getShape())
1981          else:
1982             myarg=self.getArgument()[0]
1983             val=matchShape(sinh(myarg),self.getDifferentiatedArguments(arg)[0])
1984             return val[0]*val[1]
1985    
1986    def tanh(arg):
1987       """
1988       returns hyperbolic tangent of argument arg
1989    
1990       @param arg: argument
1991       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1992       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1993       @raises TypeError: if the type of the argument is not expected.
1994       """
1995       if isinstance(arg,numarray.NumArray):
1996          return numarray.tanh(arg)
1997       elif isinstance(arg,escript.Data):
1998          return arg._tanh()
1999       elif isinstance(arg,float):
2000          return math.tanh(arg)
2001       elif isinstance(arg,int):
2002          return math.tanh(arg)
2003       elif isinstance(arg,Symbol):
2004          return Tanh_Symbol(arg)
2005       else:
2006          raise TypeError,"tanh: Unknown argument type."
2007    
2008    class Tanh_Symbol(DependendSymbol):
2009       """
2010       L{Symbol} representing the result of the hyperbolic tangent function
2011       """
2012       def __init__(self,arg):
2013          """
2014          initialization of tanh L{Symbol} with argument arg
2015          @param arg: argument of function
2016          @type arg: typically L{Symbol}.
2017          """
2018          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2019    
2020       def getMyCode(self,argstrs,format="escript"):
2021          """
2022          returns a program code that can be used to evaluate the symbol.
2023    
2024          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2025          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2026          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2027          @type format: C{str}
2028          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2029          @rtype: C{str}
2030          @raise: NotImplementedError: if the requested format is not available
2031          """
2032          if isinstance(argstrs,list):
2033              argstrs=argstrs[0]
2034          if format=="escript" or format=="str"  or format=="text":
2035             return "tanh(%s)"%argstrs
2036          else:
2037             raise NotImplementedError,"Tanh_Symbol does not provide program code for format %s."%format
2038    
2039       def substitute(self,argvals):
2040          """
2041          assigns new values to symbols in the definition of the symbol.
2042          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2043    
2044          @param argvals: new values assigned to symbols
2045          @type argvals: C{dict} with keywords of type L{Symbol}.
2046          @return: result of the substitution process. Operations are executed as much as possible.
2047          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2048          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2049          """
2050          if argvals.has_key(self):
2051             arg=argvals[self]
2052             if self.isAppropriateValue(arg):
2053                return arg
2054             else:
2055                raise TypeError,"%s: new value is not appropriate."%str(self)
2056          else:
2057             arg=self.getSubstitutedArguments(argvals)[0]
2058             return tanh(arg)
2059    
2060       def diff(self,arg):
2061          """
2062          differential of this object
2063    
2064          @param arg: the derivative is calculated with respect to arg
2065          @type arg: L{escript.Symbol}
2066          @return: derivative with respect to C{arg}
2067          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2068          """
2069          if arg==self:
2070             return identity(self.getShape())
2071          else:
2072             myarg=self.getArgument()[0]
2073             val=matchShape(1./cosh(myarg)**2,self.getDifferentiatedArguments(arg)[0])
2074             return val[0]*val[1]
2075    
2076    def asinh(arg):
2077       """
2078       returns inverse hyperbolic sine of argument arg
2079    
2080       @param arg: argument
2081       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2082       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2083       @raises TypeError: if the type of the argument is not expected.
2084       """
2085       if isinstance(arg,numarray.NumArray):
2086          return numarray.arcsinh(arg)
2087       elif isinstance(arg,escript.Data):
2088          return arg._asinh()
2089       elif isinstance(arg,float):
2090          return numarray.arcsinh(arg)
2091       elif isinstance(arg,int):
2092          return numarray.arcsinh(float(arg))
2093       elif isinstance(arg,Symbol):
2094          return Asinh_Symbol(arg)
2095       else:
2096          raise TypeError,"asinh: Unknown argument type."
2097    
2098    class Asinh_Symbol(DependendSymbol):
2099       """
2100       L{Symbol} representing the result of the inverse hyperbolic sine function
2101       """
2102       def __init__(self,arg):
2103          """
2104          initialization of asinh L{Symbol} with argument arg
2105          @param arg: argument of function
2106          @type arg: typically L{Symbol}.
2107          """
2108          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2109    
2110       def getMyCode(self,argstrs,format="escript"):
2111          """
2112          returns a program code that can be used to evaluate the symbol.
2113    
2114          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2115          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2116          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2117          @type format: C{str}
2118          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2119          @rtype: C{str}
2120          @raise: NotImplementedError: if the requested format is not available
2121          """
2122          if isinstance(argstrs,list):
2123              argstrs=argstrs[0]
2124          if format=="escript" or format=="str"  or format=="text":
2125             return "asinh(%s)"%argstrs
2126          else:
2127             raise NotImplementedError,"Asinh_Symbol does not provide program code for format %s."%format
2128    
2129       def substitute(self,argvals):
2130          """
2131          assigns new values to symbols in the definition of the symbol.
2132          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2133    
2134          @param argvals: new values assigned to symbols
2135          @type argvals: C{dict} with keywords of type L{Symbol}.
2136          @return: result of the substitution process. Operations are executed as much as possible.
2137          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2138          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2139          """
2140          if argvals.has_key(self):
2141             arg=argvals[self]
2142             if self.isAppropriateValue(arg):
2143                return arg
2144             else:
2145                raise TypeError,"%s: new value is not appropriate."%str(self)
2146          else:
2147             arg=self.getSubstitutedArguments(argvals)[0]
2148             return asinh(arg)
2149    
2150       def diff(self,arg):
2151          """
2152          differential of this object
2153    
2154          @param arg: the derivative is calculated with respect to arg
2155          @type arg: L{escript.Symbol}
2156          @return: derivative with respect to C{arg}
2157          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2158          """
2159          if arg==self:
2160             return identity(self.getShape())
2161          else:
2162             myarg=self.getArgument()[0]
2163             val=matchShape(1./sqrt(myarg**2+1),self.getDifferentiatedArguments(arg)[0])
2164             return val[0]*val[1]
2165    
2166    def acosh(arg):
2167       """
2168       returns inverse hyperolic cosine of argument arg
2169    
2170       @param arg: argument
2171       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2172       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2173       @raises TypeError: if the type of the argument is not expected.
2174       """
2175       if isinstance(arg,numarray.NumArray):
2176          return numarray.arccosh(arg)
2177       elif isinstance(arg,escript.Data):
2178          return arg._acosh()
2179       elif isinstance(arg,float):
2180          return numarray.arccosh(arg)
2181       elif isinstance(arg,int):
2182          return numarray.arccosh(float(arg))
2183       elif isinstance(arg,Symbol):
2184          return Acosh_Symbol(arg)
2185       else:
2186          raise TypeError,"acosh: Unknown argument type."
2187    
2188    class Acosh_Symbol(DependendSymbol):
2189       """
2190       L{Symbol} representing the result of the inverse hyperolic cosine function
2191       """
2192       def __init__(self,arg):
2193          """
2194          initialization of acosh L{Symbol} with argument arg
2195          @param arg: argument of function
2196          @type arg: typically L{Symbol}.
2197          """
2198          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2199    
2200       def getMyCode(self,argstrs,format="escript"):
2201          """
2202          returns a program code that can be used to evaluate the symbol.
2203    
2204          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2205          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2206          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2207          @type format: C{str}
2208          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2209          @rtype: C{str}
2210          @raise: NotImplementedError: if the requested format is not available
2211          """
2212          if isinstance(argstrs,list):
2213              argstrs=argstrs[0]
2214          if format=="escript" or format=="str"  or format=="text":
2215             return "acosh(%s)"%argstrs
2216          else:
2217             raise NotImplementedError,"Acosh_Symbol does not provide program code for format %s."%format
2218    
2219       def substitute(self,argvals):
2220          """
2221          assigns new values to symbols in the definition of the symbol.
2222          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2223    
2224          @param argvals: new values assigned to symbols
2225          @type argvals: C{dict} with keywords of type L{Symbol}.
2226          @return: result of the substitution process. Operations are executed as much as possible.
2227          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2228          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2229          """
2230          if argvals.has_key(self):
2231             arg=argvals[self]
2232             if self.isAppropriateValue(arg):
2233                return arg
2234             else:
2235                raise TypeError,"%s: new value is not appropriate."%str(self)
2236          else:
2237             arg=self.getSubstitutedArguments(argvals)[0]
2238             return acosh(arg)
2239    
2240       def diff(self,arg):
2241          """
2242          differential of this object
2243    
2244          @param arg: the derivative is calculated with respect to arg
2245          @type arg: L{escript.Symbol}
2246          @return: derivative with respect to C{arg}
2247          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2248          """
2249          if arg==self:
2250             return identity(self.getShape())
2251          else:
2252             myarg=self.getArgument()[0]
2253             val=matchShape(1./sqrt(myarg**2-1),self.getDifferentiatedArguments(arg)[0])
2254             return val[0]*val[1]
2255    
2256    def atanh(arg):
2257       """
2258       returns inverse hyperbolic tangent of argument arg
2259    
2260       @param arg: argument
2261       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2262       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2263       @raises TypeError: if the type of the argument is not expected.
2264       """
2265       if isinstance(arg,numarray.NumArray):
2266          return numarray.arctanh(arg)
2267       elif isinstance(arg,escript.Data):
2268          return arg._atanh()
2269       elif isinstance(arg,float):
2270          return numarray.arctanh(arg)
2271       elif isinstance(arg,int):
2272          return numarray.arctanh(float(arg))
2273       elif isinstance(arg,Symbol):
2274          return Atanh_Symbol(arg)
2275       else:
2276          raise TypeError,"atanh: Unknown argument type."
2277    
2278    class Atanh_Symbol(DependendSymbol):
2279       """
2280       L{Symbol} representing the result of the inverse hyperbolic tangent function
2281       """
2282       def __init__(self,arg):
2283          """
2284          initialization of atanh L{Symbol} with argument arg
2285          @param arg: argument of function
2286          @type arg: typically L{Symbol}.
2287          """
2288          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2289    
2290       def getMyCode(self,argstrs,format="escript"):
2291          """
2292          returns a program code that can be used to evaluate the symbol.
2293    
2294          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2295          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2296          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2297          @type format: C{str}
2298          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2299          @rtype: C{str}
2300          @raise: NotImplementedError: if the requested format is not available
2301          """
2302          if isinstance(argstrs,list):
2303              argstrs=argstrs[0]
2304          if format=="escript" or format=="str"  or format=="text":
2305             return "atanh(%s)"%argstrs
2306          else:
2307             raise NotImplementedError,"Atanh_Symbol does not provide program code for format %s."%format
2308    
2309       def substitute(self,argvals):
2310          """
2311          assigns new values to symbols in the definition of the symbol.
2312          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2313    
2314          @param argvals: new values assigned to symbols
2315          @type argvals: C{dict} with keywords of type L{Symbol}.
2316          @return: result of the substitution process. Operations are executed as much as possible.
2317          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2318          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2319          """
2320          if argvals.has_key(self):
2321             arg=argvals[self]
2322             if self.isAppropriateValue(arg):
2323                return arg
2324             else:
2325                raise TypeError,"%s: new value is not appropriate."%str(self)
2326          else:
2327             arg=self.getSubstitutedArguments(argvals)[0]
2328             return atanh(arg)
2329    
2330       def diff(self,arg):
2331          """
2332          differential of this object
2333    
2334          @param arg: the derivative is calculated with respect to arg
2335          @type arg: L{escript.Symbol}
2336          @return: derivative with respect to C{arg}
2337          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2338          """
2339          if arg==self:
2340             return identity(self.getShape())
2341          else:
2342             myarg=self.getArgument()[0]
2343             val=matchShape(1./(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2344             return val[0]*val[1]
2345    
2346    def exp(arg):
2347       """
2348       returns exponential of argument arg
2349    
2350       @param arg: argument
2351       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2352       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2353       @raises TypeError: if the type of the argument is not expected.
2354       """
2355       if isinstance(arg,numarray.NumArray):
2356          return numarray.exp(arg)
2357       elif isinstance(arg,escript.Data):
2358          return arg._exp()
2359       elif isinstance(arg,float):
2360          return math.exp(arg)
2361       elif isinstance(arg,int):
2362          return math.exp(arg)
2363       elif isinstance(arg,Symbol):
2364          return Exp_Symbol(arg)
2365       else:
2366          raise TypeError,"exp: Unknown argument type."
2367    
2368    class Exp_Symbol(DependendSymbol):
2369       """
2370       L{Symbol} representing the result of the exponential function
2371       """
2372       def __init__(self,arg):
2373          """
2374          initialization of exp L{Symbol} with argument arg
2375          @param arg: argument of function
2376          @type arg: typically L{Symbol}.
2377          """
2378          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2379    
2380       def getMyCode(self,argstrs,format="escript"):
2381          """
2382          returns a program code that can be used to evaluate the symbol.
2383    
2384          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2385          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2386          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2387          @type format: C{str}
2388          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2389          @rtype: C{str}
2390          @raise: NotImplementedError: if the requested format is not available
2391          """
2392          if isinstance(argstrs,list):
2393              argstrs=argstrs[0]
2394          if format=="escript" or format=="str"  or format=="text":
2395             return "exp(%s)"%argstrs
2396          else:
2397             raise NotImplementedError,"Exp_Symbol does not provide program code for format %s."%format
2398    
2399       def substitute(self,argvals):
2400          """
2401          assigns new values to symbols in the definition of the symbol.
2402          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2403    
2404          @param argvals: new values assigned to symbols
2405          @type argvals: C{dict} with keywords of type L{Symbol}.
2406          @return: result of the substitution process. Operations are executed as much as possible.
2407          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2408          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2409          """
2410          if argvals.has_key(self):
2411             arg=argvals[self]
2412             if self.isAppropriateValue(arg):
2413                return arg
2414             else:
2415                raise TypeError,"%s: new value is not appropriate."%str(self)
2416          else:
2417             arg=self.getSubstitutedArguments(argvals)[0]
2418             return exp(arg)
2419    
2420       def diff(self,arg):
2421          """
2422          differential of this object
2423    
2424          @param arg: the derivative is calculated with respect to arg
2425          @type arg: L{escript.Symbol}
2426          @return: derivative with respect to C{arg}
2427          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2428          """
2429          if arg==self:
2430             return identity(self.getShape())
2431          else:
2432             myarg=self.getArgument()[0]
2433             val=matchShape(self,self.getDifferentiatedArguments(arg)[0])
2434             return val[0]*val[1]
2435    
2436    def sqrt(arg):
2437       """
2438       returns square root of argument arg
2439    
2440       @param arg: argument
2441       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2442       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2443       @raises TypeError: if the type of the argument is not expected.
2444       """
2445       if isinstance(arg,numarray.NumArray):
2446          return numarray.sqrt(arg)
2447       elif isinstance(arg,escript.Data):
2448          return arg._sqrt()
2449       elif isinstance(arg,float):
2450          return math.sqrt(arg)
2451       elif isinstance(arg,int):
2452          return math.sqrt(arg)
2453       elif isinstance(arg,Symbol):
2454          return Sqrt_Symbol(arg)
2455       else:
2456          raise TypeError,"sqrt: Unknown argument type."
2457    
2458    class Sqrt_Symbol(DependendSymbol):
2459       """
2460       L{Symbol} representing the result of the square root function
2461       """
2462       def __init__(self,arg):
2463          """
2464          initialization of sqrt L{Symbol} with argument arg
2465          @param arg: argument of function
2466          @type arg: typically L{Symbol}.
2467          """
2468          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2469    
2470       def getMyCode(self,argstrs,format="escript"):
2471          """
2472          returns a program code that can be used to evaluate the symbol.
2473    
2474          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2475          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2476          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2477          @type format: C{str}
2478          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2479          @rtype: C{str}
2480          @raise: NotImplementedError: if the requested format is not available
2481          """
2482          if isinstance(argstrs,list):
2483              argstrs=argstrs[0]
2484          if format=="escript" or format=="str"  or format=="text":
2485             return "sqrt(%s)"%argstrs
2486          else:
2487             raise NotImplementedError,"Sqrt_Symbol does not provide program code for format %s."%format
2488    
2489       def substitute(self,argvals):
2490          """
2491          assigns new values to symbols in the definition of the symbol.
2492          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2493    
2494          @param argvals: new values assigned to symbols
2495          @type argvals: C{dict} with keywords of type L{Symbol}.
2496          @return: result of the substitution process. Operations are executed as much as possible.
2497          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2498          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2499          """
2500          if argvals.has_key(self):
2501             arg=argvals[self]
2502             if self.isAppropriateValue(arg):
2503                return arg
2504             else:
2505                raise TypeError,"%s: new value is not appropriate."%str(self)
2506          else:
2507             arg=self.getSubstitutedArguments(argvals)[0]
2508             return sqrt(arg)
2509    
2510       def diff(self,arg):
2511          """
2512          differential of this object
2513    
2514          @param arg: the derivative is calculated with respect to arg
2515          @type arg: L{escript.Symbol}
2516          @return: derivative with respect to C{arg}
2517          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2518          """
2519          if arg==self:
2520             return identity(self.getShape())
2521          else:
2522             myarg=self.getArgument()[0]
2523             val=matchShape(0.5/self,self.getDifferentiatedArguments(arg)[0])
2524             return val[0]*val[1]
2525    
2526    def log(arg):
2527       """
2528       returns natural logarithm of argument arg
2529    
2530       @param arg: argument
2531       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2532       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2533       @raises TypeError: if the type of the argument is not expected.
2534       """
2535       if isinstance(arg,numarray.NumArray):
2536          return numarray.log(arg)
2537       elif isinstance(arg,escript.Data):
2538          return arg._log()
2539       elif isinstance(arg,float):
2540          return math.log(arg)
2541       elif isinstance(arg,int):
2542          return math.log(arg)
2543       elif isinstance(arg,Symbol):
2544          return Log_Symbol(arg)
2545       else:
2546          raise TypeError,"log: Unknown argument type."
2547    
2548    class Log_Symbol(DependendSymbol):
2549       """
2550       L{Symbol} representing the result of the natural logarithm function
2551       """
2552       def __init__(self,arg):
2553          """
2554          initialization of log L{Symbol} with argument arg
2555          @param arg: argument of function
2556          @type arg: typically L{Symbol}.
2557          """
2558          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2559    
2560       def getMyCode(self,argstrs,format="escript"):
2561          """
2562          returns a program code that can be used to evaluate the symbol.
2563    
2564          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2565          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2566          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2567          @type format: C{str}
2568          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2569          @rtype: C{str}
2570          @raise: NotImplementedError: if the requested format is not available
2571          """
2572          if isinstance(argstrs,list):
2573              argstrs=argstrs[0]
2574          if format=="escript" or format=="str"  or format=="text":
2575             return "log(%s)"%argstrs
2576          else:
2577             raise NotImplementedError,"Log_Symbol does not provide program code for format %s."%format
2578    
2579       def substitute(self,argvals):
2580          """
2581          assigns new values to symbols in the definition of the symbol.
2582          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2583    
2584          @param argvals: new values assigned to symbols
2585          @type argvals: C{dict} with keywords of type L{Symbol}.
2586          @return: result of the substitution process. Operations are executed as much as possible.
2587          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2588          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2589          """
2590          if argvals.has_key(self):
2591             arg=argvals[self]
2592             if self.isAppropriateValue(arg):
2593                return arg
2594             else:
2595                raise TypeError,"%s: new value is not appropriate."%str(self)
2596          else:
2597             arg=self.getSubstitutedArguments(argvals)[0]
2598             return log(arg)
2599    
2600       def diff(self,arg):
2601          """
2602          differential of this object
2603    
2604          @param arg: the derivative is calculated with respect to arg
2605          @type arg: L{escript.Symbol}
2606          @return: derivative with respect to C{arg}
2607          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2608          """
2609          if arg==self:
2610             return identity(self.getShape())
2611          else:
2612             myarg=self.getArgument()[0]
2613             val=matchShape(1./arg,self.getDifferentiatedArguments(arg)[0])
2614             return val[0]*val[1]
2615    
2616    def sign(arg):
2617       """
2618       returns sign of argument arg
2619    
2620       @param arg: argument
2621       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2622       @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2623       @raises TypeError: if the type of the argument is not expected.
2624       """
2625       if isinstance(arg,numarray.NumArray):
2626          return wherePositive(arg)-whereNegative(arg)
2627       elif isinstance(arg,escript.Data):
2628          return arg._sign()
2629       elif isinstance(arg,float):
2630          if arg>0:
2631            return 1.
2632          elif arg<0:
2633            return -1.
2634          else:
2635            return 0.
2636       elif isinstance(arg,int):
2637          if float(arg)>0:
2638            return 1.
2639          elif float(arg)<0:
2640            return -1.
2641          else:
2642            return 0.
2643       elif isinstance(arg,Symbol):
2644          return wherePositive(arg)-whereNegative(arg)
2645       else:
2646          raise TypeError,"sign: Unknown argument type."
2647    
2648    class Abs_Symbol(DependendSymbol):
2649       """
2650       L{Symbol} representing the result of the absolute value function
2651       """
2652       def __init__(self,arg):
2653          """
2654          initialization of abs L{Symbol} with argument arg
2655          @param arg: argument of function
2656          @type arg: typically L{Symbol}.
2657          """
2658          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2659    
2660       def getMyCode(self,argstrs,format="escript"):
2661          """
2662          returns a program code that can be used to evaluate the symbol.
2663    
2664          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2665          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2666          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2667          @type format: C{str}
2668          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2669          @rtype: C{str}
2670          @raise: NotImplementedError: if the requested format is not available
2671          """
2672          if isinstance(argstrs,list):
2673              argstrs=argstrs[0]
2674          if format=="escript" or format=="str"  or format=="text":
2675             return "abs(%s)"%argstrs
2676          else:
2677             raise NotImplementedError,"Abs_Symbol does not provide program code for format %s."%format
2678    
2679       def substitute(self,argvals):
2680          """
2681          assigns new values to symbols in the definition of the symbol.
2682          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2683    
2684          @param argvals: new values assigned to symbols
2685          @type argvals: C{dict} with keywords of type L{Symbol}.
2686          @return: result of the substitution process. Operations are executed as much as possible.
2687          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2688          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2689          """
2690          if argvals.has_key(self):
2691             arg=argvals[self]
2692             if self.isAppropriateValue(arg):
2693                return arg
2694             else:
2695                raise TypeError,"%s: new value is not appropriate."%str(self)
2696          else:
2697             arg=self.getSubstitutedArguments(argvals)[0]
2698             return abs(arg)
2699    
2700       def diff(self,arg):
2701          """
2702          differential of this object
2703    
2704          @param arg: the derivative is calculated with respect to arg
2705          @type arg: L{escript.Symbol}
2706          @return: derivative with respect to C{arg}
2707          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2708          """
2709          if arg==self:
2710             return identity(self.getShape())
2711          else:
2712             myarg=self.getArgument()[0]
2713             val=matchShape(sign(myarg),self.getDifferentiatedArguments(arg)[0])
2714             return val[0]*val[1]
2715    
2716    def minval(arg):
2717       """
2718       returns minimum value over all components of arg at each data point
2719    
2720       @param arg: argument
2721       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2722       @rtype:C{float}, L{escript.Data}, L{Symbol} depending on the type of arg.
2723       @raises TypeError: if the type of the argument is not expected.
2724       """
2725       if isinstance(arg,numarray.NumArray):
2726          if arg.rank==0:
2727             return float(arg)
2728          else:
2729             return arg.min()
2730       elif isinstance(arg,escript.Data):
2731          return arg._minval()
2732       elif isinstance(arg,float):
2733          return arg
2734       elif isinstance(arg,int):
2735          return float(arg)
2736       elif isinstance(arg,Symbol):
2737          return Minval_Symbol(arg)
2738       else:
2739          raise TypeError,"minval: Unknown argument type."
2740    
2741    class Minval_Symbol(DependendSymbol):
2742       """
2743       L{Symbol} representing the result of the minimum value function
2744       """
2745       def __init__(self,arg):
2746          """
2747          initialization of minimum value L{Symbol} with argument arg
2748          @param arg: argument of function
2749          @type arg: typically L{Symbol}.
2750          """
2751          DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
2752    
2753       def getMyCode(self,argstrs,format="escript"):
2754          """
2755          returns a program code that can be used to evaluate the symbol.
2756    
2757          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2758          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2759          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2760          @type format: C{str}
2761          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2762          @rtype: C{str}
2763          @raise: NotImplementedError: if the requested format is not available
2764          """
2765          if isinstance(argstrs,list):
2766              argstrs=argstrs[0]
2767          if format=="escript" or format=="str"  or format=="text":
2768             return "minval(%s)"%argstrs
2769          else:
2770             raise NotImplementedError,"Minval_Symbol does not provide program code for format %s."%format
2771    
2772       def substitute(self,argvals):
2773          """
2774          assigns new values to symbols in the definition of the symbol.
2775          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2776    
2777          @param argvals: new values assigned to symbols
2778          @type argvals: C{dict} with keywords of type L{Symbol}.
2779          @return: result of the substitution process. Operations are executed as much as possible.
2780          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2781          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2782          """
2783          if argvals.has_key(self):
2784             arg=argvals[self]
2785             if self.isAppropriateValue(arg):
2786                return arg
2787             else:
2788                raise TypeError,"%s: new value is not appropriate."%str(self)
2789          else:
2790             arg=self.getSubstitutedArguments(argvals)[0]
2791             return minval(arg)
2792    
2793  def maxval(arg):  def maxval(arg):
2794      """     """
2795      @brief     returns maximum value over all components of arg at each data point
2796    
2797      @param arg     @param arg: argument
2798      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2799      if isinstance(arg,escript.Data):     @rtype:C{float}, L{escript.Data}, L{Symbol} depending on the type of arg.
2800         return arg.maxval()     @raises TypeError: if the type of the argument is not expected.
2801       """
2802       if isinstance(arg,numarray.NumArray):
2803          if arg.rank==0:
2804             return float(arg)
2805          else:
2806             return arg.max()
2807       elif isinstance(arg,escript.Data):
2808          return arg._maxval()
2809       elif isinstance(arg,float):
2810          return arg
2811       elif isinstance(arg,int):
2812          return float(arg)
2813       elif isinstance(arg,Symbol):
2814          return Maxval_Symbol(arg)
2815       else:
2816          raise TypeError,"maxval: Unknown argument type."
2817    
2818    class Maxval_Symbol(DependendSymbol):
2819       """
2820       L{Symbol} representing the result of the maximum value function
2821       """
2822       def __init__(self,arg):
2823          """
2824          initialization of maximum value L{Symbol} with argument arg
2825          @param arg: argument of function
2826          @type arg: typically L{Symbol}.
2827          """
2828          DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
2829    
2830       def getMyCode(self,argstrs,format="escript"):
2831          """
2832          returns a program code that can be used to evaluate the symbol.
2833    
2834          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2835          @type argstrs: C{str} or a C{list} of length 1 of C{str}.
2836          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2837          @type format: C{str}
2838          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2839          @rtype: C{str}
2840          @raise: NotImplementedError: if the requested format is not available
2841          """
2842          if isinstance(argstrs,list):
2843              argstrs=argstrs[0]
2844          if format=="escript" or format=="str"  or format=="text":
2845             return "maxval(%s)"%argstrs
2846          else:
2847             raise NotImplementedError,"Maxval_Symbol does not provide program code for format %s."%format
2848    
2849       def substitute(self,argvals):
2850          """
2851          assigns new values to symbols in the definition of the symbol.
2852          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2853    
2854          @param argvals: new values assigned to symbols
2855          @type argvals: C{dict} with keywords of type L{Symbol}.
2856          @return: result of the substitution process. Operations are executed as much as possible.
2857          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2858          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2859          """
2860          if argvals.has_key(self):
2861             arg=argvals[self]
2862             if self.isAppropriateValue(arg):
2863                return arg
2864             else:
2865                raise TypeError,"%s: new value is not appropriate."%str(self)
2866          else:
2867             arg=self.getSubstitutedArguments(argvals)[0]
2868             return maxval(arg)
2869    
2870    def length(arg):
2871       """
2872       returns length/Euclidean norm of argument arg at each data point
2873    
2874       @param arg: argument
2875       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2876       @rtype:C{float}, L{escript.Data}, L{Symbol} depending on the type of arg.
2877       """
2878       return sqrt(inner(arg,arg))
2879    
2880    #=======================================================
2881    #  Binary operations:
2882    #=======================================================
2883    def add(arg0,arg1):
2884           """
2885           adds arg0 and arg1 together.
2886    
2887           @param arg0: first term
2888           @type arg0: L{escript.Symbol}, C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
2889           @param arg1: second term
2890           @type arg1: L{escript.Symbol}, C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
2891           @return: the some of arg0 and arg1
2892           @rtype: L{escript.Symbol}, C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
2893           @note: The shape of both arguments is matched according to the rules in used in L{matchShape}
2894           """
2895           args=matchShape(arg0,arg1)
2896           if testForZero(args[0]):
2897              return args[1]
2898           elif testForZero(args[1]):
2899              return args[0]
2900           else:
2901              if isinstance(args[0],Symbol) or isinstance(args[1],Symbol) :
2902                  return Add_Symbol(args[0],args[1])
2903              elif isinstance(args[0],numarray.NumArray):
2904                  return args[1]+args[0]
2905              else:
2906                  return args[0]+args[1]
2907    
2908    class Add_Symbol(DependendSymbol):
2909       """
2910       Symbol representing the sum of two arguments.
2911       """
2912       def __init__(self,arg0,arg1):
2913           """
2914           initialization of the L{Symbol} representing the sum of two arguments
2915    
2916           @param arg0: first term in the sum
2917           @type arg0: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
2918           @param arg1: second term in the sum
2919           @type arg1: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
2920           @raise ValueError: if both arguments do not have the same shape.
2921           @note: if both arguments have a spatial dimension, they must equal.
2922           """
2923           sh0=pokeShape(arg0)
2924           sh1=pokeShape(arg1)
2925           if not sh0==sh1:
2926              raise ValueError,"Add_Symbol: shape of arguments must match"
2927           DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0,args=[arg0,arg1])
2928    
2929       def getMyCode(self,argstrs,format="escript"):
2930          """
2931          returns a program code that can be used to evaluate the symbol.
2932    
2933          @param argstrs: gives for each argument a string representing the argument for the evaluation.
2934          @type argstrs: C{list} of length 2 of C{str}.
2935          @param format: specifies the format to be used. At the moment only "escript", "str" and "text" are supported.
2936          @type format: C{str}
2937          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2938          @rtype: C{str}
2939          @raise: NotImplementedError: if the requested format is not available
2940          """
2941          if format=="str" or format=="text":
2942             return "(%s)+(%s)"%(argstrs[0],argstrs[1])
2943          elif format=="escript":
2944             return "add(%s,%s)"%(argstrs[0],argstrs[1])
2945          else:
2946             raise NotImplementedError,"%s does not provide program code for format %s."%(str(self),format)
2947    
2948       def substitute(self,argvals):
2949          """
2950          assigns new values to symbols in the definition of the symbol.
2951          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2952    
2953          @param argvals: new values assigned to symbols
2954          @type argvals: C{dict} with keywords of type L{Symbol}.
2955          @return: result of the substitution process. Operations are executed as much as possible.
2956          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2957          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2958          """
2959          if argvals.has_key(self):
2960             arg=argvals[self]
2961             if self.isAppropriateValue(arg):
2962                return arg
2963             else:
2964                raise TypeError,"%s: new value is not appropriate."%str(self)
2965          else:
2966             args=self.getSubstitutedArguments(argvals)
2967             return add(args[0],args[1])
2968    
2969       def diff(self,arg):
2970          """
2971          differential of this object
2972    
2973          @param arg: the derivative is calculated with respect to arg
2974          @type arg: L{escript.Symbol}
2975          @return: derivative with respect to C{arg}
2976          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
2977          """
2978          if arg==self:
2979             return identity(self.getShape())
2980          else:
2981             dargs=self.getDifferentiatedArguments(arg)
2982             return add(dargs[0],dargs[1])
2983    
2984    def mult(arg0,arg1):
2985           """
2986           product of arg0 and arg1
2987    
2988           @param arg0: first term
2989           @type arg0: L{escript.Symbol}, C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
2990           @param arg1: second term
2991           @type arg1: L{escript.Symbol}, C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
2992           @return: the some of arg0 and arg1
2993           @rtype: L{escript.Symbol}, C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
2994           @note: The shape of both arguments is matched according to the rules in used in L{matchShape}
2995           """
2996           args=matchShape(arg0,arg1)
2997           if testForZero(args[0]) or testForZero(args[1]):
2998              return numarray.zeros(pokeShape(args[0]),numarray.Float)
2999           else:
3000              if isinstance(args[0],Symbol) or isinstance(args[1],Symbol) :
3001                  return Mult_Symbol(args[0],args[1])
3002              elif isinstance(args[0],numarray.NumArray):
3003                  return args[1]*args[0]
3004              else:
3005                  return args[0]*args[1]
3006    
3007    class Mult_Symbol(DependendSymbol):
3008       """
3009       Symbol representing the product of two arguments.
3010       """
3011       def __init__(self,arg0,arg1):
3012           """
3013           initialization of the L{Symbol} representing the product of two arguments
3014    
3015           @param arg0: first factor
3016           @type arg0: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
3017           @param arg1: second factor
3018           @type arg1: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
3019           @raise ValueError: if both arguments do not have the same shape.
3020           @note: if both arguments have a spatial dimension, they must equal.
3021           """
3022           sh0=pokeShape(arg0)
3023           sh1=pokeShape(arg1)
3024           if not sh0==sh1:
3025              raise ValueError,"Mult_Symbol: shape of arguments must match"
3026           DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0,args=[arg0,arg1])
3027    
3028       def getMyCode(self,argstrs,format="escript"):
3029          """
3030          returns a program code that can be used to evaluate the symbol.
3031    
3032          @param argstrs: gives for each argument a string representing the argument for the evaluation.
3033          @type argstrs: C{list} of length 2 of C{str}.
3034          @param format: specifies the format to be used. At the moment only "escript", "str" and "text" are supported.
3035          @type format: C{str}
3036          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
3037          @rtype: C{str}
3038          @raise: NotImplementedError: if the requested format is not available
3039          """
3040          if format=="str" or format=="text":
3041             return "(%s)*(%s)"%(argstrs[0],argstrs[1])
3042          elif format=="escript":
3043             return "mult(%s,%s)"%(argstrs[0],argstrs[1])
3044          else:
3045             raise NotImplementedError,"%s does not provide program code for format %s."%(str(self),format)
3046    
3047       def substitute(self,argvals):
3048          """
3049          assigns new values to symbols in the definition of the symbol.
3050          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
3051    
3052          @param argvals: new values assigned to symbols
3053          @type argvals: C{dict} with keywords of type L{Symbol}.
3054          @return: result of the substitution process. Operations are executed as much as possible.
3055          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
3056          @raise TypeError: if a value for a L{Symbol} cannot be substituted.
3057          """
3058          if argvals.has_key(self):
3059             arg=argvals[self]
3060             if self.isAppropriateValue(arg):
3061                return arg
3062             else:
3063                raise TypeError,"%s: new value is not appropriate."%str(self)
3064          else:
3065             args=self.getSubstitutedArguments(argvals)
3066             return mult(args[0],args[1])
3067    
3068       def diff(self,arg):
3069          """
3070          differential of this object
3071    
3072          @param arg: the derivative is calculated with respect to arg
3073          @type arg: L{escript.Symbol}
3074          @return: derivative with respect to C{arg}
3075          @rtype: typically L{Symbol} but other types such as C{float}, L{escript.Data}, L{numarray.NumArray}  are possible.
3076          """
3077          if arg==self:
3078             return identity(self.getShape())
3079          else:
3080             myargs=self.getArgument()
3081             dargs=self.getDifferentiatedArguments(arg)
3082             return add(mult(myargs[0],dargs[1]),mult(myargs[1],dargs[0]))
3083    
3084    def quotient(arg0,arg1):
3085           """
3086           quotient of arg0 and arg1
3087    
3088           @param arg0: numerator
3089           @type arg0: L{escript.Symbol}, C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
3090           @param arg1: denominator
3091           @type arg1: L{escript.Symbol}, C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
3092           @return: the some of arg0 and arg1
3093           @rtype: L{escript.Symbol}, C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
3094           @note: The shape of both arguments is matched according to the rules in used in L{matchShape}
3095           """
3096           args=matchShape(arg0,arg1)
3097           if testForZero(args[0]):
3098              return numarray.zeros(pokeShape(args[0]),numarray.Float)
3099           elif isinstance(args[0],Symbol):
3100              if isinstance(args[1],Symbol):
3101                 return Quotient_Symbol(args[0],args[1])
3102              else:
3103                 return mult(args[0],1./args[1])
3104           else:
3105              if isinstance(args[1],Symbol):
3106                 return Quotient_Symbol(args[0],args[1])
3107 &n