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

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

Parent Directory Parent Directory | Revision Log Revision Log


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