/[escript]/trunk/escript/py_src/util.py
ViewVC logotype

Contents of /trunk/escript/py_src/util.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 813 - (show annotations)
Mon Aug 21 02:08:47 2006 UTC (13 years, 1 month ago) by ksteube
File MIME type: text/x-python
File size: 210300 byte(s)
Tensor products for Data objects are now computed by a C++ method
C_GeneralTensorProduct, which calls C function matrix_matrix_product
to do the actual calculation.

Can perform product with either input transposed in place, meaning
without first computing the transpose in a separate step.

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