/[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 1042 - (show annotations)
Mon Mar 19 03:50:34 2007 UTC (12 years, 6 months ago) by gross
File MIME type: text/x-python
File size: 211963 byte(s)
a small fix which deals with the case that a Model class
does not take the argument debug.



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