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