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