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