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

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

Parent Directory Parent Directory | Revision Log Revision Log


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