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

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

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

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