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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2259 - (show annotations)
Tue Feb 10 01:49:44 2009 UTC (10 years, 7 months ago) by jfenwick
File MIME type: text/x-python
File size: 224160 byte(s)
Fixes errors due to feeding scalars and vectors into the same call to maximum.

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