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

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

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

trunk/esys2/escript/py_src/util.py revision 147 by jgs, Fri Aug 12 01:45:47 2005 UTC trunk/escript/py_src/util.py revision 397 by gross, Wed Dec 21 05:11:31 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  TODO for Data:  @remark:  This module is under construction and is still tested!!!
16    
17    * binary operations @:               (a@b)[:,*]=a[:]@b[:,*] if rank(a)<rank(b)  @var __author__: name of author
18                  @=+,-,*,/,**           (a@b)[:]=a[:]@b[:] if rank(a)=rank(b)  @var __licence__: licence agreement
19                                         (a@b)[*,:]=a[*,:]@b[:] if rank(a)>rank(b)  @var __url__: url entry point on documentation
20      @var __version__: version
21    * implementation of outer outer(a,b)[:,*]=a[:]*b[*]  @var __date__: date of the version
   * trace: trace(arg,axis0=a0,axis1=a1)(:,&,*)=sum_i trace(:,i,&,i,*) (i are at index a0 and a1)  
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 with utilC.h )  # slicing: get
57    #          set
58  #  #
59  UNKNOWN=-1  # and derivatives
60  EPSILON=1.e-15  
61  Pi=numarray.pi  #=========================================================
62  # some solver options:  #   some helpers:
63  NO_REORDERING=0  #=========================================================
64  MINIMUM_FILL_IN=1  def saveVTK(filename,domain=None,**data):
65  NESTED_DISSECTION=2      """
66  # solver methods      writes a L{Data} objects into a files using the the VTK XML file format.
67  DEFAULT_METHOD=0  
68  DIRECT=1      Example:
69  CHOLEVSKY=2  
70  PCG=3         tmp=Scalar(..)
71  CR=4         v=Vector(..)
72  CGS=5         saveVTK("solution.xml",temperature=tmp,velovity=v)
73  BICGSTAB=6  
74  SSOR=7      tmp and v are written into "solution.xml" where tmp is named "temperature" and v is named "velovity"
75  ILU0=8  
76  ILUT=9      @param filename: file name of the output file
77  JACOBI=10      @type filename: C{str}
78  GMRES=11      @param domain: domain of the L{Data} object. If not specified, the domain of the given L{Data} objects is used.
79  PRES20=12      @type domain: L{escript.Domain}
80        @keyword <name>: writes the assigned value to the VTK file using <name> as identifier.
81  METHOD_KEY="method"      @type <name>: L{Data} object.
82  SYMMETRY_KEY="symmetric"      @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  TOLERANCE_KEY="tolerance"      """
84        if domain==None:
85  # supported file formats:         for i in data.keys():
86  VRML=1            if not data[i].isEmpty(): domain=data[i].getFunctionSpace().getDomain()
87  PNG=2      if domain==None:
88  JPEG=3          raise ValueError,"no domain detected."
89  JPG=3      else:
90  PS=4          domain.saveVTK(filename,data)
91  OOGL=5  
92  BMP=6  def saveDX(filename,domain=None,**data):
93  TIFF=7      """
94  OPENINVENTOR=8      writes a L{Data} objects into a files using the the DX file format.
95  RENDERMAN=9  
96  PNM=10      Example:
97    
98  #===========================================================         tmp=Scalar(..)
99  # a simple tool box to deal with _differentials of functions         v=Vector(..)
100  #===========================================================         saveDX("solution.dx",temperature=tmp,velovity=v)
101    
102  class Symbol:      tmp and v are written into "solution.dx" where tmp is named "temperature" and v is named "velovity".
103     """symbol class"""  
104     def __init__(self,name="symbol",shape=(),dim=3,args=[]):      @param filename: file name of the output file
105         """creates an instance of a symbol of shape shape and spatial dimension dim      @type filename: C{str}
106            The symbol may depending on a list of arguments args which      @param domain: domain of the L{Data} object. If not specified, the domain of the given L{Data} objects is used.
107            may be symbols or other objects. name gives the name of the symbol."""      @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        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    def kronecker(d=3):
121       """
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        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        @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 sup(arg):
223        """
224        returns the maximum value over all data points.
225    
226        @param arg: argument
227        @type arg: C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
228        @return: maximum value of arg over all components and all data points
229        @rtype: C{float}
230        @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:
241          raise TypeError,"sup: Unknown argument type."
242    
243    def inf(arg):
244        """
245        returns the maximum value over all data points.
246    
247        @param arg: argument
248        @type arg: C{float}, C{int}, L{escript.Data}, L{numarray.NumArray}.
249        @return : minimum value of arg over all components and all data points
250        @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:
262          raise TypeError,"inf: Unknown argument type."
263    
264    
265    #=========================================================================
266    #   some little helpers
267    #=========================================================================
268    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:
290          raise TypeError,"pokeShape: cannot identify shape"
291    
292    def pokeDim(arg):
293        """
294        identifies the spatial dimension of its argument
295    
296        @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):
303            return arg.getFunctionSpace().getDim()
304        elif isinstance(arg,Symbol):
305            return arg.getDim()
306        else:
307            return None
308    
309    def commonShape(arg0,arg1):
310        """
311        returns a shape to which arg0 can be extendent from the right and arg1 can be extended from the left.
312    
313        @param arg0: an object with a shape (see L{pokeShape})
314        @param arg1: an object with a shape (see L{pokeShape})
315        @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        @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:
330           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 matchType(arg0=0.,arg1=0.):
377        """
378        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 arg0: first argument
381        @type arg0: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, C{Symbol}
382        @param arg1: second argument
383        @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:
458          raise TypeError,"function: Unknown type of first argument."    
459    
460        return arg0,arg1
461    
462    def matchShape(arg0,arg1):
463        """
464        
465    
466        If shape is not given the shape "largest" shape of args is used.
467    
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         self.__args=args
        self.__name=name  
