/[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 2300 by gross, Wed Mar 11 08:17:57 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=0.):
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: tolerance. Values with absolute value less than tol are accepted
1500                   as zero.
1501       @type tol: C{float}
1502       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1503               on the type of C{arg}
1504       @raises TypeError: if the type of the argument is not expected
1505       """
1506       if isinstance(arg,numarray.NumArray):
1507          out=numarray.less_equal(abs(arg)-tol,numarray.zeros(arg.shape,numarray.Float64))*1.
1508          if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1509          return out
1510       elif isinstance(arg,escript.Data):
1511          return arg._whereZero(tol)
1512       elif isinstance(arg,float):
1513          if abs(arg)<=tol:
1514            return 1.
1515          else:
1516            return 0.
1517       elif isinstance(arg,int):
1518          if abs(float(arg))<=tol:
1519            return 1.
1520          else:
1521            return 0.
1522       elif isinstance(arg,Symbol):
1523          return WhereZero_Symbol(arg,tol)
1524       else:
1525          raise TypeError,"whereZero: Unknown argument type."
1526    
1527    class WhereZero_Symbol(DependendSymbol):
1528       """
1529       L{Symbol} representing the result of the mask of zero entries function.
1530       """
1531       def __init__(self,arg,tol=0.):
1532          """
1533          Initialization of whereZero L{Symbol} with argument C{arg}.
1534    
1535          @param arg: argument of function
1536          @type arg: typically L{Symbol}
1537          """
1538          DependendSymbol.__init__(self,args=[arg,tol],shape=arg.getShape(),dim=arg.getDim())
1539    
1540       def getMyCode(self,argstrs,format="escript"):
1541          """
1542          Returns program code that can be used to evaluate the symbol.
1543    
1544          @param argstrs: a string for each argument representing the argument
1545                          for the evaluation
1546          @type argstrs: C{str} or a C{list} of length 1 of C{str}
1547          @param format: specifies the format to be used. At the moment only
1548                         "escript", "str" and "text" are supported.
1549          @type format: C{str}
1550          @return: a piece of program code which can be used to evaluate the
1551                   expression assuming the values for the arguments are available
1552          @rtype: C{str}
1553          @raise NotImplementedError: if no implementation for the given format
1554                                      is available
1555          """
1556          if format=="escript" or format=="str"  or format=="text":
1557             return "whereZero(%s,tol=%s)"%(argstrs[0],argstrs[1])
1558          else:
1559             raise NotImplementedError,"WhereZero_Symbol does not provide program code for format %s."%format
1560    
1561       def substitute(self,argvals):
1562          """
1563          Assigns new values to symbols in the definition of the symbol.
1564          The method replaces the L{Symbol} u by argvals[u] in the expression
1565          defining this object.
1566    
1567          @param argvals: new values assigned to symbols
1568          @type argvals: C{dict} with keywords of type L{Symbol}
1569          @return: result of the substitution process. Operations are executed as
1570                   much as possible.
1571          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
1572                  depending on the degree of substitution
1573          @raise TypeError: if a value for a L{Symbol} cannot be substituted
1574          """
1575          if argvals.has_key(self):
1576             arg=argvals[self]
1577             if self.isAppropriateValue(arg):
1578                return arg
1579             else:
1580                raise TypeError,"%s: new value is not appropriate."%str(self)
1581          else:
1582             arg=self.getSubstitutedArguments(argvals)
1583             return whereZero(arg[0],arg[1])
1584    
1585    def whereNonZero(arg,tol=0.):
1586       """
1587       Returns mask of values different from zero of argument C{arg}.
1588    
1589       @param arg: argument
1590       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
1591       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1592               on the type of C{arg}
1593       @raise TypeError: if the type of the argument is not expected
1594       """
1595       if isinstance(arg,numarray.NumArray):
1596          out=numarray.greater(abs(arg)-tol,numarray.zeros(arg.shape,numarray.Float64))*1.
1597          if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1598          return out
1599       elif isinstance(arg,escript.Data):
1600          return arg._whereNonZero(tol)
1601       elif isinstance(arg,float):
1602          if abs(arg)>tol:
1603            return 1.
1604          else:
1605            return 0.
1606       elif isinstance(arg,int):
1607          if abs(float(arg))>tol:
1608            return 1.
1609          else:
1610            return 0.
1611       elif isinstance(arg,Symbol):
1612          return 1.-whereZero(arg,tol)
1613       else:
1614          raise TypeError,"whereNonZero: Unknown argument type."
1615    
1616    def erf(arg):
1617       """
1618       Returns the error function M{erf} of argument C{arg}.
1619    
1620       @param arg: argument
1621       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
1622       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1623               on the type of C{arg}
1624       @raise TypeError: if the type of the argument is not expected
1625       """
1626       if isinstance(arg,escript.Data):
1627          return arg._erf()
1628       else:
1629          raise TypeError,"erf: Unknown argument type."
1630    
1631    def sin(arg):
1632       """
1633       Returns sine of argument C{arg}.
1634    
1635       @param arg: argument
1636       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
1637       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1638               on the type of C{arg}
1639       @raise TypeError: if the type of the argument is not expected
1640       """
1641       if isinstance(arg,numarray.NumArray):
1642          return numarray.sin(arg)
1643       elif isinstance(arg,escript.Data):
1644          return arg._sin()
1645       elif isinstance(arg,float):
1646          return math.sin(arg)
1647       elif isinstance(arg,int):
1648          return math.sin(arg)
1649       elif isinstance(arg,Symbol):
1650          return Sin_Symbol(arg)
1651       else:
1652          raise TypeError,"sin: Unknown argument type."
1653    
1654    class Sin_Symbol(DependendSymbol):
1655       """
1656       L{Symbol} representing the result of the sine function.
1657       """
1658       def __init__(self,arg):
1659          """
1660          Initialization of sin L{Symbol} with argument C{arg}.
1661    
1662          @param arg: argument of function
1663          @type arg: typically L{Symbol}
1664          """
1665          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1666    
1667       def getMyCode(self,argstrs,format="escript"):
1668          """
1669          Returns program code that can be used to evaluate the symbol.
1670    
1671          @param argstrs: a string for each argument representing the argument
1672                          for the evaluation
1673          @type argstrs: C{str} or a C{list} of length 1 of C{str}
1674          @param format: specifies the format to be used. At the moment only
1675                         "escript", "str" and "text" are supported.
1676          @type format: C{str}
1677          @return: a piece of program code which can be used to evaluate the
1678                   expression assuming the values for the arguments are available
1679          @rtype: C{str}
1680          @raise NotImplementedError: if no implementation for the given format
1681                                      is available
1682          """
1683          if isinstance(argstrs,list):
1684              argstrs=argstrs[0]
1685          if format=="escript" or format=="str"  or format=="text":
1686             return "sin(%s)"%argstrs
1687          else:
1688             raise NotImplementedError,"Sin_Symbol does not provide program code for format %s."%format
1689    
1690       def substitute(self,argvals):
1691          """
1692          Assigns new values to symbols in the definition of the symbol.
1693          The method replaces the L{Symbol} u by argvals[u] in the expression
1694          defining this object.
1695    
1696          @param argvals: new values assigned to symbols
1697          @type argvals: C{dict} with keywords of type L{Symbol}
1698          @return: result of the substitution process. Operations are executed as
1699                   much as possible.
1700          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
1701                  depending on the degree of substitution
1702          @raise TypeError: if a value for a L{Symbol} cannot be substituted
1703          """
1704          if argvals.has_key(self):
1705             arg=argvals[self]
1706             if self.isAppropriateValue(arg):
1707                return arg
1708             else:
1709                raise TypeError,"%s: new value is not appropriate."%str(self)
1710          else:
1711             arg=self.getSubstitutedArguments(argvals)[0]
1712             return sin(arg)
1713    
1714       def diff(self,arg):
1715          """
1716          Differential of this object.
1717    
1718          @param arg: the derivative is calculated with respect to C{arg}
1719          @type arg: L{escript.Symbol}
1720          @return: derivative with respect to C{arg}
1721          @rtype: typically L{Symbol} but other types such as C{float},
1722                  L{escript.Data}, C{numarray.NumArray} are possible
1723          """
1724          if arg==self:
1725             return identity(self.getShape())
1726          else:
1727             myarg=self.getArgument()[0]
1728             val=matchShape(cos(myarg),self.getDifferentiatedArguments(arg)[0])
1729             return val[0]*val[1]
1730    
1731    def cos(arg):
1732       """
1733       Returns cosine of argument C{arg}.
1734    
1735       @param arg: argument
1736       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
1737       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1738               on the type of C{arg}
1739       @raises TypeError: if the type of the argument is not expected
1740       """
1741       if isinstance(arg,numarray.NumArray):
1742          return numarray.cos(arg)
1743       elif isinstance(arg,escript.Data):
1744          return arg._cos()
1745       elif isinstance(arg,float):
1746          return math.cos(arg)
1747       elif isinstance(arg,int):
1748          return math.cos(arg)
1749       elif isinstance(arg,Symbol):
1750          return Cos_Symbol(arg)
1751       else:
1752          raise TypeError,"cos: Unknown argument type."
1753    
1754    class Cos_Symbol(DependendSymbol):
1755       """
1756       L{Symbol} representing the result of the cosine function.
1757       """
1758       def __init__(self,arg):
1759          """
1760          Initialization of cos L{Symbol} with argument C{arg}.
1761    
1762          @param arg: argument of function
1763          @type arg: typically L{Symbol}
1764          """
1765          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1766    
1767       def getMyCode(self,argstrs,format="escript"):
1768          """
1769          Returns program code that can be used to evaluate the symbol.
1770    
1771          @param argstrs: a string for each argument representing the argument
1772                          for the evaluation
1773          @type argstrs: C{str} or a C{list} of length 1 of C{str}
1774          @param format: specifies the format to be used. At the moment only
1775                         "escript", "str" and "text" are supported.
1776          @type format: C{str}
1777          @return: a piece of program code which can be used to evaluate the
1778                   expression assuming the values for the arguments are available
1779          @rtype: C{str}
1780          @raise NotImplementedError: if no implementation for the given format
1781                                      is available
1782          """
1783          if isinstance(argstrs,list):
1784              argstrs=argstrs[0]
1785          if format=="escript" or format=="str"  or format=="text":
1786             return "cos(%s)"%argstrs
1787          else:
1788             raise NotImplementedError,"Cos_Symbol does not provide program code for format %s."%format
1789    
1790       def substitute(self,argvals):
1791          """
1792          Assigns new values to symbols in the definition of the symbol.
1793          The method replaces the L{Symbol} u by argvals[u] in the expression
1794          defining this object.
1795    
1796          @param argvals: new values assigned to symbols
1797          @type argvals: C{dict} with keywords of type L{Symbol}
1798          @return: result of the substitution process. Operations are executed as
1799                   much as possible.
1800          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
1801                  depending on the degree of substitution
1802          @raise TypeError: if a value for a L{Symbol} cannot be substituted
1803          """
1804          if argvals.has_key(self):
1805             arg=argvals[self]
1806             if self.isAppropriateValue(arg):
1807                return arg
1808             else:
1809                raise TypeError,"%s: new value is not appropriate."%str(self)
1810          else:
1811             arg=self.getSubstitutedArguments(argvals)[0]
1812             return cos(arg)
1813    
1814       def diff(self,arg):
1815          """
1816          Differential of this object.
1817    
1818          @param arg: the derivative is calculated with respect to C{arg}
1819          @type arg: L{escript.Symbol}
1820          @return: derivative with respect to C{arg}
1821          @rtype: typically L{Symbol} but other types such as C{float},
1822                  L{escript.Data}, C{numarray.NumArray} are possible
1823          """
1824          if arg==self:
1825             return identity(self.getShape())
1826          else:
1827             myarg=self.getArgument()[0]
1828             val=matchShape(-sin(myarg),self.getDifferentiatedArguments(arg)[0])
1829             return val[0]*val[1]
1830    
1831    def tan(arg):
1832       """
1833       Returns tangent of argument C{arg}.
1834    
1835       @param arg: argument
1836       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
1837       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1838               on the type of C{arg}
1839       @raises TypeError: if the type of the argument is not expected
1840       """
1841       if isinstance(arg,numarray.NumArray):
1842          return numarray.tan(arg)
1843       elif isinstance(arg,escript.Data):
1844          return arg._tan()
1845       elif isinstance(arg,float):
1846          return math.tan(arg)
1847       elif isinstance(arg,int):
1848          return math.tan(arg)
1849       elif isinstance(arg,Symbol):
1850          return Tan_Symbol(arg)
1851       else:
1852          raise TypeError,"tan: Unknown argument type."
1853    
1854    class Tan_Symbol(DependendSymbol):
1855       """
1856       L{Symbol} representing the result of the tangent function.
1857       """
1858       def __init__(self,arg):
1859          """
1860          Initialization of tan L{Symbol} with argument C{arg}.
1861    
1862          @param arg: argument of function
1863          @type arg: typically L{Symbol}
1864          """
1865          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1866    
1867       def getMyCode(self,argstrs,format="escript"):
1868          """
1869          Returns program code that can be used to evaluate the symbol.
1870    
1871          @param argstrs: a string for each argument representing the argument
1872                          for the evaluation
1873          @type argstrs: C{str} or a C{list} of length 1 of C{str}
1874          @param format: specifies the format to be used. At the moment only
1875                         "escript", "str" and "text" are supported.
1876          @type format: C{str}
1877          @return: a piece of program code which can be used to evaluate the
1878                   expression assuming the values for the arguments are available
1879          @rtype: C{str}
1880          @raise NotImplementedError: if no implementation for the given format
1881                                      is available
1882          """
1883          if isinstance(argstrs,list):
1884              argstrs=argstrs[0]
1885          if format=="escript" or format=="str"  or format=="text":
1886             return "tan(%s)"%argstrs
1887          else:
1888             raise NotImplementedError,"Tan_Symbol does not provide program code for format %s."%format
1889    
1890       def substitute(self,argvals):
1891          """
1892          Assigns new values to symbols in the definition of the symbol.
1893          The method replaces the L{Symbol} u by argvals[u] in the expression
1894          defining this object.
1895    
1896          @param argvals: new values assigned to symbols
1897          @type argvals: C{dict} with keywords of type L{Symbol}
1898          @return: result of the substitution process. Operations are executed as
1899                   much as possible.
1900          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
1901                  depending on the degree of substitution
1902          @raise TypeError: if a value for a L{Symbol} cannot be substituted
1903          """
1904          if argvals.has_key(self):
1905             arg=argvals[self]
1906             if self.isAppropriateValue(arg):
1907                return arg
1908             else:
1909                raise TypeError,"%s: new value is not appropriate."%str(self)
1910          else:
1911             arg=self.getSubstitutedArguments(argvals)[0]
1912             return tan(arg)
1913    
1914       def diff(self,arg):
1915          """
1916          Differential of this object.
1917    
1918          @param arg: the derivative is calculated with respect to C{arg}
1919          @type arg: L{escript.Symbol}
1920          @return: derivative with respect to C{arg}
1921          @rtype: typically L{Symbol} but other types such as C{float},
1922                  L{escript.Data}, C{numarray.NumArray} are possible
1923          """
1924          if arg==self:
1925             return identity(self.getShape())
1926          else:
1927             myarg=self.getArgument()[0]
1928             val=matchShape(1./cos(myarg)**2,self.getDifferentiatedArguments(arg)[0])
1929             return val[0]*val[1]
1930    
1931    def asin(arg):
1932       """
1933       Returns the inverse sine of argument C{arg}.
1934    
1935       @param arg: argument
1936       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
1937       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1938               on the type of C{arg}
1939       @raises TypeError: if the type of the argument is not expected
1940       """
1941       if isinstance(arg,numarray.NumArray):
1942          return numarray.arcsin(arg)
1943       elif isinstance(arg,escript.Data):
1944          return arg._asin()
1945       elif isinstance(arg,float):
1946          return math.asin(arg)
1947       elif isinstance(arg,int):
1948          return math.asin(arg)
1949       elif isinstance(arg,Symbol):
1950          return Asin_Symbol(arg)
1951       else:
1952          raise TypeError,"asin: Unknown argument type."
1953    
1954    class Asin_Symbol(DependendSymbol):
1955       """
1956       L{Symbol} representing the result of the inverse sine function.
1957       """
1958       def __init__(self,arg):
1959          """
1960          Initialization of asin L{Symbol} with argument C{arg}.
1961    
1962          @param arg: argument of function
1963          @type arg: typically L{Symbol}
1964          """
1965          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1966    
1967       def getMyCode(self,argstrs,format="escript"):
1968          """
1969          Returns program code that can be used to evaluate the symbol.
1970    
1971          @param argstrs: a string for each argument representing the argument
1972                          for the evaluation
1973          @type argstrs: C{str} or a C{list} of length 1 of C{str}
1974          @param format: specifies the format to be used. At the moment only
1975                         "escript", "str" and "text" are supported.
1976          @type format: C{str}
1977          @return: a piece of program code which can be used to evaluate the
1978                   expression assuming the values for the arguments are available
1979          @rtype: C{str}
1980          @raise NotImplementedError: if no implementation for the given format
1981                                      is available
1982          """
1983          if isinstance(argstrs,list):
1984              argstrs=argstrs[0]
1985          if format=="escript" or format=="str"  or format=="text":
1986             return "asin(%s)"%argstrs
1987          else:
1988             raise NotImplementedError,"Asin_Symbol does not provide program code for format %s."%format
1989    
1990       def substitute(self,argvals):
1991          """
1992          Assigns new values to symbols in the definition of the symbol.
1993          The method replaces the L{Symbol} u by argvals[u] in the expression
1994          defining this object.
1995    
1996          @param argvals: new values assigned to symbols
1997          @type argvals: C{dict} with keywords of type L{Symbol}
1998          @return: result of the substitution process. Operations are executed as
1999                   much as possible.
2000          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2001                  depending on the degree of substitution
2002          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2003          """
2004          if argvals.has_key(self):
2005             arg=argvals[self]
2006             if self.isAppropriateValue(arg):
2007                return arg
2008             else:
2009                raise TypeError,"%s: new value is not appropriate."%str(self)
2010          else:
2011             arg=self.getSubstitutedArguments(argvals)[0]
2012             return asin(arg)
2013    
2014       def diff(self,arg):
2015          """
2016          Differential of this object.
2017    
2018          @param arg: the derivative is calculated with respect to C{arg}
2019          @type arg: L{escript.Symbol}
2020          @return: derivative with respect to C{arg}
2021          @rtype: typically L{Symbol} but other types such as C{float},
2022                  L{escript.Data}, C{numarray.NumArray} are possible
2023          """
2024          if arg==self:
2025             return identity(self.getShape())
2026          else:
2027             myarg=self.getArgument()[0]
2028             val=matchShape(1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2029             return val[0]*val[1]
2030    
2031    def acos(arg):
2032       """
2033       Returns the inverse cosine of argument C{arg}.
2034    
2035       @param arg: argument
2036       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2037       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2038               on the type of C{arg}
2039       @raises TypeError: if the type of the argument is not expected
2040       """
2041       if isinstance(arg,numarray.NumArray):
2042          return numarray.arccos(arg)
2043       elif isinstance(arg,escript.Data):
2044          return arg._acos()
2045       elif isinstance(arg,float):
2046          return math.acos(arg)
2047       elif isinstance(arg,int):
2048          return math.acos(arg)
2049       elif isinstance(arg,Symbol):
2050          return Acos_Symbol(arg)
2051       else:
2052          raise TypeError,"acos: Unknown argument type."
2053    
2054    class Acos_Symbol(DependendSymbol):
2055       """
2056       L{Symbol} representing the result of the inverse cosine function.
2057       """
2058       def __init__(self,arg):
2059          """
2060          Initialization of acos L{Symbol} with argument C{arg}.
2061    
2062          @param arg: argument of function
2063          @type arg: typically L{Symbol}
2064          """
2065          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2066    
2067       def getMyCode(self,argstrs,format="escript"):
2068          """
2069          Returns program code that can be used to evaluate the symbol.
2070    
2071          @param argstrs: a string for each argument representing the argument
2072                          for the evaluation
2073          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2074          @param format: specifies the format to be used. At the moment only
2075                         "escript", "str" and "text" are supported.
2076          @type format: C{str}
2077          @return: a piece of program code which can be used to evaluate the
2078                   expression assuming the values for the arguments are available
2079          @rtype: C{str}
2080          @raise NotImplementedError: if no implementation for the given format
2081                                      is available
2082          """
2083          if isinstance(argstrs,list):
2084              argstrs=argstrs[0]
2085          if format=="escript" or format=="str"  or format=="text":
2086             return "acos(%s)"%argstrs
2087          else:
2088             raise NotImplementedError,"Acos_Symbol does not provide program code for format %s."%format
2089    
2090       def substitute(self,argvals):
2091          """
2092          Assigns new values to symbols in the definition of the symbol.
2093          The method replaces the L{Symbol} u by argvals[u] in the expression
2094          defining this object.
2095    
2096          @param argvals: new values assigned to symbols
2097          @type argvals: C{dict} with keywords of type L{Symbol}
2098          @return: result of the substitution process. Operations are executed as
2099                   much as possible.
2100          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2101                  depending on the degree of substitution
2102          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2103          """
2104          if argvals.has_key(self):
2105             arg=argvals[self]
2106             if self.isAppropriateValue(arg):
2107                return arg
2108             else:
2109                raise TypeError,"%s: new value is not appropriate."%str(self)
2110          else:
2111             arg=self.getSubstitutedArguments(argvals)[0]
2112             return acos(arg)
2113    
2114       def diff(self,arg):
2115          """
2116          Differential of this object.
2117    
2118          @param arg: the derivative is calculated with respect to C{arg}
2119          @type arg: L{escript.Symbol}
2120          @return: derivative with respect to C{arg}
2121          @rtype: typically L{Symbol} but other types such as C{float},
2122                  L{escript.Data}, C{numarray.NumArray} are possible
2123          """
2124          if arg==self:
2125             return identity(self.getShape())
2126          else:
2127             myarg=self.getArgument()[0]
2128             val=matchShape(-1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2129             return val[0]*val[1]
2130    
2131  def atan(arg):  def atan(arg):
2132      """     """
2133      Applies the atan function to arg.     Returns inverse tangent of argument C{arg}.
2134    
2135      @param arg: argument     @param arg: argument
2136      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2137      if isinstance(arg,symbols.Symbol):     @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2138         return symbols.Atan_Symbol(arg)             on the type of C{arg}
2139      elif hasattr(arg,"atan"):     @raises TypeError: if the type of the argument is not expected
2140         return arg.atan()     """
2141      else:     if isinstance(arg,numarray.NumArray):
2142         return numarray.atan(arg)        return numarray.arctan(arg)
2143       elif isinstance(arg,escript.Data):
2144          return arg._atan()
2145       elif isinstance(arg,float):
2146          return math.atan(arg)
2147       elif isinstance(arg,int):
2148          return math.atan(arg)
2149       elif isinstance(arg,Symbol):
2150          return Atan_Symbol(arg)
2151       else:
2152          raise TypeError,"atan: Unknown argument type."
2153    
2154    class Atan_Symbol(DependendSymbol):
2155       """
2156       L{Symbol} representing the result of the inverse tangent function.
2157       """
2158       def __init__(self,arg):
2159          """
2160          Initialization of atan L{Symbol} with argument C{arg}.
2161    
2162          @param arg: argument of function
2163          @type arg: typically L{Symbol}
2164          """
2165          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2166    
2167       def getMyCode(self,argstrs,format="escript"):
2168          """
2169          Returns program code that can be used to evaluate the symbol.
2170    
2171          @param argstrs: a string for each argument representing the argument
2172                          for the evaluation
2173          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2174          @param format: specifies the format to be used. At the moment only
2175                         "escript", "str" and "text" are supported.
2176          @type format: C{str}
2177          @return: a piece of program code which can be used to evaluate the
2178                   expression assuming the values for the arguments are available
2179          @rtype: C{str}
2180          @raise NotImplementedError: if no implementation for the given format
2181                                      is available
2182          """
2183          if isinstance(argstrs,list):
2184              argstrs=argstrs[0]
2185          if format=="escript" or format=="str"  or format=="text":
2186             return "atan(%s)"%argstrs
2187          else:
2188             raise NotImplementedError,"Atan_Symbol does not provide program code for format %s."%format
2189    
2190       def substitute(self,argvals):
2191          """
2192          Assigns new values to symbols in the definition of the symbol.
2193          The method replaces the L{Symbol} u by argvals[u] in the expression
2194          defining this object.
2195    
2196          @param argvals: new values assigned to symbols
2197          @type argvals: C{dict} with keywords of type L{Symbol}
2198          @return: result of the substitution process. Operations are executed as
2199                   much as possible.
2200          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2201                  depending on the degree of substitution
2202          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2203          """
2204          if argvals.has_key(self):
2205             arg=argvals[self]
2206             if self.isAppropriateValue(arg):
2207                return arg
2208             else:
2209                raise TypeError,"%s: new value is not appropriate."%str(self)
2210          else:
2211             arg=self.getSubstitutedArguments(argvals)[0]
2212             return atan(arg)
2213    
2214       def diff(self,arg):
2215          """
2216          Differential of this object.
2217    
2218          @param arg: the derivative is calculated with respect to C{arg}
2219          @type arg: L{escript.Symbol}
2220          @return: derivative with respect to C{arg}
2221          @rtype: typically L{Symbol} but other types such as C{float},
2222                  L{escript.Data}, C{numarray.NumArray} are possible
2223          """
2224          if arg==self:
2225             return identity(self.getShape())
2226          else:
2227             myarg=self.getArgument()[0]
2228             val=matchShape(1./(1+myarg**2),self.getDifferentiatedArguments(arg)[0])
2229             return val[0]*val[1]
2230    
2231  def sinh(arg):  def sinh(arg):
2232      """     """
2233      Applies the sinh function to arg.     Returns the hyperbolic sine of argument C{arg}.
2234    
2235      @param arg: argument     @param arg: argument
2236      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2237      if isinstance(arg,symbols.Symbol):     @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2238         return symbols.Sinh_Symbol(arg)             on the type of C{arg}
2239      elif hasattr(arg,"sinh"):     @raises TypeError: if the type of the argument is not expected
2240         return arg.sinh()     """
2241      else:     if isinstance(arg,numarray.NumArray):
2242         return numarray.sinh(arg)        return numarray.sinh(arg)
2243       elif isinstance(arg,escript.Data):
2244          return arg._sinh()
2245       elif isinstance(arg,float):
2246          return math.sinh(arg)
2247       elif isinstance(arg,int):
2248          return math.sinh(arg)
2249       elif isinstance(arg,Symbol):
2250          return Sinh_Symbol(arg)
2251       else:
2252          raise TypeError,"sinh: Unknown argument type."
2253    
2254    class Sinh_Symbol(DependendSymbol):
2255       """
2256       L{Symbol} representing the result of the hyperbolic sine function.
2257       """
2258       def __init__(self,arg):
2259          """
2260          Initialization of sinh L{Symbol} with argument C{arg}.
2261    
2262          @param arg: argument of function
2263          @type arg: typically L{Symbol}
2264          """
2265          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2266    
2267       def getMyCode(self,argstrs,format="escript"):
2268          """
2269          Returns program code that can be used to evaluate the symbol.
2270    
2271          @param argstrs: a string for each argument representing the argument
2272                          for the evaluation
2273          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2274          @param format: specifies the format to be used. At the moment only
2275                         "escript", "str" and "text" are supported.
2276          @type format: C{str}
2277          @return: a piece of program code which can be used to evaluate the
2278                   expression assuming the values for the arguments are available
2279          @rtype: C{str}
2280          @raise NotImplementedError: if no implementation for the given format
2281                                      is available
2282          """
2283          if isinstance(argstrs,list):
2284              argstrs=argstrs[0]
2285          if format=="escript" or format=="str"  or format=="text":
2286             return "sinh(%s)"%argstrs
2287          else:
2288             raise NotImplementedError,"Sinh_Symbol does not provide program code for format %s."%format
2289    
2290       def substitute(self,argvals):
2291          """
2292          Assigns new values to symbols in the definition of the symbol.
2293          The method replaces the L{Symbol} u by argvals[u] in the expression
2294          defining this object.
2295    
2296          @param argvals: new values assigned to symbols
2297          @type argvals: C{dict} with keywords of type L{Symbol}
2298          @return: result of the substitution process. Operations are executed as
2299                   much as possible.
2300          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2301                  depending on the degree of substitution
2302          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2303          """
2304          if argvals.has_key(self):
2305             arg=argvals[self]
2306             if self.isAppropriateValue(arg):
2307                return arg
2308             else:
2309                raise TypeError,"%s: new value is not appropriate."%str(self)
2310          else:
2311             arg=self.getSubstitutedArguments(argvals)[0]
2312             return sinh(arg)
2313    
2314       def diff(self,arg):
2315          """
2316          Differential of this object.
2317    
2318          @param arg: the derivative is calculated with respect to C{arg}
2319          @type arg: L{escript.Symbol}
2320          @return: derivative with respect to C{arg}
2321          @rtype: typically L{Symbol} but other types such as C{float},
2322                  L{escript.Data}, C{numarray.NumArray} are possible
2323          """
2324          if arg==self:
2325             return identity(self.getShape())
2326          else:
2327             myarg=self.getArgument()[0]
2328             val=matchShape(cosh(myarg),self.getDifferentiatedArguments(arg)[0])
2329             return val[0]*val[1]
2330    
2331  def cosh(arg):  def cosh(arg):
2332      """     """
2333      Applies the cosh function to arg.     Returns the hyperbolic cosine of argument C{arg}.
2334    
2335      @param arg: argument     @param arg: argument
2336      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2337      if isinstance(arg,symbols.Symbol):     @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2338         return symbols.Cosh_Symbol(arg)             on the type of C{arg}
2339      elif hasattr(arg,"cosh"):     @raises TypeError: if the type of the argument is not expected
2340         return arg.cosh()     """
2341      else:     if isinstance(arg,numarray.NumArray):
2342         return numarray.cosh(arg)        return numarray.cosh(arg)
2343       elif isinstance(arg,escript.Data):
2344          return arg._cosh()
2345       elif isinstance(arg,float):
2346          return math.cosh(arg)
2347       elif isinstance(arg,int):
2348          return math.cosh(arg)
2349       elif isinstance(arg,Symbol):
2350          return Cosh_Symbol(arg)
2351       else:
2352          raise TypeError,"cosh: Unknown argument type."
2353    
2354    class Cosh_Symbol(DependendSymbol):
2355       """
2356       L{Symbol} representing the result of the hyperbolic cosine function.
2357       """
2358       def __init__(self,arg):
2359          """
2360          Initialization of cosh L{Symbol} with argument C{arg}.
2361    
2362          @param arg: argument of function
2363          @type arg: typically L{Symbol}
2364          """
2365          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2366    
2367       def getMyCode(self,argstrs,format="escript"):
2368          """
2369          Returns program code that can be used to evaluate the symbol.
2370    
2371          @param argstrs: a string for each argument representing the argument
2372                          for the evaluation
2373          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2374          @param format: specifies the format to be used. At the moment only
2375                         "escript", "str" and "text" are supported.
2376          @type format: C{str}
2377          @return: a piece of program code which can be used to evaluate the
2378                   expression assuming the values for the arguments are available
2379          @rtype: C{str}
2380          @raise NotImplementedError: if no implementation for the given format
2381                                      is available
2382          """
2383          if isinstance(argstrs,list):
2384              argstrs=argstrs[0]
2385          if format=="escript" or format=="str"  or format=="text":
2386             return "cosh(%s)"%argstrs
2387          else:
2388             raise NotImplementedError,"Cosh_Symbol does not provide program code for format %s."%format
2389    
2390       def substitute(self,argvals):
2391          """
2392          Assigns new values to symbols in the definition of the symbol.
2393          The method replaces the L{Symbol} u by argvals[u] in the expression
2394          defining this object.
2395    
2396          @param argvals: new values assigned to symbols
2397          @type argvals: C{dict} with keywords of type L{Symbol}
2398          @return: result of the substitution process. Operations are executed as
2399                   much as possible.
2400          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2401                  depending on the degree of substitution
2402          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2403          """
2404          if argvals.has_key(self):
2405             arg=argvals[self]
2406             if self.isAppropriateValue(arg):
2407                return arg
2408             else:
2409                raise TypeError,"%s: new value is not appropriate."%str(self)
2410          else:
2411             arg=self.getSubstitutedArguments(argvals)[0]
2412             return cosh(arg)
2413    
2414       def diff(self,arg):
2415          """
2416          Differential of this object.
2417    
2418          @param arg: the derivative is calculated with respect to C{arg}
2419          @type arg: L{escript.Symbol}
2420          @return: derivative with respect to C{arg}
2421          @rtype: typically L{Symbol} but other types such as C{float},
2422                  L{escript.Data}, C{numarray.NumArray} are possible
2423          """
2424          if arg==self:
2425             return identity(self.getShape())
2426          else:
2427             myarg=self.getArgument()[0]
2428             val=matchShape(sinh(myarg),self.getDifferentiatedArguments(arg)[0])
2429             return val[0]*val[1]
2430    
2431  def tanh(arg):  def tanh(arg):
2432      """     """
2433      Applies the tanh function to arg.     Returns the hyperbolic tangent of argument C{arg}.
2434    
2435      @param arg: argument     @param arg: argument
2436      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2437      if isinstance(arg,symbols.Symbol):     @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2438         return symbols.Tanh_Symbol(arg)             on the type of C{arg}
2439      elif hasattr(arg,"tanh"):     @raises TypeError: if the type of the argument is not expected
2440         return arg.tanh()     """
2441      else:     if isinstance(arg,numarray.NumArray):
2442         return numarray.tanh(arg)        return numarray.tanh(arg)
2443       elif isinstance(arg,escript.Data):
2444          return arg._tanh()
2445       elif isinstance(arg,float):
2446          return math.tanh(arg)
2447       elif isinstance(arg,int):
2448          return math.tanh(arg)
2449       elif isinstance(arg,Symbol):
2450          return Tanh_Symbol(arg)
2451       else:
2452          raise TypeError,"tanh: Unknown argument type."
2453    
2454    class Tanh_Symbol(DependendSymbol):
2455       """
2456       L{Symbol} representing the result of the hyperbolic tangent function.
2457       """
2458       def __init__(self,arg):
2459          """
2460          Initialization of tanh L{Symbol} with argument C{arg}.
2461    
2462          @param arg: argument of function
2463          @type arg: typically L{Symbol}
2464          """
2465          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2466    
2467       def getMyCode(self,argstrs,format="escript"):
2468          """
2469          Returns program code that can be used to evaluate the symbol.
2470    
2471          @param argstrs: a string for each argument representing the argument
2472                          for the evaluation
2473          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2474          @param format: specifies the format to be used. At the moment only
2475                         "escript", "str" and "text" are supported.
2476          @type format: C{str}
2477          @return: a piece of program code which can be used to evaluate the
2478                   expression assuming the values for the arguments are available
2479          @rtype: C{str}
2480          @raise NotImplementedError: if no implementation for the given format
2481                                      is available
2482          """
2483          if isinstance(argstrs,list):
2484              argstrs=argstrs[0]
2485          if format=="escript" or format=="str"  or format=="text":
2486             return "tanh(%s)"%argstrs
2487          else:
2488             raise NotImplementedError,"Tanh_Symbol does not provide program code for format %s."%format
2489    
2490       def substitute(self,argvals):
2491          """
2492          Assigns new values to symbols in the definition of the symbol.
2493          The method replaces the L{Symbol} u by argvals[u] in the expression
2494          defining this object.
2495    
2496          @param argvals: new values assigned to symbols
2497          @type argvals: C{dict} with keywords of type L{Symbol}
2498          @return: result of the substitution process. Operations are executed as
2499                   much as possible.
2500          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2501                  depending on the degree of substitution
2502          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2503          """
2504          if argvals.has_key(self):
2505             arg=argvals[self]
2506             if self.isAppropriateValue(arg):
2507                return arg
2508             else:
2509                raise TypeError,"%s: new value is not appropriate."%str(self)
2510          else:
2511             arg=self.getSubstitutedArguments(argvals)[0]
2512             return tanh(arg)
2513    
2514       def diff(self,arg):
2515          """
2516          Differential of this object.
2517    
2518          @param arg: the derivative is calculated with respect to C{arg}
2519          @type arg: L{escript.Symbol}
2520          @return: derivative with respect to C{arg}
2521          @rtype: typically L{Symbol} but other types such as C{float},
2522                  L{escript.Data}, C{numarray.NumArray} are possible
2523          """
2524          if arg==self:
2525             return identity(self.getShape())
2526          else:
2527             myarg=self.getArgument()[0]
2528             val=matchShape(1./cosh(myarg)**2,self.getDifferentiatedArguments(arg)[0])
2529             return val[0]*val[1]
2530    
2531  def asinh(arg):  def asinh(arg):
2532      """     """
2533      Applies the asinh function to arg.     Returns the inverse hyperbolic sine of argument C{arg}.
2534    
2535      @param arg: argument     @param arg: argument
2536      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2537      if isinstance(arg,symbols.Symbol):     @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2538         return symbols.Asinh_Symbol(arg)             on the type of C{arg}
2539      elif hasattr(arg,"asinh"):     @raises TypeError: if the type of the argument is not expected
2540         return arg.asinh()     """
2541      else:     if isinstance(arg,numarray.NumArray):
2542         return numarray.asinh(arg)        return numarray.arcsinh(arg)
2543       elif isinstance(arg,escript.Data):
2544          return arg._asinh()
2545       elif isinstance(arg,float):
2546          return numarray.arcsinh(arg)
2547       elif isinstance(arg,int):
2548          return numarray.arcsinh(float(arg))
2549       elif isinstance(arg,Symbol):
2550          return Asinh_Symbol(arg)
2551       else:
2552          raise TypeError,"asinh: Unknown argument type."
2553    
2554    class Asinh_Symbol(DependendSymbol):
2555       """
2556       L{Symbol} representing the result of the inverse hyperbolic sine function.
2557       """
2558       def __init__(self,arg):
2559          """
2560          Initialization of asinh L{Symbol} with argument C{arg}.
2561    
2562          @param arg: argument of function
2563          @type arg: typically L{Symbol}
2564          """
2565          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2566    
2567       def getMyCode(self,argstrs,format="escript"):
2568          """
2569          Returns program code that can be used to evaluate the symbol.
2570    
2571          @param argstrs: a string for each argument representing the argument
2572                          for the evaluation
2573          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2574          @param format: specifies the format to be used. At the moment only
2575                         "escript", "str" and "text" are supported.
2576          @type format: C{str}
2577          @return: a piece of program code which can be used to evaluate the
2578                   expression assuming the values for the arguments are available
2579          @rtype: C{str}
2580          @raise NotImplementedError: if no implementation for the given format
2581                                      is available
2582          """
2583          if isinstance(argstrs,list):
2584              argstrs=argstrs[0]
2585          if format=="escript" or format=="str"  or format=="text":
2586             return "asinh(%s)"%argstrs
2587          else:
2588             raise NotImplementedError,"Asinh_Symbol does not provide program code for format %s."%format
2589    
2590       def substitute(self,argvals):
2591          """
2592          Assigns new values to symbols in the definition of the symbol.
2593          The method replaces the L{Symbol} u by argvals[u] in the expression
2594          defining this object.
2595    
2596          @param argvals: new values assigned to symbols
2597          @type argvals: C{dict} with keywords of type L{Symbol}
2598          @return: result of the substitution process. Operations are executed as
2599                   much as possible.
2600          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2601                  depending on the degree of substitution
2602          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2603          """
2604          if argvals.has_key(self):
2605             arg=argvals[self]
2606             if self.isAppropriateValue(arg):
2607                return arg
2608             else:
2609                raise TypeError,"%s: new value is not appropriate."%str(self)
2610          else:
2611             arg=self.getSubstitutedArguments(argvals)[0]
2612             return asinh(arg)
2613    
2614       def diff(self,arg):
2615          """
2616          Differential of this object.
2617    
2618          @param arg: the derivative is calculated with respect to C{arg}
2619          @type arg: L{escript.Symbol}
2620          @return: derivative with respect to C{arg}
2621          @rtype: typically L{Symbol} but other types such as C{float},
2622                  L{escript.Data}, C{numarray.NumArray} are possible
2623          """
2624          if arg==self:
2625             return identity(self.getShape())
2626          else:
2627             myarg=self.getArgument()[0]
2628             val=matchShape(1./sqrt(myarg**2+1),self.getDifferentiatedArguments(arg)[0])
2629             return val[0]*val[1]
2630    
2631  def acosh(arg):  def acosh(arg):
2632      """     """
2633      Applies the acosh function to arg.     Returns the inverse hyperbolic cosine of argument C{arg}.
2634    
2635      @param arg: argument     @param arg: argument
2636      """     @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2637      if isinstance(arg,symbols.Symbol):     @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2638         return symbols.Acosh_Symbol(arg)             on the type of C{arg}
2639      elif hasattr(arg,"acosh"):     @raises TypeError: if the type of the argument is not expected
2640         return arg.acosh()     """
2641      else:     if isinstance(arg,numarray.NumArray):
2642         return numarray.acosh(arg)        return numarray.arccosh(arg)
2643       elif isinstance(arg,escript.Data):
2644          return arg._acosh()
2645       elif isinstance(arg,float):
2646          return numarray.arccosh(arg)
2647       elif isinstance(arg,int):
2648          return numarray.arccosh(float(arg))
2649       elif isinstance(arg,Symbol):
2650          return Acosh_Symbol(arg)
2651       else:
2652          raise TypeError,"acosh: Unknown argument type."
2653    
2654    class Acosh_Symbol(DependendSymbol):
2655       """
2656       L{Symbol} representing the result of the inverse hyperbolic cosine function.
2657       """
2658       def __init__(self,arg):
2659          """
2660          Initialization of acosh L{Symbol} with argument C{arg}.
2661    
2662          @param arg: argument of function
2663          @type arg: typically L{Symbol}
2664          """
2665          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2666    
2667       def getMyCode(self,argstrs,format="escript"):
2668          """
2669          Returns program code that can be used to evaluate the symbol.
2670    
2671          @param argstrs: a string for each argument representing the argument
2672                          for the evaluation
2673          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2674          @param format: specifies the format to be used. At the moment only
2675                         "escript", "str" and "text" are supported.
2676          @type format: C{str}
2677          @return: a piece of program code which can be used to evaluate the
2678                   expression assuming the values for the arguments are available
2679          @rtype: C{str}
2680          @raise NotImplementedError: if no implementation for the given format
2681                                      is available
2682          """
2683          if isinstance(argstrs,list):
2684              argstrs=argstrs[0]
2685          if format=="escript" or format=="str"  or format=="text":
2686             return "acosh(%s)"%argstrs
2687          else:
2688             raise NotImplementedError,"Acosh_Symbol does not provide program code for format %s."%format
2689    
2690       def substitute(self,argvals):
2691          """
2692          Assigns new values to symbols in the definition of the symbol.
2693          The method replaces the L{Symbol} u by argvals[u] in the expression
2694          defining this object.
2695    
2696          @param argvals: new values assigned to symbols
2697          @type argvals: C{dict} with keywords of type L{Symbol}
2698          @return: result of the substitution process. Operations are executed as
2699                   much as possible.
2700          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2701                  depending on the degree of substitution
2702          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2703          """
2704          if argvals.has_key(self):
2705             arg=argvals[self]
2706             if self.isAppropriateValue(arg):
2707                return arg
2708             else:
2709                raise TypeError,"%s: new value is not appropriate."%str(self)
2710          else:
2711             arg=self.getSubstitutedArguments(argvals)[0]
2712             return acosh(arg)
2713    
2714       def diff(self,arg):
2715          """
2716          Differential of this object.
2717    
2718          @param arg: the derivative is calculated with respect to C{arg}
2719          @type arg: L{escript.Symbol}
2720          @return: derivative with respect to C{arg}
2721          @rtype: typically L{Symbol} but other types such as C{float},
2722                  L{escript.Data}, C{numarray.NumArray} are possible
2723          """
2724          if arg==self:
2725             return identity(self.getShape())
2726          else:
2727             myarg=self.getArgument()[0]
2728             val=matchShape(1./sqrt(myarg**2-1),self.getDifferentiatedArguments(arg)[0])
2729             return val[0]*val[1]
2730    
2731  def atanh(arg):  def atanh(arg):
2732       """
2733       Returns the inverse hyperbolic tangent of argument C{arg}.
2734    
2735       @param arg: argument
2736       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2737       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2738               on the type of C{arg}
2739       @raises TypeError: if the type of the argument is not expected
2740       """
2741       if isinstance(arg,numarray.NumArray):
2742          return numarray.arctanh(arg)
2743       elif isinstance(arg,escript.Data):
2744          return arg._atanh()
2745       elif isinstance(arg,float):
2746          return numarray.arctanh(arg)
2747       elif isinstance(arg,int):
2748          return numarray.arctanh(float(arg))
2749       elif isinstance(arg,Symbol):
2750          return Atanh_Symbol(arg)
2751       else:
2752          raise TypeError,"atanh: Unknown argument type."
2753    
2754    class Atanh_Symbol(DependendSymbol):
2755       """
2756       L{Symbol} representing the result of the inverse hyperbolic tangent function.
2757       """
2758       def __init__(self,arg):
2759          """
2760          Initialization of atanh L{Symbol} with argument C{arg}.
2761    
2762          @param arg: argument of function
2763          @type arg: typically L{Symbol}
2764          """
2765          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2766    
2767       def getMyCode(self,argstrs,format="escript"):
2768          """
2769          Returns program code that can be used to evaluate the symbol.
2770    
2771          @param argstrs: a string for each argument representing the argument
2772                          for the evaluation
2773          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2774          @param format: specifies the format to be used. At the moment only
2775                         "escript", "str" and "text" are supported.
2776          @type format: C{str}
2777          @return: a piece of program code which can be used to evaluate the
2778                   expression assuming the values for the arguments are available
2779          @rtype: C{str}
2780          @raise NotImplementedError: if no implementation for the given format
2781                                      is available
2782          """
2783          if isinstance(argstrs,list):
2784              argstrs=argstrs[0]
2785          if format=="escript" or format=="str"  or format=="text":
2786             return "atanh(%s)"%argstrs
2787          else:
2788             raise NotImplementedError,"Atanh_Symbol does not provide program code for format %s."%format
2789    
2790       def substitute(self,argvals):
2791          """
2792          Assigns new values to symbols in the definition of the symbol.
2793          The method replaces the L{Symbol} u by argvals[u] in the expression
2794          defining this object.
2795    
2796          @param argvals: new values assigned to symbols
2797          @type argvals: C{dict} with keywords of type L{Symbol}
2798          @return: result of the substitution process. Operations are executed as
2799                   much as possible.
2800          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2801                  depending on the degree of substitution
2802          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2803          """
2804          if argvals.has_key(self):
2805             arg=argvals[self]
2806             if self.isAppropriateValue(arg):
2807                return arg
2808             else:
2809                raise TypeError,"%s: new value is not appropriate."%str(self)
2810          else:
2811             arg=self.getSubstitutedArguments(argvals)[0]
2812             return atanh(arg)
2813    
2814       def diff(self,arg):
2815          """
2816          Differential of this object.
2817    
2818          @param arg: the derivative is calculated with respect to C{arg}
2819          @type arg: L{escript.Symbol}
2820          @return: derivative with respect to C{arg}
2821          @rtype: typically L{Symbol} but other types such as C{float},
2822                  L{escript.Data}, C{numarray.NumArray} are possible
2823          """
2824          if arg==self:
2825             return identity(self.getShape())
2826          else:
2827             myarg=self.getArgument()[0]
2828             val=matchShape(1./(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2829             return val[0]*val[1]
2830    
2831    def exp(arg):
2832       """
2833       Returns M{e} to the power of argument C{arg}.
2834    
2835       @param arg: argument
2836       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
2837       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2838               on the type of arg
2839       @raises TypeError: if the type of the argument is not expected
2840       """
2841       if isinstance(arg,numarray.NumArray):
2842          return numarray.exp(arg)
2843       elif isinstance(arg,escript.Data):
2844          return arg._exp()
2845       elif isinstance(arg,float):
2846          return math.exp(arg)
2847       elif isinstance(arg,int):
2848          return math.exp(arg)
2849       elif isinstance(arg,Symbol):
2850          return Exp_Symbol(arg)
2851       else:
2852          raise TypeError,"exp: Unknown argument type."
2853    
2854    class Exp_Symbol(DependendSymbol):
2855       """
2856       L{Symbol} representing the result of the exponential function.
2857       """
2858       def __init__(self,arg):
2859          """
2860          Initialization of exp L{Symbol} with argument C{arg}.
2861    
2862          @param arg: argument of function
2863          @type arg: typically L{Symbol}
2864          """
2865          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2866    
2867       def getMyCode(self,argstrs,format="escript"):
2868          """
2869          Returns program code that can be used to evaluate the symbol.
2870    
2871          @param argstrs: a string for each argument representing the argument
2872                          for the evaluation
2873          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2874          @param format: specifies the format to be used. At the moment only
2875                         "escript", "str" and "text" are supported.
2876          @type format: C{str}
2877          @return: a piece of program code which can be used to evaluate the
2878                   expression assuming the values for the arguments are available
2879          @rtype: C{str}
2880          @raise NotImplementedError: if no implementation for the given format
2881                                      is available
2882          """
2883          if isinstance(argstrs,list):
2884              argstrs=argstrs[0]
2885          if format=="escript" or format=="str"  or format=="text":
2886             return "exp(%s)"%argstrs
2887          else:
2888             raise NotImplementedError,"Exp_Symbol does not provide program code for format %s."%format
2889    
2890       def substitute(self,argvals):
2891          """
2892          Assigns new values to symbols in the definition of the symbol.
2893          The method replaces the L{Symbol} u by argvals[u] in the expression
2894          defining this object.
2895    
2896          @param argvals: new values assigned to symbols
2897          @type argvals: C{dict} with keywords of type L{Symbol}
2898          @return: result of the substitution process. Operations are executed as
2899                   much as possible.
2900          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2901                  depending on the degree of substitution
2902          @raise TypeError: if a value for a L{Symbol} cannot be substituted
2903          """
2904          if argvals.has_key(self):
2905             arg=argvals[self]
2906             if self.isAppropriateValue(arg):
2907                return arg
2908             else:
2909                raise TypeError,"%s: new value is not appropriate."%str(self)
2910          else:
2911             arg=self.getSubstitutedArguments(argvals)[0]
2912             return exp(arg)
2913    
2914       def diff(self,arg):
2915          """
2916          Differential of this object.
2917    
2918          @param arg: the derivative is calculated with respect to C{arg}
2919          @type arg: L{escript.Symbol}
2920          @return: derivative with respect to C{arg}
2921          @rtype: typically L{Symbol} but other types such as C{float},
2922                  L{escript.Data}, C{numarray.NumArray} are possible
2923          """
2924          if arg==self:
2925             return identity(self.getShape())
2926          else:
2927             myarg=self.getArgument()[0]
2928             val=matchShape(self,self.getDifferentiatedArguments(arg)[0])
2929             return val[0]*val[1]
2930    
2931    def sqrt(arg):
2932       """
2933       Returns the square root of argument C{arg}.
2934    
2935       @param arg: argument
2936       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2937       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2938               depending on the type of C{arg}
2939       @raises TypeError: if the type of the argument is not expected
2940       """
2941       if isinstance(arg,numarray.NumArray):
2942          return numarray.sqrt(arg)
2943       elif isinstance(arg,escript.Data):
2944          return arg._sqrt()
2945       elif isinstance(arg,float):
2946          return math.sqrt(arg)
2947       elif isinstance(arg,int):
2948          return math.sqrt(arg)
2949       elif isinstance(arg,Symbol):
2950          return Sqrt_Symbol(arg)
2951       else:
2952          raise TypeError,"sqrt: Unknown argument type."
2953    
2954    class Sqrt_Symbol(DependendSymbol):
2955       """
2956       L{Symbol} representing the result of the square root function.
2957       """
2958       def __init__(self,arg):
2959          """
2960          Initialization of sqrt L{Symbol} with argument C{arg}.
2961    
2962          @param arg: argument of function
2963          @type arg: typically L{Symbol}
2964          """
2965          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2966    
2967       def getMyCode(self,argstrs,format="escript"):
2968          """
2969          Returns program code that can be used to evaluate the symbol.
2970    
2971          @param argstrs: a string for each argument representing the argument
2972                          for the evaluation
2973          @type argstrs: C{str} or a C{list} of length 1 of C{str}
2974          @param format: specifies the format to be used. At the moment only
2975                         "escript", "str" and "text" are supported.
2976          @type format: C{str}
2977          @return: a piece of program code which can be used to evaluate the
2978                   expression assuming the values for the arguments are available
2979          @rtype: C{str}
2980          @raise NotImplementedError: if no implementation for the given format
2981                                      is available
2982          """
2983          if isinstance(argstrs,list):
2984              argstrs=argstrs[0]
2985          if format=="escript" or format=="str"  or format=="text":
2986             return "sqrt(%s)"%argstrs
2987          else:
2988             raise NotImplementedError,"Sqrt_Symbol does not provide program code for format %s."%format
2989    
2990       def substitute(self,argvals):
2991          """
2992          Assigns new values to symbols in the definition of the symbol.
2993          The method replaces the L{Symbol} u by argvals[u] in the expression
2994          defining this object.
2995    
2996          @param argvals: new values assigned to symbols
2997          @type argvals: C{dict} with keywords of type L{Symbol}
2998          @return: result of the substitution process. Operations are executed as
2999                   much as possible.
3000          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
3001                  depending on the degree of substitution
3002          @raise TypeError: if a value for a L{Symbol} cannot be substituted
3003          """
3004          if argvals.has_key(self):
3005             arg=argvals[self]
3006             if self.isAppropriateValue(arg):
3007                return arg
3008             else:
3009                raise TypeError,"%s: new value is not appropriate."%str(self)
3010          else:
3011             arg=self.getSubstitutedArguments(argvals)[0]
3012             return sqrt(arg)
3013    
3014       def diff(self,arg):
3015          """
3016          Differential of this object.
3017    
3018          @param arg: the derivative is calculated with respect to C{arg}
3019          @type arg: L{escript.Symbol}
3020          @return: derivative with respect to C{arg}
3021          @rtype: typically L{Symbol} but other types such as C{float},
3022                  L{escript.Data}, C{numarray.NumArray} are possible
3023          """
3024          if arg==self:
3025             return identity(self.getShape())
3026          else:
3027             myarg=self.getArgument()[0]
3028             val=matchShape(0.5/self,self.getDifferentiatedArguments(arg)[0])
3029             return val[0]*val[1]
3030    
3031    def log(arg):
3032       """
3033       Returns the natural logarithm of argument C{arg}.
3034    
3035       @param arg: argument
3036       @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
3037       @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
3038               on the type of C{arg}
3039       @raises TypeError: if the type of the argument is not expected
3040       """
3041       if isinstance(arg,numarray.NumArray):
3042          return numarray.log(arg)
3043       elif isinstance(arg,escript.Data):
3044          return arg._log()
3045       elif isinstance(arg,float):
3046          return math.log(arg)
3047       elif isinstance(arg,int):
3048          return math.log(arg)
3049       elif isinstance(arg,Symbol):
3050          return Log_Symbol(arg)
3051       else:
3052          raise TypeError,"log: Unknown argument type."
3053    
3054    class Log_Symbol(DependendSymbol):
3055       """
3056       L{Symbol} representing the result of the natural logarithm function.
3057       """
3058       def __init__(self,arg):
3059          """
3060          Initialization of log L{Symbol} with argument C{arg}.
3061    
3062          @param arg: argument of function
3063          @type arg: typically L{Symbol}
3064          """
3065          DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
3066    
3067       def getMyCode(self,argstrs,format="escript"):
3068          """
3069          Returns program code that can be used to evaluate the symbol.
3070    
3071          @param argstrs: a string for each argument representing the argument
3072                          for the evaluation
3073          @type argstrs: C{str} or a C{list} of length 1 of C{str}
3074          @param format: specifies the format to be used. At the moment only
3075                         "escript", "str" and "text" are supported.
3076          @type format: C{str}
3077          @return: a piece of program code which can be used to evaluate the
3078                   expression assuming the values for the arguments are available
3079          @rtype: C{str}
3080          @raise NotImplementedError: if no implementation for the given format
3081                                      is available
3082          """
3083          if isinstance(argstrs,list):
3084              argstrs=argstrs[0]
3085          if format=="escript" or format=="str"  or format=="text":
3086             return "log(%s)"%argstrs
3087          else:
3088             raise NotImplementedError,"Log_Symbol does not provide program code for format %s."%format
3089    
3090       def substitute(self,argvals):
3091          """
3092          Assigns new values to symbols in the definition of the symbol.
3093          The method replaces the L{Symbol} u by argvals[u] in the expression
3094          defining this object.
3095    
3096          @param argvals: new values assigned to symbols
3097          @type argvals: C{dict} with keywords of type L{Symbol}
3098          @return: result of the substitution process. Operations are executed as
3099                   much as possible.
3100          @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
3101                  depending on the degree of substitution
3102          @raise TypeError: if a value for a L{Symbol} cannot be substituted
3103          """
3104          if argvals.has_key(self):
3105             arg=argvals[self]
3106             if self.isAppropriateValue(arg):
3107                return arg
3108             else:
3109                raise TypeError,"%s: new value is not appropriate."%str(self)
3110          else:
3111             arg=self.getSubstitutedArguments(argvals)[0]