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