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