/[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 608 - (show annotations)
Tue Mar 21 09:46:06 2006 UTC (13 years, 6 months ago) by elspeth
Original Path: trunk/escript/py_src/util.py
File MIME type: text/x-python
File size: 194470 byte(s)
moved "import numarray.linear_algebra" to function that uses it, in case it is not installed

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