/[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 2100 - (show annotations)
Wed Nov 26 08:13:00 2008 UTC (11 years ago) by gross
File MIME type: text/x-python
File size: 210560 byte(s)
This commit cleans up the incompressible solver and adds a DarcyFlux solver in model module. 
Some documentation for both classes has been added.
The convection code is only linear at the moment.



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