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