/[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 1247 - (show annotations)
Tue Aug 14 01:29:20 2007 UTC (12 years, 6 months ago) by ksteube
File MIME type: text/x-python
File size: 212759 byte(s)
New python method getVersion() which returns the Subversion revision
from which escript was compiled

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