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