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

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

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

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