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