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