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