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