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