/[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 150 by jgs, Thu Sep 15 03:44:45 2005 UTC trunk/escript/py_src/util.py revision 550 by gross, Wed Feb 22 02:14:38 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
 import symbols  
35  import os  import os
36    
37  #=========================================================  # missing tests:
38  #   some little helpers  
39  #=========================================================  # def pokeShape(arg):
40  def _testForZero(arg):  # def pokeDim(arg):
41     """  # def commonShape(arg0,arg1):
42     Returns True is arg is considered to be zero.  # def commonDim(*args):
43     """  # def testForZero(arg):
44     if isinstance(arg,int):  # def matchType(arg0=0.,arg1=0.):
45        return not arg>0  # def matchShape(arg0,arg1):
46     elif isinstance(arg,float):  
47        return not arg>0.  # def reorderComponents(arg,index):
48     elif isinstance(arg,numarray.NumArray):  
49        a=abs(arg)  #
50        while isinstance(a,numarray.NumArray): a=numarray.sometrue(a)  # slicing: get
51        return not a>0  #          set
52     else:  #
53        return False  # and derivatives
54    
55  #=========================================================  #=========================================================
56  def saveVTK(filename,**data):  #   some helpers:
57    #=========================================================
58    def saveVTK(filename,domain=None,**data):
59      """      """
60      writes arg into files in the vtk file format      writes a L{Data} objects into a files using the the VTK XML file format.
61    
62             saveVTK(<filename>,<data name 1>=<data object 1>,...,<data name n>=<data object n>)        Example:
63    
64        This will create VTK files of the name <dir name>+<data name i>+"."+<extension> where <filename>=<dir name>+<extension>         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      ex=os.path.split(filename)      writes a L{Data} objects into a files using the the DX file format.
     for i in data.keys():  
        data[i].saveVTK(os.path.join(ex[0],i+"."+ex[1]))  
89    
90  #=========================================================      Example:
 def saveDX(filename,**data):  
     """  
     writes arg into file in the openDX file format  
91    
92             saveDX(<filename>,<data name 1>=<data object 1>,...,<data name n>=<data object n>)           tmp=Scalar(..)
93           v=Vector(..)
94           saveDX("solution.dx",temperature=tmp,velovity=v)
95    
96        This will create DX files of the name <dir name>+<data name i>+"."+<extension> where <filename>=<dir name>+<extension>      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      ex=os.path.split(filename)      if domain==None:
107      for i in data.keys():         for i in data.keys():
108         data[i].saveDX(os.path.join(ex[0],i+"."+ex[1]))            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  def exp(arg):     @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.Float)
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       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       return the dxdxdxd identity tensor
169    
170       @param d: dimension or an object that has the C{getDim} method defining the dimension
171       @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       @rtype d: L{numarray.NumArray} or L{escript.Data} of rank 4.
174       """
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      Applies the exponential function to arg.      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      @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,symbols.Symbol):      if isinstance(arg,numarray.NumArray):
210         return symbols.Exp_Symbol(arg)          return sup(abs(arg))
211      elif hasattr(arg,"exp"):      elif isinstance(arg,escript.Data):
212         return arg.exp()          return arg._Lsup()
213        elif isinstance(arg,float):
214            return abs(arg)
215        elif isinstance(arg,int):
216            return abs(float(arg))
217      else:      else:
218         return numarray.exp(arg)        raise TypeError,"Lsup: Unknown argument type."
219    
220  def sqrt(arg):  def sup(arg):
221      """      """
222      Applies the squre root function to arg.      returns the maximum value over all data points.
223    
224      @param arg: argument      @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,symbols.Symbol):      if isinstance(arg,numarray.NumArray):
231         return symbols.Sqrt_Symbol(arg)          return arg.max()
232      elif hasattr(arg,"sqrt"):      elif isinstance(arg,escript.Data):
233         return arg.sqrt()          return arg._sup()
234        elif isinstance(arg,float):
235            return arg
236        elif isinstance(arg,int):
237            return float(arg)
238      else:      else:
239         return numarray.sqrt(arg)              raise TypeError,"sup: Unknown argument type."
240    
241  def log(arg):  def inf(arg):
242      """      """
243      Applies the logarithmic function bases exp(1.) to arg      returns the maximum value over all data points.
244    
245      @param arg: argument      @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,symbols.Symbol):      if isinstance(arg,numarray.NumArray):
252         return symbols.Log_Symbol(arg)          return arg.min()
253      elif hasattr(arg,"log"):      elif isinstance(arg,escript.Data):
254         return arg.log()          return arg._inf()
255        elif isinstance(arg,float):
256            return arg
257        elif isinstance(arg,int):
258            return float(arg)
259      else:      else:
260         return numarray.log(arg)        raise TypeError,"inf: Unknown argument type."
261    
262  def ln(arg):  
263    #=========================================================================
264    #   some little helpers
265    #=========================================================================
266    def pokeShape(arg):
267      """      """
268      Applies the natural logarithmic function to arg.      identifies the shape of its argument
269    
270      @param arg: argument      @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      if isinstance(arg,symbols.Symbol):  
277         return symbols.Ln_Symbol(arg)      if isinstance(arg,numarray.NumArray):
278      elif hasattr(arg,"ln"):          return arg.shape
279         return arg.log()      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:      else:
288         return numarray.log(arg)        raise TypeError,"pokeShape: cannot identify shape"
289    
290  def sin(arg):  def pokeDim(arg):
291      """      """
292      Applies the sin function to arg.      identifies the spatial dimension of its argument
293    
294      @param arg: argument      @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      if isinstance(arg,symbols.Symbol):  
300         return symbols.Sin_Symbol(arg)      if isinstance(arg,escript.Data):
301      elif hasattr(arg,"sin"):          return arg.getFunctionSpace().getDim()
302         return arg.sin()      elif isinstance(arg,Symbol):
303            return arg.getDim()
304      else:      else:
305         return numarray.sin(arg)          return None
306    
307  def cos(arg):  def commonShape(arg0,arg1):
308      """      """
309      Applies the cos function to arg.      returns a shape to which arg0 can be extendent from the right and arg1 can be extended from the left.
310    
311      @param arg: argument      @param arg0: an object with a shape (see L{pokeShape})
312      """      @param arg1: an object with a shape (see L{pokeShape})
313      if isinstance(arg,symbols.Symbol):      @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         return symbols.Cos_Symbol(arg)      @rtype: C{tuple} of C{int}
315      elif hasattr(arg,"cos"):      @raise ValueError: if no shape can be found.
316         return arg.cos()      """
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:      else:
328         return numarray.cos(arg)         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 tan(arg):  def testForZero(arg):
353      """      """
354      Applies the tan function to arg.      test the argument for being identical to Zero
355    
356      @param arg: argument      @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,symbols.Symbol):      if isinstance(arg,numarray.NumArray):
362         return symbols.Tan_Symbol(arg)         return not Lsup(arg)>0.
363      elif hasattr(arg,"tan"):      elif isinstance(arg,escript.Data):
364         return arg.tan()         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:      else:
372         return numarray.tan(arg)         return False
373    
374  def asin(arg):  def matchType(arg0=0.,arg1=0.):
375      """      """
376      Applies the asin function to arg.      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 arg: argument      @param arg0: first argument
379      """      @type arg0: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, C{Symbol}
380      if isinstance(arg,symbols.Symbol):      @param arg1: second argument
381         return symbols.Asin_Symbol(arg)      @type arg1: L{numarray.NumArray},L{escript.Data},C{float}, C{int}, C{Symbol}
382      elif hasattr(arg,"asin"):      @return: a tuple representing arg0 and arg1 with the same type or with one of them being a L{Symbol}
383         return arg.asin()      @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)
393           elif isinstance(arg1,int):
394              arg1=numarray.array(float(arg1))
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)
419           elif isinstance(arg1,int):
420              arg1=numarray.array(float(arg1))
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)
428           elif isinstance(arg1,escript.Data):
429              arg0=escript.Data(arg0,arg1.getFunctionSpace())
430           elif isinstance(arg1,float):
431              arg0=numarray.array(arg0)
432              arg1=numarray.array(arg1)
433           elif isinstance(arg1,int):
434              arg0=numarray.array(arg0)
435              arg1=numarray.array(float(arg1))
436           elif isinstance(arg1,Symbol):
437              arg0=numarray.array(arg0)
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))
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))
447              arg1=numarray.array(arg1)
448           elif isinstance(arg1,int):
449              arg0=numarray.array(float(arg0))
450              arg1=numarray.array(float(arg1))
451           elif isinstance(arg1,Symbol):
452              arg0=numarray.array(float(arg0))
453           else:
454              raise TypeError,"function: Unknown type of second argument."    
455      else:      else:
456         return numarray.asin(arg)        raise TypeError,"function: Unknown type of first argument."    
457    
458  def acos(arg):      return arg0,arg1
     """  
     Applies the acos function to arg.  
