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