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