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