/[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 1809 - (show annotations)
Thu Sep 25 06:43:44 2008 UTC (10 years, 11 months ago) by ksteube
File MIME type: text/x-python
File size: 210377 byte(s)
Copyright updated in all python files

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