/[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 912 - (show annotations)
Wed Dec 6 03:29:49 2006 UTC (12 years, 10 months ago) by gross
File MIME type: text/x-python
File size: 211633 byte(s)
modellib.WriteVTK has been rewritten. Instead of only three data objects scalar,
vector, tensor it takes now up to 20 data objects data0 ... data19 and writes it into a 
single VTK file. There is also the possibilty to define individiual name tags name0,..., name19.
If no name is given the corresponding attribute name of the Link target is used. 
This simplifies the usage and increases efficiency.



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