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

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

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

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