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