459    
460      @param arg: argument  def matchShape(arg0,arg1):
461      """      """
462      if isinstance(arg,symbols.Symbol):      
463         return symbols.Acos_Symbol(arg)  
464      elif hasattr(arg,"acos"):      If shape is not given the shape "largest" shape of args is used.
465         return arg.acos()  
466      else:      @param args: a given ob
467         return numarray.acos(arg)      @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.Float)),arg1
476        elif len(sh1)<len(sh):
477           return arg0,outer(arg1,numarray.ones(sh[len(sh1):],numarray.Float))
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
508           self.__shape=shape
509           self.__dim=dim
510    
511       def getArgument(self,i=None):
512           """
513           returns the i-th argument of the symbol
514    
515           @param i: index of the argument requested.
516           @type i: C{int} or C{None}
517           @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           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):
529           """
530           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())
536    
537       def getShape(self):
538           """
539           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
545    
546       def getDim(self):
547           """
548           the spatial dimension
549    
550           @return : the spatial dimension
551           @rtype: C{int} if the dimension is defined. Otherwise C{None} is returned.
552           """
553           return self.__dim
554      
555       def __str__(self):
556           """
557           a string representation of the symbol.
558           @return: a string representation of the object
559           @rtype: C{str}
560           """
561           args=[]
562           for arg in self.getArgument():
563              args.append(str(arg))
564           try:
565               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):
588           """
589           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=[]
597           for a in self.getArgument():
598              if isinstance(a,Symbol):
599                 out.append(a.substitute(argvals))
600              else:
601                  s=pokeShape(s)+arg.getShape()
602                  if len(s)>0:
603                     out.append(numarray.zeros(s),numarray.Float)
604                  else:
605                     out.append(a)
606           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):
679           """
680           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 arg==self:
689              return identity(self.getShape())
690           else:
691              s=self.getShape()+arg.getShape()
692              if len(s)>0:
693                 return numarray.zeros(s,numarray.Float)
694              else:
695                 return 0.
696    
697       def __neg__(self):
698           """
699           returns -self.
700    
701           @return:  a S{Symbol} representing the negative of the object
702           @rtype: L{DependendSymbol}
703           """
704           return self*(-1.)
705    
706       def __pos__(self):
707           """
708           returns +self.
709    
710           @return:  a S{Symbol} representing the positive of the object
711           @rtype: L{DependendSymbol}
712           """
713           return self*(1.)
714    
715       def __abs__(self):
716           """
717           returns a S{Symbol} representing the absolute value of the object.
718           """
719           return Abs_Symbol(self)
720    
721       def __add__(self,other):
722           """
723           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           return add(self,other)
731    
732       def __radd__(self,other):
733           """
734           add this object to another object
735    
736           @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           return add(other,self)
742    
743       def __sub__(self,other):
744           """
745           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 add(self,-other)
753    
754       def __rsub__(self,other):
755           """
756           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 add(-self,other)
764    
765       def __mul__(self,other):
766           """
767           multiplies this object with other object
768    
769           @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           return mult(self,other)
775    
776       def __rmul__(self,other):
777           """
778           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 mult(other,self)
786    
787       def __div__(self,other):
788           """
789           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           return quotient(self,other)
797    
798       def __rdiv__(self,other):
799           """
800           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           return quotient(other,self)
808    
809       def __pow__(self,other):
810           """
811           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           return power(self,other)
819    
820       def __rpow__(self,other):
821           """
822           raises an object to the power of this object
823    
824           @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           return power(other,self)
830    
831       def __getitem__(self,index):
832           """
833           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 GetSlice_Symbol(self,index)
841    
842    class DependendSymbol(Symbol):
843       """
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       u1=DependendSymbol(shape=(3,4),dim=2,args=[4.])
857       u2=DependendSymbol(shape=(3,4),dim=2,args=[4.])
858       u3=DependendSymbol(shape=(2,),dim=2,args=[4.])  
859       print u1==u2, u1==u3
860       True False
861    
862       @note: DependendSymbol should be used as return value of functions with L{Symbol} arguments. This will allow the optimizer to remove redundant function calls.
863       """
864       def __eq__(self,other):
865          """
866          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 isinstance(other,DependendSymbol):
873             if self.__class__==other.__class__:  
874                if self.getShape()==other.getShape():
875                  if self.getArgument()==other.getArgument():
876                     if self.getDim()==None or other.getDim()==None or self.getDim()==other.getDim():
877                        return True
878          return False
879    
880       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       L{Symbol} representing getting a slice for a L{Symbol}
895       """
896       def __init__(self,arg,index):
897          """
898          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 not isinstance(index,tuple): index=(index,)
907          if len(index)>arg.getRank():
908               raise IndexError,"GetSlice_Symbol: index out of range."
909          sh=()
910          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       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       returns mask of positive values of argument arg
1005    
1006       @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.Float))*1.
1013          if isinstance(out,float): out=numarray.array(out)
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          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 argvals.has_key(self):
1075             arg=argvals[self]
1076             if self.isAppropriateValue(arg):
1077                return arg
1078             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    def whereNegative(arg):
1085       """
1086       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.Float))*1.
1095          if isinstance(out,float): out=numarray.array(out)
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,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          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          assigns new values to symbols in the definition of the symbol.
1148          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
1149    
1150          @param argvals: new values assigned to symbols
1151          @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.Float))*1.
1177          if isinstance(out,float): out=numarray.array(out)
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.Float))*1.
1207          if isinstance(out,float): out=numarray.array(out)
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.Float))*1.
1239          if isinstance(out,float): out=numarray.array(out)
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 WhereZero_Symbol(DependendSymbol):
1262       """
1263       L{Symbol} representing the result of the mask of zero entries function
1264       """
1265       def __init__(self,arg,tol=0.):
1266          """
1267          initialization of whereZero L{Symbol} with argument arg
1268          @param arg: argument of function
1269          @type arg: typically L{Symbol}.
1270          """
1271          DependendSymbol.__init__(self,args=[arg,tol],shape=arg.getShape(),dim=arg.getDim())
1272    
1273       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          @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       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.Float))*1.
1322          if isinstance(out,float): out=numarray.array(out)
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       returns sine of argument arg
1347    
1348       @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       L{Symbol} representing the result of the sine function
1369       """
1370       def __init__(self,arg):
1371          """
1372          initialization of sin L{Symbol} with argument arg
1373          @param arg: argument of function
1374          @type arg: typically L{Symbol}.
1375          """
1376          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1377    
1378       def getMyCode(self,argstrs,format="escript"):
1379          """
1380          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    def cos(arg):
1435       """
1436       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       L{Symbol} representing the result of the cosine function
1459       """
1460       def __init__(self,arg):
1461          """
1462          initialization of cos L{Symbol} with argument arg
1463          @param arg: argument of function
1464          @type arg: typically L{Symbol}.
1465          """
1466          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1467    
1468       def getMyCode(self,argstrs,format="escript"):
1469          """
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          @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       L{Symbol} representing the result of the tangent function
1549       """
1550       def __init__(self,arg):
1551          """
1552          initialization of tan L{Symbol} with argument arg
1553          @param arg: argument of function
1554          @type arg: typically L{Symbol}.
1555          """
1556          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1557    
1558       def getMyCode(self,argstrs,format="escript"):
1559          """
1560          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          @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       L{Symbol} representing the result of the inverse sine function
1639       """
1640       def __init__(self,arg):
1641          """
1642          initialization of asin L{Symbol} with argument arg
1643          @param arg: argument of function
1644          @type arg: typically L{Symbol}.
1645          """
1646          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1647    
1648       def getMyCode(self,argstrs,format="escript"):
1649          """
1650          returns a program code that can be used to evaluate the symbol.
1651    
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       L{Symbol} representing the result of the inverse cosine function
1729       """
1730       def __init__(self,arg):
1731          """
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):  def atan(arg):
1795      """     """
1796      Applies the atan function to arg.     returns inverse tangent of argument arg
1797    
1798      @param arg: argument     @param arg: argument
1799      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1800      if isinstance(arg,symbols.Symbol):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1801         return symbols.Atan_Symbol(arg)     @raises TypeError: if the type of the argument is not expected.
1802      elif hasattr(arg,"atan"):     """
1803         return arg.atan()     if isinstance(arg,numarray.NumArray):
1804      else:        return numarray.arctan(arg)
1805         return numarray.atan(arg)     elif isinstance(arg,escript.Data):
1806          return arg._atan()
1807       elif isinstance(arg,float):
1808          return math.atan(arg)
1809       elif isinstance(arg,int):
1810          return math.atan(arg)
1811       elif isinstance(arg,Symbol):
1812          return Atan_Symbol(arg)
1813       else:
1814          raise TypeError,"atan: Unknown argument type."
1815    
1816    class Atan_Symbol(DependendSymbol):
1817       """
1818       L{Symbol} representing the result of the inverse tangent function
1819       """
1820       def __init__(self,arg):
1821          """
1822          initialization of atan L{Symbol} with argument arg
1823          @param arg: argument of function
1824          @type arg: typically L{Symbol}.
1825          """
1826          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1827    
1828       def getMyCode(self,argstrs,format="escript"):
1829          """
1830          returns a program code that can be used to evaluate the symbol.
1831    
1832          @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):  def sinh(arg):
1885      """     """
1886      Applies the sinh function to arg.     returns hyperbolic sine of argument arg
1887    
1888      @param arg: argument     @param arg: argument
1889      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1890      if isinstance(arg,symbols.Symbol):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1891         return symbols.Sinh_Symbol(arg)     @raises TypeError: if the type of the argument is not expected.
1892      elif hasattr(arg,"sinh"):     """
1893         return arg.sinh()     if isinstance(arg,numarray.NumArray):
1894      else:        return numarray.sinh(arg)
1895         return numarray.sinh(arg)     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       L{Symbol} representing the result of the hyperbolic sine function
1909       """
1910       def __init__(self,arg):
1911          """
1912          initialization of sinh L{Symbol} with argument arg
1913          @param arg: argument of function
1914          @type arg: typically L{Symbol}.
1915          """
1916          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1917    
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):  def cosh(arg):
1975      """     """
1976      Applies the cosh function to arg.     returns hyperbolic cosine of argument arg
1977    
1978      @param arg: argument     @param arg: argument
1979      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
1980      if isinstance(arg,symbols.Symbol):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
1981         return symbols.Cosh_Symbol(arg)     @raises TypeError: if the type of the argument is not expected.
1982      elif hasattr(arg,"cosh"):     """
1983         return arg.cosh()     if isinstance(arg,numarray.NumArray):
1984      else:        return numarray.cosh(arg)
1985         return numarray.cosh(arg)     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:
1994          raise TypeError,"cosh: Unknown argument type."
1995    
1996    class Cosh_Symbol(DependendSymbol):
1997       """
1998       L{Symbol} representing the result of the hyperbolic cosine function
1999       """
2000       def __init__(self,arg):
2001          """
2002          initialization of cosh L{Symbol} with argument arg
2003          @param arg: argument of function
2004          @type arg: typically L{Symbol}.
2005          """
2006          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2007    
2008       def getMyCode(self,argstrs,format="escript"):
2009          """
2010          returns a program code that can be used to evaluate the symbol.
2011    
2012          @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          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2015          @type format: C{str}
2016          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2017          @rtype: C{str}
2018          @raise: NotImplementedError: if the requested format is not available
2019          """
2020          if isinstance(argstrs,list):
2021              argstrs=argstrs[0]
2022          if format=="escript" or format=="str"  or format=="text":
2023             return "cosh(%s)"%argstrs
2024          else:
2025             raise NotImplementedError,"Cosh_Symbol does not provide program code for format %s."%format
2026    
2027       def substitute(self,argvals):
2028          """
2029          assigns new values to symbols in the definition of the symbol.
2030          The method replaces the L{Symbol} u by argvals[u] in the expression defining this object.
2031    
2032          @param argvals: new values assigned to symbols
2033          @type argvals: C{dict} with keywords of type L{Symbol}.
2034          @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       def diff(self,arg):
2049          """
2050          differential of this object
2051    
2052          @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):  def tanh(arg):
2065      """     """
2066      Applies the tanh function to arg.     returns hyperbolic tangent of argument arg
2067    
2068      @param arg: argument     @param arg: argument
2069      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2070      if isinstance(arg,symbols.Symbol):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2071         return symbols.Tanh_Symbol(arg)     @raises TypeError: if the type of the argument is not expected.
2072      elif hasattr(arg,"tanh"):     """
2073         return arg.tanh()     if isinstance(arg,numarray.NumArray):
2074      else:        return numarray.tanh(arg)
2075         return numarray.tanh(arg)     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       L{Symbol} representing the result of the hyperbolic tangent function
2089       """
2090       def __init__(self,arg):
2091          """
2092          initialization of tanh L{Symbol} with argument arg
2093          @param arg: argument of function
2094          @type arg: typically L{Symbol}.
2095          """
2096          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2097    
2098       def getMyCode(self,argstrs,format="escript"):
2099          """
2100          returns a program code that can be used to evaluate the symbol.
2101    
2102          @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          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2105          @type format: C{str}
2106          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2107          @rtype: C{str}
2108          @raise: NotImplementedError: if the requested format is not available
2109          """
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          @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):  def asinh(arg):
2155      """     """
2156      Applies the asinh function to arg.     returns inverse hyperbolic sine of argument arg
2157    
2158      @param arg: argument     @param arg: argument
2159      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2160      if isinstance(arg,symbols.Symbol):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2161         return symbols.Asinh_Symbol(arg)     @raises TypeError: if the type of the argument is not expected.
2162      elif hasattr(arg,"asinh"):     """
2163         return arg.asinh()     if isinstance(arg,numarray.NumArray):
2164      else:        return numarray.arcsinh(arg)
2165         return numarray.asinh(arg)     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       L{Symbol} representing the result of the inverse hyperbolic sine function
2179       """
2180       def __init__(self,arg):
2181          """
2182          initialization of asinh L{Symbol} with argument arg
2183          @param arg: argument of function
2184          @type arg: typically L{Symbol}.
2185          """
2186          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2187    
2188       def getMyCode(self,argstrs,format="escript"):
2189          """
2190          returns a program code that can be used to evaluate the symbol.
2191    
2192          @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          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2195          @type format: C{str}
2196          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2197          @rtype: C{str}
2198          @raise: NotImplementedError: if the requested format is not available
2199          """
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):  def acosh(arg):
2245      """     """
2246      Applies the acosh function to arg.     returns inverse hyperolic cosine of argument arg
2247    
2248      @param arg: argument     @param arg: argument
2249      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2250      if isinstance(arg,symbols.Symbol):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2251         return symbols.Acosh_Symbol(arg)     @raises TypeError: if the type of the argument is not expected.
2252      elif hasattr(arg,"acosh"):     """
2253         return arg.acosh()     if isinstance(arg,numarray.NumArray):
2254      else:        return numarray.arccosh(arg)
2255         return numarray.acosh(arg)     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 Acosh_Symbol(DependendSymbol):
2267       """
2268       L{Symbol} representing the result of the inverse hyperolic cosine function
2269       """
2270       def __init__(self,arg):
2271          """
2272          initialization of acosh L{Symbol} with argument arg
2273          @param arg: argument of function
2274          @type arg: typically L{Symbol}.
2275          """
2276          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2277    
2278       def getMyCode(self,argstrs,format="escript"):
2279          """
2280          returns a program code that can be used to evaluate the symbol.
2281    
2282          @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          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2285          @type format: C{str}
2286          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2287          @rtype: C{str}
2288          @raise: NotImplementedError: if the requested format is not available
2289          """
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):  def atanh(arg):
2335      """     """
2336      Applies the atanh function to arg.     returns inverse hyperbolic tangent of argument arg
2337    
2338      @param arg: argument     @param arg: argument
2339      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2340      if isinstance(arg,symbols.Symbol):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2341         return symbols.Atanh_Symbol(arg)     @raises TypeError: if the type of the argument is not expected.
2342      elif hasattr(arg,"atanh"):     """
2343         return arg.atanh()     if isinstance(arg,numarray.NumArray):
2344      else:        return numarray.arctanh(arg)
2345         return numarray.atanh(arg)     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 Atanh_Symbol(DependendSymbol):
2357       """
2358       L{Symbol} representing the result of the inverse hyperbolic tangent function
2359       """
2360       def __init__(self,arg):
2361          """
2362          initialization of atanh L{Symbol} with argument arg
2363          @param arg: argument of function
2364          @type arg: typically L{Symbol}.
2365          """
2366          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2367    
2368       def getMyCode(self,argstrs,format="escript"):
2369          """
2370          returns a program code that can be used to evaluate the symbol.
2371    
2372          @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          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2375          @type format: C{str}
2376          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2377          @rtype: C{str}
2378          @raise: NotImplementedError: if the requested format is not available
2379          """
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 Exp_Symbol(DependendSymbol):
2447       """
2448       L{Symbol} representing the result of the exponential function
2449       """
2450       def __init__(self,arg):
2451          """
2452          initialization of exp L{Symbol} with argument arg
2453          @param arg: argument of function
2454          @type arg: typically L{Symbol}.
2455          """
2456          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2457    
2458       def getMyCode(self,argstrs,format="escript"):
2459          """
2460          returns a program code that can be used to evaluate the symbol.
2461    
2462          @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          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2465          @type format: C{str}
2466          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2467          @rtype: C{str}
2468          @raise: NotImplementedError: if the requested format is not available
2469          """
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          @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       L{Symbol} representing the result of the square root function
2539       """
2540       def __init__(self,arg):
2541          """
2542          initialization of sqrt L{Symbol} with argument arg
2543          @param arg: argument of function
2544          @type arg: typically L{Symbol}.
2545          """
2546          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2547    
2548       def getMyCode(self,argstrs,format="escript"):
2549          """
2550          returns a program code that can be used to evaluate the symbol.
2551    
2552          @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          @param format: specifies the format to be used. At the moment only "escript" ,"text" and "str" are supported.
2555          @type format: C{str}
2556          @return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available.
2557          @rtype: C{str}
2558          @raise: NotImplementedError: if the requested format is not available
2559          """
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 Log_Symbol(DependendSymbol):
2627       """
2628       L{Symbol} representing the result of the natural logarithm function
2629       """
2630       def __init__(self,arg):
2631          """
2632          initialization of log L{Symbol} with argument arg
2633          @param arg: argument of function
2634          @type arg: typically L{Symbol}.
2635          """
2636          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2637    
2638       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,symbols.Symbol):     @rtype:C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray} depending on the type of arg.
2701         return symbols.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 Abs_Symbol(DependendSymbol):
2727       """
2728       L{Symbol} representing the result of the absolute value function
2729       """
2730       def __init__(self,arg):
2731          """
2732          initialization of abs L{Symbol} with argument arg
2733          @param arg: argument of function
2734          @type arg: typically L{Symbol}.
2735          """
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
2876       @type arg: C{float}, L{escript.Data}, L{Symbol}, L{numarray.NumArray}.
2877       @rtype:C{float}, L{escript.Data}, L{Symbol} depending on the type of arg.
2878       @raises TypeError: if the type of the argument is not expected.
2879       """
2880       if isinstance(arg,numarray.NumArray):
2881          if arg.rank==0:
2882             return float(arg)
2883          else:
2884             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 Maxval_Symbol(DependendSymbol):
2897       """
2898       L{Symbol} representing the result of the maximum value function
2899       """
2900       def __init__(self,arg):
2901          """
2902          initialization of maximum value L{Symbol} with argument arg
2903          @param arg: argument of function
2904          @type arg: typically L{Symbol}.
2905          """
2906          DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
2907    
2908       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.Float)
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):