510         self.__shape=shape         self.__shape=shape
511         if hasattr(dim,"getDim"):         self.__dim=dim
            self.__dim=dim.getDim()  
        else:      
            self.__dim=dim  
        #  
        self.__cache_val=None  
        self.__cache_argval=None  
   
    def getArgument(self,i):  
        """returns the i-th argument"""  
        return self.__args[i]  
512    
513     def getDim(self):     def getArgument(self,i=None):
514         """returns the spatial dimension of the symbol"""         """
515         return self.__dim         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):     def getRank(self):
531         """returns the rank of the symbol"""         """
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())         return len(self.getShape())
538    
539     def getShape(self):     def getShape(self):
540         """returns the shape of the symbol"""         """
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         return self.__shape
547    
548     def getEvaluatedArguments(self,argval):     def getDim(self):
549         """returns the list of evaluated arguments by subsituting symbol u by argval[u]."""         """
550         if argval==self.__cache_argval:         the spatial dimension
551             print "%s: cached value used"%self  
552             return self.__cache_val         @return : the spatial dimension
553         else:         @rtype: C{int} if the dimension is defined. Otherwise C{None} is returned.
554             out=[]         """
555             for a  in self.__args:         return self.__dim
556                if isinstance(a,Symbol):    
557                  out.append(a.eval(argval))     def __str__(self):
558                else:         """
559                  out.append(a)         a string representation of the symbol.
560             self.__cache_argval=argval         @return: a string representation of the object
561             self.__cache_val=out         @rtype: C{str}
562             return out         """
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):     def getDifferentiatedArguments(self,arg):
590         """returns the list of the arguments _differentiated by arg"""         """
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=[]         out=[]
599         for a in self.__args:         for a in self.getArgument():
600            if isinstance(a,Symbol):            if isinstance(a,Symbol):
601              out.append(a.diff(arg))               out.append(a.substitute(argvals))
602            else:            else:
603              out.append(0)                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         return out
609    
610     def diff(self,arg):     def isAppropriateValue(self,arg):
611         """returns the _differention of self by arg."""        """
612         if self==arg:        checks if the given argument arg can be used as a substitution of this object. The method checks
613            out=numarray.zeros(tuple(2*list(self.getShape())),numarray.Float)        the shape of arg and, if the spatial dimension is defined, the spatial dimension of arg.    
614            if self.getRank()==0:  
615               out=1.        @param arg: a given object
616            elif self.getRank()==1:        @type arg: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, C{Symbol}
617                for i0 in range(self.getShape()[0]):        @return: True if arg is a suitbale object to be used for substitution. Otherwise False is returned.
618                   out[i0,i0]=1.          @rtype: C{bool}
619            elif self.getRank()==2:        """
620                for i0 in range(self.getShape()[0]):        if isinstance(arg,numarray.NumArray):
621                  for i1 in range(self.getShape()[1]):            return arg.shape==self.getShape()
622                       out[i0,i1,i0,i1]=1.          elif isinstance(arg,escript.Data):
623            elif self.getRank()==3:            if self.getDim()==None:
624                for i0 in range(self.getShape()[0]):                return arg.getShape()==self.getShape()
625                  for i1 in range(self.getShape()[1]):            elif self.getDim()==arg.getFunctionSpace().getDim():
626                    for i2 in range(self.getShape()[2]):                return arg.getShape()==self.getShape()
                      out[i0,i1,i2,i0,i1,i2]=1.    
           elif self.getRank()==4:  
               for i0 in range(self.getShape()[0]):  
                 for i1 in range(self.getShape()[1]):  
                   for i2 in range(self.getShape()[2]):  
                     for i3 in range(self.getShape()[3]):  
                        out[i0,i1,i2,i3,i0,i1,i2,i3]=1.    
