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