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