/[escript]/trunk-mpi-branch/escript/py_src/util.py
ViewVC logotype

Contents of /trunk-mpi-branch/escript/py_src/util.py

Parent Directory Parent Directory | Revision Log Revision Log


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