627            else:            else:
628               raise ValueError,"differential support rank<5 only."                return False
629            return out        elif isinstance(arg,Symbol):
630         else:            if self.getDim()==None:
631            return self._diff(arg)                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 _diff(self,arg):     def getMyCode(self,argstrs,format="escript"):
644         """return derivate of self with respect to arg (!=self).         """
645            This method is overwritten by a particular symbol"""         returns a program code that can be used to evaluate the symbol.
646         return 0  
647           @param argstrs: gives for each argument a string representing the argument for the evaluation.
648     def eval(self,argval):         @type argstrs: C{list} of C{str}.
649         """subsitutes symbol u in self by argval[u] and returns the result. If         @param format: specifies the format to be used. At the moment only "escript", "str" and "text" are supported.
650            self is not a key of argval then self is returned."""         @type format: C{str}
651         if argval.has_key(self):         @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
652           return argval[self]         @rtype: C{str}
653         else:         @raise NotImplementedError: if no implementation for the given format is available
654           return self         @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 __str__(self):     def diff(self,arg):
681         """returns a string representation of the symbol"""         """
682         return self.__name         returns the derivative of the symbol with respect to L{Symbol} arg
683    
684     def __add__(self,other):         @param arg: the derivative is calculated with respect to arg
685         """adds other to symbol self. if _testForZero(other) self is returned."""         @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         if _testForZero(other):         @return: derivative with respect to C{arg}
687            return self         @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:         else:
693            a=_matchShape([self,other])            s=self.getShape()+arg.getShape()
694            return Add_Symbol(a[0],a[1])            if len(s)>0:
695                 return numarray.zeros(s,numarray.Float)
696     def __radd__(self,other):            else:
697         """adds other to symbol self. if _testForZero(other) self is returned."""               return 0.
        return self+other  
698    
699     def __neg__(self):     def __neg__(self):
700         """returns -self."""         """
701           returns -self.
702    
703           @return:  a S{Symbol} representing the negative of the object
704           @rtype: L{DependendSymbol}
705           """
706         return self*(-1.)         return self*(-1.)
707    
708     def __pos__(self):     def __pos__(self):
709         """returns +self."""         """
710         return self         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):     def __abs__(self):
718         """returns absolute value"""         """
719           returns a S{Symbol} representing the absolute value of the object.
720           """
721         return Abs_Symbol(self)         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):     def __sub__(self,other):
746         """subtracts other from symbol self. if _testForZero(other) self is returned."""         """
747         if _testForZero(other):         subtracts another object from this object
748            return self  
749         else:         @param other: object to be subtracted from this object
750            return self+(-other)         @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):     def __rsub__(self,other):
757         """subtracts symbol self from other."""         """
758         return -self+other         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):     def __div__(self,other):
790         """divides symbol self by other."""         """
791         if isinstance(other,Symbol):         divides this object by other object
792            a=_matchShape([self,other])  
793            return Div_Symbol(a[0],a[1])         @param other: object dividing this object
794         else:         @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
795            return self*(1./other)         @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):     def __rdiv__(self,other):
801         """dived other by symbol self. if _testForZero(other) 0 is returned."""         """
802         if _testForZero(other):         divides this object by other object
803            return 0  
804         else:         @param other: object dividing this object
805            a=_matchShape([self,other])         @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
806            return Div_Symbol(a[0],a[1])         @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):     def __pow__(self,other):
812         """raises symbol self to the power of other"""         """
813         a=_matchShape([self,other])         raises this object to the power of other
814         return Power_Symbol(a[0],a[1])  
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):     def __rpow__(self,other):
823         """raises other to the symbol self"""         """
824         a=_matchShape([self,other])         raises an object to the power of this object
        return Power_Symbol(a[1],a[0])  
825    
826     def __mul__(self,other):         @param other: basis
827         """multiplies other by symbol self. if _testForZero(other) 0 is returned."""         @type other: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}.
828         if _testForZero(other):         @return: a S{Symbol} representing the power of C{other} to this object
829            return 0         @rtype: L{DependendSymbol} or 0 if C{other} is identical to zero.
830         else:         """
831            a=_matchShape([self,other])         return power(other,self)
           return Mult_Symbol(a[0],a[1])  
832    
833     def __rmul__(self,other):  class DependendSymbol(Symbol):
834         """multiplies other by symbol self. if _testSForZero(other) 0 is returned."""     """
835         return self*other     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     def __getitem__(self,sl):     u1=DependendSymbol(shape=(3,4),dim=2,args=[4.])
848            print sl     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  def Float_Symbol(Symbol):     @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      def __init__(self,name="symbol",shape=(),args=[]):     """
855          Symbol.__init__(self,dim=0,name="symbol",shape=(),args=[])     def __eq__(self,other):
856          """
857  class ScalarSymbol(Symbol):        checks if other equals self
858     """a scalar symbol"""  
859     def __init__(self,dim=3,name="scalar"):        @param other: any object
860        """creates a scalar symbol of spatial dimension dim"""        @return: True if other has the same class like self, and the shape, the spatial diemsnion and the arguments are equal.
861        if hasattr(dim,"getDim"):        @rtype: C{bool}
862             d=dim.getDim()        """
863        else:            if isinstance(other,DependendSymbol):
864             d=dim           if self.__class__==other.__class__:  
865        Symbol.__init__(self,shape=(),dim=d,name=name)              if self.getShape()==other.getShape():
866                  if self.getArgument()==other.getArgument():
867  class VectorSymbol(Symbol):                   if self.getDim()==None or other.getDim()==None or self.getDim()==other.getDim():
868     """a vector symbol"""                      return True
869     def __init__(self,dim=3,name="vector"):        return False
       """creates a vector symbol of spatial dimension dim"""  
       if hasattr(dim,"getDim"):  
            d=dim.getDim()  
       else:      
            d=dim  
       Symbol.__init__(self,shape=(d,),dim=d,name=name)  
   
 class TensorSymbol(Symbol):  
    """a tensor symbol"""  
    def __init__(self,dim=3,name="tensor"):  
       """creates a tensor symbol of spatial dimension dim"""  
       if hasattr(dim,"getDim"):  
            d=dim.getDim()  
       else:      
            d=dim  
       Symbol.__init__(self,shape=(d,d),dim=d,name=name)  
   
 class Tensor3Symbol(Symbol):  
    """a tensor order 3 symbol"""  
    def __init__(self,dim=3,name="tensor3"):  
       """creates a tensor order 3 symbol of spatial dimension dim"""  
       if hasattr(dim,"getDim"):  
            d=dim.getDim()  
       else:      
            d=dim  
       Symbol.__init__(self,shape=(d,d,d),dim=d,name=name)  
   
 class Tensor4Symbol(Symbol):  
    """a tensor order 4 symbol"""  
    def __init__(self,dim=3,name="tensor4"):  
       """creates a tensor order 4 symbol of spatial dimension dim"""      
       if hasattr(dim,"getDim"):  
            d=dim.getDim()  
       else:      
            d=dim  
       Symbol.__init__(self,shape=(d,d,d,d),dim=d,name=name)  
