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

Diff of /trunk-mpi-branch/escript/py_src/util.py

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

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