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