870    
871  class Add_Symbol(Symbol):     def __ne__(self,other):
872     """symbol representing the sum of two arguments"""        """
873     def __init__(self,arg0,arg1):        checks if other equals self
874         a=[arg0,arg1]  
875         Symbol.__init__(self,dim=_extractDim(a),shape=_extractShape(a),args=a)        @param other: any object
876     def __str__(self):        @return: Flase if other has the same class like self, and the shape, the spatial diemsnion and the arguments are equal.
877        return "(%s+%s)"%(str(self.getArgument(0)),str(self.getArgument(1)))        @rtype: C{bool}
878     def eval(self,argval):        """
879         a=self.getEvaluatedArguments(argval)        return not self==other
880         return a[0]+a[1]  #=========================================================
881     def _diff(self,arg):  #  Unary operations prserving the shape
882         a=self.getDifferentiatedArguments(arg)  #========================================================
883         return a[0]+a[1]  def log10(arg):
884       """
885       returns base-10 logarithm of argument arg
886    
887  class Mult_Symbol(Symbol):     @param arg: argument
888     """symbol representing the product of two arguments"""     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
889     def __init__(self,arg0,arg1):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
890         a=[arg0,arg1]     @raises TypeError: if the type of the argument is not expected.
891         Symbol.__init__(self,dim=_extractDim(a),shape=_extractShape(a),args=a)     """
892     def __str__(self):     if isinstance(arg,numarray.NumArray):
893        return "(%s*%s)"%(str(self.getArgument(0)),str(self.getArgument(1)))        return numarray.log10(arg)
894     def eval(self,argval):     elif isinstance(arg,escript.Data):
895         a=self.getEvaluatedArguments(argval)        return arg._log10()
896         return a[0]*a[1]     elif isinstance(arg,float):
897     def _diff(self,arg):        return math.log10(arg)
898         a=self.getDifferentiatedArguments(arg)     elif isinstance(arg,int):
899         return self.getArgument(1)*a[0]+self.getArgument(0)*a[1]        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  class Div_Symbol(Symbol):  def wherePositive(arg):
906     """symbol representing the quotient of two arguments"""     """
907     def __init__(self,arg0,arg1):     returns mask of positive values of argument arg
        a=[arg0,arg1]  
        Symbol.__init__(self,dim=_extractDim(a),shape=_extractShape(a),args=a)  
    def __str__(self):  
       return "(%s/%s)"%(str(self.getArgument(0)),str(self.getArgument(1)))  
    def eval(self,argval):  
        a=self.getEvaluatedArguments(argval)  
        return a[0]/a[1]  
    def _diff(self,arg):  
        a=self.getDifferentiatedArguments(arg)  
        return (a[0]*self.getArgument(1)-self.getArgument(0)*a[1])/ \  
                           (self.getArgument(1)*self.getArgument(1))  
908    
909  class Power_Symbol(Symbol):     @param arg: argument
910     """symbol representing the power of the first argument to the power of the second argument"""     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
911     def __init__(self,arg0,arg1):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
912         a=[arg0,arg1]     @raises TypeError: if the type of the argument is not expected.
913         Symbol.__init__(self,dim=_extractDim(a),shape=_extractShape(a),args=a)     """
914     def __str__(self):     if isinstance(arg,numarray.NumArray):
915        return "(%s**%s)"%(str(self.getArgument(0)),str(self.getArgument(1)))        out=numarray.greater(arg,numarray.zeros(arg.shape,numarray.Float))
916     def eval(self,argval):        if isinstance(out,float): out=numarray.array(out)
917         a=self.getEvaluatedArguments(argval)        return out
918         return a[0]**a[1]     elif isinstance(arg,escript.Data):
919     def _diff(self,arg):        return arg._wherePositive()
920         a=self.getDifferentiatedArguments(arg)     elif isinstance(arg,float):
921         return self*(a[1]*log(self.getArgument(0))+self.getArgument(1)/self.getArgument(0)*a[0])        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 Abs_Symbol(Symbol):  class WherePositive_Symbol(DependendSymbol):
936     """symbol representing absolute value of its argument"""     """
937       L{Symbol} representing the result of the mask of positive values function
938       """
939     def __init__(self,arg):     def __init__(self,arg):
940         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
941     def __str__(self):        initialization of wherePositive L{Symbol} with argument arg
942        return "abs(%s)"%str(self.getArgument(0))        @param arg: argument of function
943     def eval(self,argval):        @type arg: typically L{Symbol}.
944         return abs(self.getEvaluatedArguments(argval)[0])        """
945     def _diff(self,arg):        DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
946         return sign(self.getArgument(0))*self.getDifferentiatedArguments(arg)[0]  
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  #   some little helpers        """
968  #=========================================================        assigns new values to symbols in the definition of the symbol.
969  def _testForZero(arg):        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
970     """returns True is arg is considered of being zero"""  
971     if isinstance(arg,int):        @param argvals: new values assigned to symbols
972        return not arg>0        @type argvals: C{dict} with keywords of type L{Symbol}.
973     elif isinstance(arg,float):        @return: result of the substitution process. Operations are executed as much as possible.
974        return not arg>0.        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
975     elif isinstance(arg,numarray.NumArray):        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
976        a=abs(arg)        """
977        while isinstance(a,numarray.NumArray): a=numarray.sometrue(a)        if argvals.has_key(self):
978        return not a>0           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))
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:     else:
1015        return False        raise TypeError,"whereNegative: Unknown argument type."
1016    
1017  def _extractDim(args):  class WhereNegative_Symbol(DependendSymbol):
1018      dim=None     """
1019      for a in args:     L{Symbol} representing the result of the mask of positive values function
1020         if hasattr(a,"getDim"):     """
1021            d=a.getDim()     def __init__(self,arg):
1022            if dim==None:        """
1023               dim=d        initialization of whereNegative L{Symbol} with argument arg
1024            else:        @param arg: argument of function
1025               if dim!=d: raise ValueError,"inconsistent spatial dimension of arguments"        @type arg: typically L{Symbol}.
1026      if dim==None:        """
1027         raise ValueError,"cannot recover spatial dimension"        DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1028      return dim  
1029       def getMyCode(self,argstrs,format="escript"):
1030  def _identifyShape(arg):        """
1031     """identifies the shape of arg."""        returns a program code that can be used to evaluate the symbol.
1032     if hasattr(arg,"getShape"):  
1033         arg_shape=arg.getShape()        @param argstrs: gives for each argument a string representing the argument for the evaluation.
1034     elif hasattr(arg,"shape"):        @type argstrs: C{str} or a C{list} of length 1 of C{str}.
1035       s=arg.shape        @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
1036       if callable(s):        @type format: C{str}
1037         arg_shape=s()        @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
1038       else:        @rtype: C{str}
1039         arg_shape=s        @raise: NotImplementedError: if the requested format is not available
1040     else:        """
1041         arg_shape=()        if isinstance(argstrs,list):
1042     return arg_shape            argstrs=argstrs[0]
1043          if format=="escript" or format=="str"  or format=="text":
1044  def _extractShape(args):           return "whereNegative(%s)"%argstrs
1045      """extracts the common shape of the list of arguments args"""        else:
1046      shape=None           raise NotImplementedError,"WhereNegative_Symbol does not provide program code for format %s."%format
     for a in args:  
        a_shape=_identifyShape(a)  
        if shape==None: shape=a_shape  
        if shape!=a_shape: raise ValueError,"inconsistent shape"  
     if shape==None:  
        raise ValueError,"cannot recover shape"  
     return shape  
   
 def _matchShape(args,shape=None):  
     """returns the list of arguments args as object which have all the specified shape.  
        if shape is not given the shape "largest" shape of args is used."""  
     # identify the list of shapes:  
     arg_shapes=[]  
     for a in args: arg_shapes.append(_identifyShape(a))  
     # get the largest shape (currently the longest shape):  
     if shape==None: shape=max(arg_shapes)  
       
     out=[]  
     for i in range(len(args)):  
        if shape==arg_shapes[i]:  
           out.append(args[i])  
        else:  
           if len(shape)==0: # then len(arg_shapes[i])>0  
             raise ValueError,"cannot adopt shape of %s to %s"%(str(args[i]),str(shape))  
           else:  
             if len(arg_shapes[i])==0:  
                 out.append(outer(args[i],numarray.ones(shape)))          
             else:    
                 raise ValueError,"cannot adopt shape of %s to %s"%(str(args[i]),str(shape))  
     return out    
1047    
1048  #=========================================================     def substitute(self,argvals):
1049  #   wrappers for various mathematical functions:        """
1050  #=========================================================        assigns new values to symbols in the definition of the symbol.
1051  def diff(arg,dep):        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1052      """returns the derivative of arg with respect to dep. If arg is not Symbol object  
1053         0 is returned"""        @param argvals: new values assigned to symbols
1054      if isinstance(arg,Symbol):        @type argvals: C{dict} with keywords of type L{Symbol}.
1055         return arg.diff(dep)        @return: result of the substitution process. Operations are executed as much as possible.
1056      elif hasattr(arg,"shape"):        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1057            if callable(arg.shape):        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1058                return numarray.zeros(arg.shape(),numarray.Float)        """
1059            else:        if argvals.has_key(self):
1060                return numarray.zeros(arg.shape,numarray.Float)           arg=argvals[self]
1061      else:           if self.isAppropriateValue(arg):
1062         return 0              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 exp(arg):  def whereNonNegative(arg):
1070      """     """
1071      @brief applies the exponential function to arg     returns mask of non-negative values of argument arg
     @param arg (input): argument  
     """  
     if isinstance(arg,Symbol):  
        return Exp_Symbol(arg)  
     elif hasattr(arg,"exp"):  
        return arg.exp()  
     else:  
        return numarray.exp(arg)  
