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