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

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

Parent Directory Parent Directory | Revision Log Revision Log


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