1072    
1073  class Exp_Symbol(Symbol):     @param arg: argument
1074     """symbol representing the power of the first argument to the power of the second argument"""     @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))
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):     def __init__(self,arg):
1274         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
1275     def __str__(self):        initialization of sin L{Symbol} with argument arg
1276        return "exp(%s)"%str(self.getArgument(0))        @param arg: argument of function
1277     def eval(self,argval):        @type arg: typically L{Symbol}.
1278         return exp(self.getEvaluatedArguments(argval)[0])        """
1279     def _diff(self,arg):        DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1280         return self*self.getDifferentiatedArguments(arg)[0]  
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 sqrt(arg):     def substitute(self,argvals):
1301      """        """
1302      @brief applies the squre root function to arg        assigns new values to symbols in the definition of the symbol.
1303      @param arg (input): argument        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1304      """  
1305      if isinstance(arg,Symbol):        @param argvals: new values assigned to symbols
1306         return Sqrt_Symbol(arg)        @type argvals: C{dict} with keywords of type L{Symbol}.
1307      elif hasattr(arg,"sqrt"):        @return: result of the substitution process. Operations are executed as much as possible.
1308         return arg.sqrt()        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1309      else:        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1310         return numarray.sqrt(arg)              """
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  class Sqrt_Symbol(Symbol):     @param arg: argument
1342     """symbol representing square root of argument"""     @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):     def __init__(self,arg):
1364         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
1365     def __str__(self):        initialization of cos L{Symbol} with argument arg
1366        return "sqrt(%s)"%str(self.getArgument(0))        @param arg: argument of function
1367     def eval(self,argval):        @type arg: typically L{Symbol}.
1368         return sqrt(self.getEvaluatedArguments(argval)[0])        """
1369     def _diff(self,arg):        DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1370         return (-0.5)/self*self.getDifferentiatedArguments(arg)[0]  
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 log(arg):     def substitute(self,argvals):
1391      """        """
1392      @brief applies the logarithmic function bases exp(1.) to arg        assigns new values to symbols in the definition of the symbol.
1393      @param arg (input): argument        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1394      """  
1395      if isinstance(arg,Symbol):        @param argvals: new values assigned to symbols
1396         return Log_Symbol(arg)        @type argvals: C{dict} with keywords of type L{Symbol}.
1397      elif hasattr(arg,"log"):        @return: result of the substitution process. Operations are executed as much as possible.
1398         return arg.log()        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1399      else:        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1400         return numarray.log(arg)        """
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  class Log_Symbol(Symbol):        @param arg: the derivative is calculated with respect to arg
1416     """symbol representing logarithm of the argument"""        @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):     def __init__(self,arg):
1454         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
1455     def __str__(self):        initialization of tan L{Symbol} with argument arg
1456        return "log(%s)"%str(self.getArgument(0))        @param arg: argument of function
1457     def eval(self,argval):        @type arg: typically L{Symbol}.
1458         return log(self.getEvaluatedArguments(argval)[0])        """
1459     def _diff(self,arg):        DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1460         return self.getDifferentiatedArguments(arg)[0]/self.getArgument(0)  
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 ln(arg):     def substitute(self,argvals):
1481      """        """
1482      @brief applies the natural logarithmic function to arg        assigns new values to symbols in the definition of the symbol.
1483      @param arg (input): argument        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1484      """  
1485      if isinstance(arg,Symbol):        @param argvals: new values assigned to symbols
1486         return Ln_Symbol(arg)        @type argvals: C{dict} with keywords of type L{Symbol}.
1487      elif hasattr(arg,"ln"):        @return: result of the substitution process. Operations are executed as much as possible.
1488         return arg.log()        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1489      else:        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1490         return numarray.log(arg)        """
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  class Ln_Symbol(Symbol):        @param arg: the derivative is calculated with respect to arg
1506     """symbol representing natural logarithm of the argument"""        @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):     def __init__(self,arg):
1544         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
1545     def __str__(self):        initialization of asin L{Symbol} with argument arg
1546        return "ln(%s)"%str(self.getArgument(0))        @param arg: argument of function
1547     def eval(self,argval):        @type arg: typically L{Symbol}.
1548         return ln(self.getEvaluatedArguments(argval)[0])        """
1549     def _diff(self,arg):        DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1550         return self.getDifferentiatedArguments(arg)[0]/self.getArgument(0)  
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 sin(arg):     def substitute(self,argvals):
1571      """        """
1572      @brief applies the sin function to arg        assigns new values to symbols in the definition of the symbol.
1573      @param arg (input): argument        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1574      """  
1575      if isinstance(arg,Symbol):        @param argvals: new values assigned to symbols
1576         return Sin_Symbol(arg)        @type argvals: C{dict} with keywords of type L{Symbol}.
1577      elif hasattr(arg,"sin"):        @return: result of the substitution process. Operations are executed as much as possible.
1578         return arg.sin()        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1579      else:        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1580         return numarray.sin(arg)        """
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  class Sin_Symbol(Symbol):     def diff(self,arg):
1592     """symbol representing sin of the argument"""        """
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):     def __init__(self,arg):
1634         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
1635     def __str__(self):        initialization of acos L{Symbol} with argument arg
1636        return "sin(%s)"%str(self.getArgument(0))        @param arg: argument of function
1637     def eval(self,argval):        @type arg: typically L{Symbol}.
1638         return sin(self.getEvaluatedArguments(argval)[0])        """
1639     def _diff(self,arg):        DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1640         return cos(self.getArgument(0))*self.getDifferentiatedArguments(arg)[0]  
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 cos(arg):     def substitute(self,argvals):
1661      """        """
1662      @brief applies the cos function to arg        assigns new values to symbols in the definition of the symbol.
1663      @param arg (input): argument        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1664      """  
1665      if isinstance(arg,Symbol):        @param argvals: new values assigned to symbols
1666         return Cos_Symbol(arg)        @type argvals: C{dict} with keywords of type L{Symbol}.
1667      elif hasattr(arg,"cos"):        @return: result of the substitution process. Operations are executed as much as possible.
1668         return arg.cos()        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1669      else:        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1670         return numarray.cos(arg)        """
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  class Cos_Symbol(Symbol):     def diff(self,arg):
1682     """symbol representing cos of the argument"""        """
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):     def __init__(self,arg):
1724         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
1725     def __str__(self):        initialization of atan L{Symbol} with argument arg
1726        return "cos(%s)"%str(self.getArgument(0))        @param arg: argument of function
1727     def eval(self,argval):        @type arg: typically L{Symbol}.
1728         return cos(self.getEvaluatedArguments(argval)[0])        """
1729     def _diff(self,arg):        DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1730         return -sin(self.getArgument(0))*self.getDifferentiatedArguments(arg)[0]  
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 tan(arg):     def substitute(self,argvals):
1751      """        """
1752      @brief applies the tan function to arg        assigns new values to symbols in the definition of the symbol.
1753      @param arg (input): argument        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1754      """  
1755      if isinstance(arg,Symbol):        @param argvals: new values assigned to symbols
1756         return Tan_Symbol(arg)        @type argvals: C{dict} with keywords of type L{Symbol}.
1757      elif hasattr(arg,"tan"):        @return: result of the substitution process. Operations are executed as much as possible.
1758         return arg.tan()        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1759      else:        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1760         return numarray.tan(arg)        """
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 Tan_Symbol(Symbol):  class Sinh_Symbol(DependendSymbol):
1810     """symbol representing tan of the argument"""     """
1811       L{Symbol} representing the result of the hyperbolic sine function
1812       """
1813     def __init__(self,arg):     def __init__(self,arg):
1814         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
1815     def __str__(self):        initialization of sinh L{Symbol} with argument arg
1816        return "tan(%s)"%str(self.getArgument(0))        @param arg: argument of function
1817     def eval(self,argval):        @type arg: typically L{Symbol}.
1818         return tan(self.getEvaluatedArguments(argval)[0])        """
1819     def _diff(self,arg):        DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1820         s=cos(self.getArgument(0))  
1821         return 1./(s*s)*self.getDifferentiatedArguments(arg)[0]     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 sign(arg):     def substitute(self,argvals):
1841      """        """
1842      @brief applies the sign function to arg        assigns new values to symbols in the definition of the symbol.
1843      @param arg (input): argument        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1844      """  
1845      if isinstance(arg,Symbol):        @param argvals: new values assigned to symbols
1846         return Sign_Symbol(arg)        @type argvals: C{dict} with keywords of type L{Symbol}.
1847      elif hasattr(arg,"sign"):        @return: result of the substitution process. Operations are executed as much as possible.
1848         return arg.sign()        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1849      else:        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1850         return numarray.greater(arg,numarray.zeros(arg.shape,numarray.Float))- \        """
1851                numarray.less(arg,numarray.zeros(arg.shape,numarray.Float))        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  class Sign_Symbol(Symbol):        @param arg: the derivative is calculated with respect to arg
1866     """symbol representing the sign of the argument"""        @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):     def __init__(self,arg):
1904         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
1905     def __str__(self):        initialization of cosh L{Symbol} with argument arg
1906        return "sign(%s)"%str(self.getArgument(0))        @param arg: argument of function
1907     def eval(self,argval):        @type arg: typically L{Symbol}.
1908         return sign(self.getEvaluatedArguments(argval)[0])        """
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 maxval(arg):     def substitute(self,argvals):
1931      """        """
1932      @brief returns the maximum value of argument arg""        assigns new values to symbols in the definition of the symbol.
1933      @param arg (input): argument        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1934      """  
1935      if isinstance(arg,Symbol):        @param argvals: new values assigned to symbols
1936         return Max_Symbol(arg)        @type argvals: C{dict} with keywords of type L{Symbol}.
1937      elif hasattr(arg,"maxval"):        @return: result of the substitution process. Operations are executed as much as possible.
1938         return arg.maxval()        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
1939      elif hasattr(arg,"max"):        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
1940         return arg.max()        """
1941      else:        if argvals.has_key(self):
1942         return arg           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 Max_Symbol(Symbol):  class Tanh_Symbol(DependendSymbol):
1990     """symbol representing the maximum value of the argument"""     """
1991       L{Symbol} representing the result of the hyperbolic tangent function
1992       """
1993     def __init__(self,arg):     def __init__(self,arg):
1994         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
1995     def __str__(self):        initialization of tanh L{Symbol} with argument arg
1996        return "maxval(%s)"%str(self.getArgument(0))        @param arg: argument of function
1997     def eval(self,argval):        @type arg: typically L{Symbol}.
1998         return maxval(self.getEvaluatedArguments(argval)[0])        """
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):  def minval(arg):
2698      """     """
2699      @brief returns the minimum value of argument arg""     returns minimum value over all components of arg at each data point
2700      @param arg (input): argument  
2701      """     @param arg: argument
2702      if isinstance(arg,Symbol):     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2703         return Min_Symbol(arg)     @rtype:C{float}, L{escript.Data}, L{Symbol} depending on the type of arg.
2704      elif hasattr(arg,"maxval"):     @raises TypeError: if the type of the argument is not expected.
2705         return arg.minval()     """
2706      elif hasattr(arg,"min"):     if isinstance(arg,numarray.NumArray):
2707         return arg.min()        if arg.rank==0:
2708      else:           return float(arg)
2709         return arg        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 Min_Symbol(Symbol):  class Minval_Symbol(DependendSymbol):
2723     """symbol representing the minimum value of the argument"""     """
2724       L{Symbol} representing the result of the minimum value function
2725       """
2726     def __init__(self,arg):     def __init__(self,arg):
2727         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
2728     def __str__(self):        initialization of minimum value L{Symbol} with argument arg
2729        return "minval(%s)"%str(self.getArgument(0))        @param arg: argument of function
2730     def eval(self,argval):        @type arg: typically L{Symbol}.
2731         return minval(self.getEvaluatedArguments(argval)[0])        """
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 wherePositive(arg):     def substitute(self,argvals):
2754      """        """
2755      @brief returns the positive values of argument arg""        assigns new values to symbols in the definition of the symbol.
2756      @param arg (input): argument        The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2757      """  
2758      if _testForZero(arg):        @param argvals: new values assigned to symbols
2759        return 0        @type argvals: C{dict} with keywords of type L{Symbol}.
2760      elif isinstance(arg,Symbol):        @return: result of the substitution process. Operations are executed as much as possible.
2761         return WherePositive_Symbol(arg)        @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution
2762      elif hasattr(arg,"wherePositive"):        @raise TypeError: if a value for a L{Symbol} cannot be substituted.
2763         return arg.minval()        """
2764      elif hasattr(arg,"wherePositive"):        if argvals.has_key(self):
2765         numarray.greater(arg,numarray.zeros(arg.shape,numarray.Float))           arg=argvals[self]
2766      else:           if self.isAppropriateValue(arg):
2767         if arg>0:              return arg
2768            return 1.           else:
2769         else:              raise TypeError,"%s: new value is not appropriate."%str(self)
2770            return 0.        else:
2771             arg=self.getSubstitutedArguments(argvals)[0]
2772             return minval(arg)
2773    
2774    def maxval(arg):
2775       """
2776       returns maximum value over all components of arg at each data point
2777    
2778  class WherePositive_Symbol(Symbol):     @param arg: argument
2779     """symbol representing the wherePositive function"""     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2780       @rtype:C{float}, L{escript.Data}, L{Symbol} depending on the type of arg.
2781       @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):     def __init__(self,arg):
2804         Symbol.__init__(self,shape=arg.getShape(),dim=arg.getDim(),args=[arg])        """
2805     def __str__(self):        initialization of maximum value L{Symbol} with argument arg
2806        return "wherePositive(%s)"%str(self.getArgument(0))        @param arg: argument of function
2807     def eval(self,argval):        @type arg: typically L{Symbol}.
2808         return wherePositive(self.getEvaluatedArguments(argval)[0])        """
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 whereNegative(arg):     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