/[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 876 - (show annotations)
Thu Oct 19 03:50:23 2006 UTC (13 years ago) by ksteube
File MIME type: text/x-python
File size: 210747 byte(s)
Added erf (error function) implementation

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