/[escript]/trunk-mpi-branch/escript/py_src/util.py
ViewVC logotype

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