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

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

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

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