/[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 2142 - (show annotations)
Tue Dec 9 06:22:57 2008 UTC (12 years, 2 months ago) by jfenwick
File MIME type: text/x-python
File size: 210784 byte(s)
Added showEscriptParams to output a list of available params.

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