/[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 2300 - (show annotations)
Wed Mar 11 08:17:57 2009 UTC (10 years, 7 months ago) by gross
File MIME type: text/x-python
File size: 224790 byte(s)
a power law model. tests still need to be added and needs to be linked with an incompressible solver.
1
2 ########################################################
3 #
4 # Copyright (c) 2003-2008 by University of Queensland
5 # Earth Systems Science Computational Center (ESSCC)
6 # http://www.uq.edu.au/esscc
7 #
8 # Primary Business: Queensland, Australia
9 # Licensed under the Open Software License version 3.0
10 # http://www.opensource.org/licenses/osl-3.0.php
11 #
12 ########################################################
13
14 __copyright__="""Copyright (c) 2003-2008 by University of Queensland
15 Earth Systems Science Computational Center (ESSCC)
16 http://www.uq.edu.au/esscc
17 Primary Business: Queensland, Australia"""
18 __license__="""Licensed under the Open Software License version 3.0
19 http://www.opensource.org/licenses/osl-3.0.php"""
20 __url__="http://www.uq.edu.au/esscc/escript-finley"
21
22 """
23 Utility functions for escript
24
25 @var __author__: name of author
26 @var __copyright__: copyrights
27 @var __license__: licence agreement
28 @var __url__: url entry point on documentation
29 @var __version__: version
30 @var __date__: date of the version
31 @var EPSILON: smallest positive value with 1.<1.+EPSILON
32 @var DBLE_MAX: largest positive float
33 """
34
35 __author__="Lutz Gross, l.gross@uq.edu.au"
36
37
38 import math
39 import numarray
40 import escript
41 import os
42 from esys.escript import C_GeneralTensorProduct
43 from esys.escript import getVersion
44 from esys.escript import printParallelThreadCounts
45 from esys.escript import listEscriptParams
46
47 #=========================================================
48 # some helpers:
49 #=========================================================
50 def getEpsilon():
51 return escript.getMachinePrecision()
52 EPSILON=getEpsilon()
53
54 def getMaxFloat():
55 return escript.getMaxFloat()
56 DBLE_MAX=getMaxFloat()
57
58 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=0.):
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: tolerance. Values with absolute value less than tol are accepted
1500 as zero.
1501 @type tol: C{float}
1502 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1503 on the type of C{arg}
1504 @raises TypeError: if the type of the argument is not expected
1505 """
1506 if isinstance(arg,numarray.NumArray):
1507 out=numarray.less_equal(abs(arg)-tol,numarray.zeros(arg.shape,numarray.Float64))*1.
1508 if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1509 return out
1510 elif isinstance(arg,escript.Data):
1511 return arg._whereZero(tol)
1512 elif isinstance(arg,float):
1513 if abs(arg)<=tol:
1514 return 1.
1515 else:
1516 return 0.
1517 elif isinstance(arg,int):
1518 if abs(float(arg))<=tol:
1519 return 1.
1520 else:
1521 return 0.
1522 elif isinstance(arg,Symbol):
1523 return WhereZero_Symbol(arg,tol)
1524 else:
1525 raise TypeError,"whereZero: Unknown argument type."
1526
1527 class WhereZero_Symbol(DependendSymbol):
1528 """
1529 L{Symbol} representing the result of the mask of zero entries function.
1530 """
1531 def __init__(self,arg,tol=0.):
1532 """
1533 Initialization of whereZero L{Symbol} with argument C{arg}.
1534
1535 @param arg: argument of function
1536 @type arg: typically L{Symbol}
1537 """
1538 DependendSymbol.__init__(self,args=[arg,tol],shape=arg.getShape(),dim=arg.getDim())
1539
1540 def getMyCode(self,argstrs,format="escript"):
1541 """
1542 Returns program code that can be used to evaluate the symbol.
1543
1544 @param argstrs: a string for each argument representing the argument
1545 for the evaluation
1546 @type argstrs: C{str} or a C{list} of length 1 of C{str}
1547 @param format: specifies the format to be used. At the moment only
1548 "escript", "str" and "text" are supported.
1549 @type format: C{str}
1550 @return: a piece of program code which can be used to evaluate the
1551 expression assuming the values for the arguments are available
1552 @rtype: C{str}
1553 @raise NotImplementedError: if no implementation for the given format
1554 is available
1555 """
1556 if format=="escript" or format=="str" or format=="text":
1557 return "whereZero(%s,tol=%s)"%(argstrs[0],argstrs[1])
1558 else:
1559 raise NotImplementedError,"WhereZero_Symbol does not provide program code for format %s."%format
1560
1561 def substitute(self,argvals):
1562 """
1563 Assigns new values to symbols in the definition of the symbol.
1564 The method replaces the L{Symbol} u by argvals[u] in the expression
1565 defining this object.
1566
1567 @param argvals: new values assigned to symbols
1568 @type argvals: C{dict} with keywords of type L{Symbol}
1569 @return: result of the substitution process. Operations are executed as
1570 much as possible.
1571 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
1572 depending on the degree of substitution
1573 @raise TypeError: if a value for a L{Symbol} cannot be substituted
1574 """
1575 if argvals.has_key(self):
1576 arg=argvals[self]
1577 if self.isAppropriateValue(arg):
1578 return arg
1579 else:
1580 raise TypeError,"%s: new value is not appropriate."%str(self)
1581 else:
1582 arg=self.getSubstitutedArguments(argvals)
1583 return whereZero(arg[0],arg[1])
1584
1585 def whereNonZero(arg,tol=0.):
1586 """
1587 Returns mask of values different from zero of argument C{arg}.
1588
1589 @param arg: argument
1590 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
1591 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1592 on the type of C{arg}
1593 @raise TypeError: if the type of the argument is not expected
1594 """
1595 if isinstance(arg,numarray.NumArray):
1596 out=numarray.greater(abs(arg)-tol,numarray.zeros(arg.shape,numarray.Float64))*1.
1597 if isinstance(out,float): out=numarray.array(out,type=numarray.Float64)
1598 return out
1599 elif isinstance(arg,escript.Data):
1600 return arg._whereNonZero(tol)
1601 elif isinstance(arg,float):
1602 if abs(arg)>tol:
1603 return 1.
1604 else:
1605 return 0.
1606 elif isinstance(arg,int):
1607 if abs(float(arg))>tol:
1608 return 1.
1609 else:
1610 return 0.
1611 elif isinstance(arg,Symbol):
1612 return 1.-whereZero(arg,tol)
1613 else:
1614 raise TypeError,"whereNonZero: Unknown argument type."
1615
1616 def erf(arg):
1617 """
1618 Returns the error function M{erf} of argument C{arg}.
1619
1620 @param arg: argument
1621 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
1622 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1623 on the type of C{arg}
1624 @raise TypeError: if the type of the argument is not expected
1625 """
1626 if isinstance(arg,escript.Data):
1627 return arg._erf()
1628 else:
1629 raise TypeError,"erf: Unknown argument type."
1630
1631 def sin(arg):
1632 """
1633 Returns sine of argument C{arg}.
1634
1635 @param arg: argument
1636 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
1637 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1638 on the type of C{arg}
1639 @raise TypeError: if the type of the argument is not expected
1640 """
1641 if isinstance(arg,numarray.NumArray):
1642 return numarray.sin(arg)
1643 elif isinstance(arg,escript.Data):
1644 return arg._sin()
1645 elif isinstance(arg,float):
1646 return math.sin(arg)
1647 elif isinstance(arg,int):
1648 return math.sin(arg)
1649 elif isinstance(arg,Symbol):
1650 return Sin_Symbol(arg)
1651 else:
1652 raise TypeError,"sin: Unknown argument type."
1653
1654 class Sin_Symbol(DependendSymbol):
1655 """
1656 L{Symbol} representing the result of the sine function.
1657 """
1658 def __init__(self,arg):
1659 """
1660 Initialization of sin L{Symbol} with argument C{arg}.
1661
1662 @param arg: argument of function
1663 @type arg: typically L{Symbol}
1664 """
1665 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1666
1667 def getMyCode(self,argstrs,format="escript"):
1668 """
1669 Returns program code that can be used to evaluate the symbol.
1670
1671 @param argstrs: a string for each argument representing the argument
1672 for the evaluation
1673 @type argstrs: C{str} or a C{list} of length 1 of C{str}
1674 @param format: specifies the format to be used. At the moment only
1675 "escript", "str" and "text" are supported.
1676 @type format: C{str}
1677 @return: a piece of program code which can be used to evaluate the
1678 expression assuming the values for the arguments are available
1679 @rtype: C{str}
1680 @raise NotImplementedError: if no implementation for the given format
1681 is available
1682 """
1683 if isinstance(argstrs,list):
1684 argstrs=argstrs[0]
1685 if format=="escript" or format=="str" or format=="text":
1686 return "sin(%s)"%argstrs
1687 else:
1688 raise NotImplementedError,"Sin_Symbol does not provide program code for format %s."%format
1689
1690 def substitute(self,argvals):
1691 """
1692 Assigns new values to symbols in the definition of the symbol.
1693 The method replaces the L{Symbol} u by argvals[u] in the expression
1694 defining this object.
1695
1696 @param argvals: new values assigned to symbols
1697 @type argvals: C{dict} with keywords of type L{Symbol}
1698 @return: result of the substitution process. Operations are executed as
1699 much as possible.
1700 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
1701 depending on the degree of substitution
1702 @raise TypeError: if a value for a L{Symbol} cannot be substituted
1703 """
1704 if argvals.has_key(self):
1705 arg=argvals[self]
1706 if self.isAppropriateValue(arg):
1707 return arg
1708 else:
1709 raise TypeError,"%s: new value is not appropriate."%str(self)
1710 else:
1711 arg=self.getSubstitutedArguments(argvals)[0]
1712 return sin(arg)
1713
1714 def diff(self,arg):
1715 """
1716 Differential of this object.
1717
1718 @param arg: the derivative is calculated with respect to C{arg}
1719 @type arg: L{escript.Symbol}
1720 @return: derivative with respect to C{arg}
1721 @rtype: typically L{Symbol} but other types such as C{float},
1722 L{escript.Data}, C{numarray.NumArray} are possible
1723 """
1724 if arg==self:
1725 return identity(self.getShape())
1726 else:
1727 myarg=self.getArgument()[0]
1728 val=matchShape(cos(myarg),self.getDifferentiatedArguments(arg)[0])
1729 return val[0]*val[1]
1730
1731 def cos(arg):
1732 """
1733 Returns cosine of argument C{arg}.
1734
1735 @param arg: argument
1736 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
1737 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1738 on the type of C{arg}
1739 @raises TypeError: if the type of the argument is not expected
1740 """
1741 if isinstance(arg,numarray.NumArray):
1742 return numarray.cos(arg)
1743 elif isinstance(arg,escript.Data):
1744 return arg._cos()
1745 elif isinstance(arg,float):
1746 return math.cos(arg)
1747 elif isinstance(arg,int):
1748 return math.cos(arg)
1749 elif isinstance(arg,Symbol):
1750 return Cos_Symbol(arg)
1751 else:
1752 raise TypeError,"cos: Unknown argument type."
1753
1754 class Cos_Symbol(DependendSymbol):
1755 """
1756 L{Symbol} representing the result of the cosine function.
1757 """
1758 def __init__(self,arg):
1759 """
1760 Initialization of cos L{Symbol} with argument C{arg}.
1761
1762 @param arg: argument of function
1763 @type arg: typically L{Symbol}
1764 """
1765 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1766
1767 def getMyCode(self,argstrs,format="escript"):
1768 """
1769 Returns program code that can be used to evaluate the symbol.
1770
1771 @param argstrs: a string for each argument representing the argument
1772 for the evaluation
1773 @type argstrs: C{str} or a C{list} of length 1 of C{str}
1774 @param format: specifies the format to be used. At the moment only
1775 "escript", "str" and "text" are supported.
1776 @type format: C{str}
1777 @return: a piece of program code which can be used to evaluate the
1778 expression assuming the values for the arguments are available
1779 @rtype: C{str}
1780 @raise NotImplementedError: if no implementation for the given format
1781 is available
1782 """
1783 if isinstance(argstrs,list):
1784 argstrs=argstrs[0]
1785 if format=="escript" or format=="str" or format=="text":
1786 return "cos(%s)"%argstrs
1787 else:
1788 raise NotImplementedError,"Cos_Symbol does not provide program code for format %s."%format
1789
1790 def substitute(self,argvals):
1791 """
1792 Assigns new values to symbols in the definition of the symbol.
1793 The method replaces the L{Symbol} u by argvals[u] in the expression
1794 defining this object.
1795
1796 @param argvals: new values assigned to symbols
1797 @type argvals: C{dict} with keywords of type L{Symbol}
1798 @return: result of the substitution process. Operations are executed as
1799 much as possible.
1800 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
1801 depending on the degree of substitution
1802 @raise TypeError: if a value for a L{Symbol} cannot be substituted
1803 """
1804 if argvals.has_key(self):
1805 arg=argvals[self]
1806 if self.isAppropriateValue(arg):
1807 return arg
1808 else:
1809 raise TypeError,"%s: new value is not appropriate."%str(self)
1810 else:
1811 arg=self.getSubstitutedArguments(argvals)[0]
1812 return cos(arg)
1813
1814 def diff(self,arg):
1815 """
1816 Differential of this object.
1817
1818 @param arg: the derivative is calculated with respect to C{arg}
1819 @type arg: L{escript.Symbol}
1820 @return: derivative with respect to C{arg}
1821 @rtype: typically L{Symbol} but other types such as C{float},
1822 L{escript.Data}, C{numarray.NumArray} are possible
1823 """
1824 if arg==self:
1825 return identity(self.getShape())
1826 else:
1827 myarg=self.getArgument()[0]
1828 val=matchShape(-sin(myarg),self.getDifferentiatedArguments(arg)[0])
1829 return val[0]*val[1]
1830
1831 def tan(arg):
1832 """
1833 Returns tangent of argument C{arg}.
1834
1835 @param arg: argument
1836 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
1837 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1838 on the type of C{arg}
1839 @raises TypeError: if the type of the argument is not expected
1840 """
1841 if isinstance(arg,numarray.NumArray):
1842 return numarray.tan(arg)
1843 elif isinstance(arg,escript.Data):
1844 return arg._tan()
1845 elif isinstance(arg,float):
1846 return math.tan(arg)
1847 elif isinstance(arg,int):
1848 return math.tan(arg)
1849 elif isinstance(arg,Symbol):
1850 return Tan_Symbol(arg)
1851 else:
1852 raise TypeError,"tan: Unknown argument type."
1853
1854 class Tan_Symbol(DependendSymbol):
1855 """
1856 L{Symbol} representing the result of the tangent function.
1857 """
1858 def __init__(self,arg):
1859 """
1860 Initialization of tan L{Symbol} with argument C{arg}.
1861
1862 @param arg: argument of function
1863 @type arg: typically L{Symbol}
1864 """
1865 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1866
1867 def getMyCode(self,argstrs,format="escript"):
1868 """
1869 Returns program code that can be used to evaluate the symbol.
1870
1871 @param argstrs: a string for each argument representing the argument
1872 for the evaluation
1873 @type argstrs: C{str} or a C{list} of length 1 of C{str}
1874 @param format: specifies the format to be used. At the moment only
1875 "escript", "str" and "text" are supported.
1876 @type format: C{str}
1877 @return: a piece of program code which can be used to evaluate the
1878 expression assuming the values for the arguments are available
1879 @rtype: C{str}
1880 @raise NotImplementedError: if no implementation for the given format
1881 is available
1882 """
1883 if isinstance(argstrs,list):
1884 argstrs=argstrs[0]
1885 if format=="escript" or format=="str" or format=="text":
1886 return "tan(%s)"%argstrs
1887 else:
1888 raise NotImplementedError,"Tan_Symbol does not provide program code for format %s."%format
1889
1890 def substitute(self,argvals):
1891 """
1892 Assigns new values to symbols in the definition of the symbol.
1893 The method replaces the L{Symbol} u by argvals[u] in the expression
1894 defining this object.
1895
1896 @param argvals: new values assigned to symbols
1897 @type argvals: C{dict} with keywords of type L{Symbol}
1898 @return: result of the substitution process. Operations are executed as
1899 much as possible.
1900 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
1901 depending on the degree of substitution
1902 @raise TypeError: if a value for a L{Symbol} cannot be substituted
1903 """
1904 if argvals.has_key(self):
1905 arg=argvals[self]
1906 if self.isAppropriateValue(arg):
1907 return arg
1908 else:
1909 raise TypeError,"%s: new value is not appropriate."%str(self)
1910 else:
1911 arg=self.getSubstitutedArguments(argvals)[0]
1912 return tan(arg)
1913
1914 def diff(self,arg):
1915 """
1916 Differential of this object.
1917
1918 @param arg: the derivative is calculated with respect to C{arg}
1919 @type arg: L{escript.Symbol}
1920 @return: derivative with respect to C{arg}
1921 @rtype: typically L{Symbol} but other types such as C{float},
1922 L{escript.Data}, C{numarray.NumArray} are possible
1923 """
1924 if arg==self:
1925 return identity(self.getShape())
1926 else:
1927 myarg=self.getArgument()[0]
1928 val=matchShape(1./cos(myarg)**2,self.getDifferentiatedArguments(arg)[0])
1929 return val[0]*val[1]
1930
1931 def asin(arg):
1932 """
1933 Returns the inverse sine of argument C{arg}.
1934
1935 @param arg: argument
1936 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
1937 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
1938 on the type of C{arg}
1939 @raises TypeError: if the type of the argument is not expected
1940 """
1941 if isinstance(arg,numarray.NumArray):
1942 return numarray.arcsin(arg)
1943 elif isinstance(arg,escript.Data):
1944 return arg._asin()
1945 elif isinstance(arg,float):
1946 return math.asin(arg)
1947 elif isinstance(arg,int):
1948 return math.asin(arg)
1949 elif isinstance(arg,Symbol):
1950 return Asin_Symbol(arg)
1951 else:
1952 raise TypeError,"asin: Unknown argument type."
1953
1954 class Asin_Symbol(DependendSymbol):
1955 """
1956 L{Symbol} representing the result of the inverse sine function.
1957 """
1958 def __init__(self,arg):
1959 """
1960 Initialization of asin L{Symbol} with argument C{arg}.
1961
1962 @param arg: argument of function
1963 @type arg: typically L{Symbol}
1964 """
1965 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1966
1967 def getMyCode(self,argstrs,format="escript"):
1968 """
1969 Returns program code that can be used to evaluate the symbol.
1970
1971 @param argstrs: a string for each argument representing the argument
1972 for the evaluation
1973 @type argstrs: C{str} or a C{list} of length 1 of C{str}
1974 @param format: specifies the format to be used. At the moment only
1975 "escript", "str" and "text" are supported.
1976 @type format: C{str}
1977 @return: a piece of program code which can be used to evaluate the
1978 expression assuming the values for the arguments are available
1979 @rtype: C{str}
1980 @raise NotImplementedError: if no implementation for the given format
1981 is available
1982 """
1983 if isinstance(argstrs,list):
1984 argstrs=argstrs[0]
1985 if format=="escript" or format=="str" or format=="text":
1986 return "asin(%s)"%argstrs
1987 else:
1988 raise NotImplementedError,"Asin_Symbol does not provide program code for format %s."%format
1989
1990 def substitute(self,argvals):
1991 """
1992 Assigns new values to symbols in the definition of the symbol.
1993 The method replaces the L{Symbol} u by argvals[u] in the expression
1994 defining this object.
1995
1996 @param argvals: new values assigned to symbols
1997 @type argvals: C{dict} with keywords of type L{Symbol}
1998 @return: result of the substitution process. Operations are executed as
1999 much as possible.
2000 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2001 depending on the degree of substitution
2002 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2003 """
2004 if argvals.has_key(self):
2005 arg=argvals[self]
2006 if self.isAppropriateValue(arg):
2007 return arg
2008 else:
2009 raise TypeError,"%s: new value is not appropriate."%str(self)
2010 else:
2011 arg=self.getSubstitutedArguments(argvals)[0]
2012 return asin(arg)
2013
2014 def diff(self,arg):
2015 """
2016 Differential of this object.
2017
2018 @param arg: the derivative is calculated with respect to C{arg}
2019 @type arg: L{escript.Symbol}
2020 @return: derivative with respect to C{arg}
2021 @rtype: typically L{Symbol} but other types such as C{float},
2022 L{escript.Data}, C{numarray.NumArray} are possible
2023 """
2024 if arg==self:
2025 return identity(self.getShape())
2026 else:
2027 myarg=self.getArgument()[0]
2028 val=matchShape(1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2029 return val[0]*val[1]
2030
2031 def acos(arg):
2032 """
2033 Returns the inverse cosine of argument C{arg}.
2034
2035 @param arg: argument
2036 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2037 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2038 on the type of C{arg}
2039 @raises TypeError: if the type of the argument is not expected
2040 """
2041 if isinstance(arg,numarray.NumArray):
2042 return numarray.arccos(arg)
2043 elif isinstance(arg,escript.Data):
2044 return arg._acos()
2045 elif isinstance(arg,float):
2046 return math.acos(arg)
2047 elif isinstance(arg,int):
2048 return math.acos(arg)
2049 elif isinstance(arg,Symbol):
2050 return Acos_Symbol(arg)
2051 else:
2052 raise TypeError,"acos: Unknown argument type."
2053
2054 class Acos_Symbol(DependendSymbol):
2055 """
2056 L{Symbol} representing the result of the inverse cosine function.
2057 """
2058 def __init__(self,arg):
2059 """
2060 Initialization of acos L{Symbol} with argument C{arg}.
2061
2062 @param arg: argument of function
2063 @type arg: typically L{Symbol}
2064 """
2065 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2066
2067 def getMyCode(self,argstrs,format="escript"):
2068 """
2069 Returns program code that can be used to evaluate the symbol.
2070
2071 @param argstrs: a string for each argument representing the argument
2072 for the evaluation
2073 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2074 @param format: specifies the format to be used. At the moment only
2075 "escript", "str" and "text" are supported.
2076 @type format: C{str}
2077 @return: a piece of program code which can be used to evaluate the
2078 expression assuming the values for the arguments are available
2079 @rtype: C{str}
2080 @raise NotImplementedError: if no implementation for the given format
2081 is available
2082 """
2083 if isinstance(argstrs,list):
2084 argstrs=argstrs[0]
2085 if format=="escript" or format=="str" or format=="text":
2086 return "acos(%s)"%argstrs
2087 else:
2088 raise NotImplementedError,"Acos_Symbol does not provide program code for format %s."%format
2089
2090 def substitute(self,argvals):
2091 """
2092 Assigns new values to symbols in the definition of the symbol.
2093 The method replaces the L{Symbol} u by argvals[u] in the expression
2094 defining this object.
2095
2096 @param argvals: new values assigned to symbols
2097 @type argvals: C{dict} with keywords of type L{Symbol}
2098 @return: result of the substitution process. Operations are executed as
2099 much as possible.
2100 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2101 depending on the degree of substitution
2102 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2103 """
2104 if argvals.has_key(self):
2105 arg=argvals[self]
2106 if self.isAppropriateValue(arg):
2107 return arg
2108 else:
2109 raise TypeError,"%s: new value is not appropriate."%str(self)
2110 else:
2111 arg=self.getSubstitutedArguments(argvals)[0]
2112 return acos(arg)
2113
2114 def diff(self,arg):
2115 """
2116 Differential of this object.
2117
2118 @param arg: the derivative is calculated with respect to C{arg}
2119 @type arg: L{escript.Symbol}
2120 @return: derivative with respect to C{arg}
2121 @rtype: typically L{Symbol} but other types such as C{float},
2122 L{escript.Data}, C{numarray.NumArray} are possible
2123 """
2124 if arg==self:
2125 return identity(self.getShape())
2126 else:
2127 myarg=self.getArgument()[0]
2128 val=matchShape(-1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2129 return val[0]*val[1]
2130
2131 def atan(arg):
2132 """
2133 Returns inverse tangent of argument C{arg}.
2134
2135 @param arg: argument
2136 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2137 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2138 on the type of C{arg}
2139 @raises TypeError: if the type of the argument is not expected
2140 """
2141 if isinstance(arg,numarray.NumArray):
2142 return numarray.arctan(arg)
2143 elif isinstance(arg,escript.Data):
2144 return arg._atan()
2145 elif isinstance(arg,float):
2146 return math.atan(arg)
2147 elif isinstance(arg,int):
2148 return math.atan(arg)
2149 elif isinstance(arg,Symbol):
2150 return Atan_Symbol(arg)
2151 else:
2152 raise TypeError,"atan: Unknown argument type."
2153
2154 class Atan_Symbol(DependendSymbol):
2155 """
2156 L{Symbol} representing the result of the inverse tangent function.
2157 """
2158 def __init__(self,arg):
2159 """
2160 Initialization of atan L{Symbol} with argument C{arg}.
2161
2162 @param arg: argument of function
2163 @type arg: typically L{Symbol}
2164 """
2165 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2166
2167 def getMyCode(self,argstrs,format="escript"):
2168 """
2169 Returns program code that can be used to evaluate the symbol.
2170
2171 @param argstrs: a string for each argument representing the argument
2172 for the evaluation
2173 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2174 @param format: specifies the format to be used. At the moment only
2175 "escript", "str" and "text" are supported.
2176 @type format: C{str}
2177 @return: a piece of program code which can be used to evaluate the
2178 expression assuming the values for the arguments are available
2179 @rtype: C{str}
2180 @raise NotImplementedError: if no implementation for the given format
2181 is available
2182 """
2183 if isinstance(argstrs,list):
2184 argstrs=argstrs[0]
2185 if format=="escript" or format=="str" or format=="text":
2186 return "atan(%s)"%argstrs
2187 else:
2188 raise NotImplementedError,"Atan_Symbol does not provide program code for format %s."%format
2189
2190 def substitute(self,argvals):
2191 """
2192 Assigns new values to symbols in the definition of the symbol.
2193 The method replaces the L{Symbol} u by argvals[u] in the expression
2194 defining this object.
2195
2196 @param argvals: new values assigned to symbols
2197 @type argvals: C{dict} with keywords of type L{Symbol}
2198 @return: result of the substitution process. Operations are executed as
2199 much as possible.
2200 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2201 depending on the degree of substitution
2202 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2203 """
2204 if argvals.has_key(self):
2205 arg=argvals[self]
2206 if self.isAppropriateValue(arg):
2207 return arg
2208 else:
2209 raise TypeError,"%s: new value is not appropriate."%str(self)
2210 else:
2211 arg=self.getSubstitutedArguments(argvals)[0]
2212 return atan(arg)
2213
2214 def diff(self,arg):
2215 """
2216 Differential of this object.
2217
2218 @param arg: the derivative is calculated with respect to C{arg}
2219 @type arg: L{escript.Symbol}
2220 @return: derivative with respect to C{arg}
2221 @rtype: typically L{Symbol} but other types such as C{float},
2222 L{escript.Data}, C{numarray.NumArray} are possible
2223 """
2224 if arg==self:
2225 return identity(self.getShape())
2226 else:
2227 myarg=self.getArgument()[0]
2228 val=matchShape(1./(1+myarg**2),self.getDifferentiatedArguments(arg)[0])
2229 return val[0]*val[1]
2230
2231 def sinh(arg):
2232 """
2233 Returns the hyperbolic sine of argument C{arg}.
2234
2235 @param arg: argument
2236 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2237 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2238 on the type of C{arg}
2239 @raises TypeError: if the type of the argument is not expected
2240 """
2241 if isinstance(arg,numarray.NumArray):
2242 return numarray.sinh(arg)
2243 elif isinstance(arg,escript.Data):
2244 return arg._sinh()
2245 elif isinstance(arg,float):
2246 return math.sinh(arg)
2247 elif isinstance(arg,int):
2248 return math.sinh(arg)
2249 elif isinstance(arg,Symbol):
2250 return Sinh_Symbol(arg)
2251 else:
2252 raise TypeError,"sinh: Unknown argument type."
2253
2254 class Sinh_Symbol(DependendSymbol):
2255 """
2256 L{Symbol} representing the result of the hyperbolic sine function.
2257 """
2258 def __init__(self,arg):
2259 """
2260 Initialization of sinh L{Symbol} with argument C{arg}.
2261
2262 @param arg: argument of function
2263 @type arg: typically L{Symbol}
2264 """
2265 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2266
2267 def getMyCode(self,argstrs,format="escript"):
2268 """
2269 Returns program code that can be used to evaluate the symbol.
2270
2271 @param argstrs: a string for each argument representing the argument
2272 for the evaluation
2273 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2274 @param format: specifies the format to be used. At the moment only
2275 "escript", "str" and "text" are supported.
2276 @type format: C{str}
2277 @return: a piece of program code which can be used to evaluate the
2278 expression assuming the values for the arguments are available
2279 @rtype: C{str}
2280 @raise NotImplementedError: if no implementation for the given format
2281 is available
2282 """
2283 if isinstance(argstrs,list):
2284 argstrs=argstrs[0]
2285 if format=="escript" or format=="str" or format=="text":
2286 return "sinh(%s)"%argstrs
2287 else:
2288 raise NotImplementedError,"Sinh_Symbol does not provide program code for format %s."%format
2289
2290 def substitute(self,argvals):
2291 """
2292 Assigns new values to symbols in the definition of the symbol.
2293 The method replaces the L{Symbol} u by argvals[u] in the expression
2294 defining this object.
2295
2296 @param argvals: new values assigned to symbols
2297 @type argvals: C{dict} with keywords of type L{Symbol}
2298 @return: result of the substitution process. Operations are executed as
2299 much as possible.
2300 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2301 depending on the degree of substitution
2302 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2303 """
2304 if argvals.has_key(self):
2305 arg=argvals[self]
2306 if self.isAppropriateValue(arg):
2307 return arg
2308 else:
2309 raise TypeError,"%s: new value is not appropriate."%str(self)
2310 else:
2311 arg=self.getSubstitutedArguments(argvals)[0]
2312 return sinh(arg)
2313
2314 def diff(self,arg):
2315 """
2316 Differential of this object.
2317
2318 @param arg: the derivative is calculated with respect to C{arg}
2319 @type arg: L{escript.Symbol}
2320 @return: derivative with respect to C{arg}
2321 @rtype: typically L{Symbol} but other types such as C{float},
2322 L{escript.Data}, C{numarray.NumArray} are possible
2323 """
2324 if arg==self:
2325 return identity(self.getShape())
2326 else:
2327 myarg=self.getArgument()[0]
2328 val=matchShape(cosh(myarg),self.getDifferentiatedArguments(arg)[0])
2329 return val[0]*val[1]
2330
2331 def cosh(arg):
2332 """
2333 Returns the hyperbolic cosine of argument C{arg}.
2334
2335 @param arg: argument
2336 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2337 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2338 on the type of C{arg}
2339 @raises TypeError: if the type of the argument is not expected
2340 """
2341 if isinstance(arg,numarray.NumArray):
2342 return numarray.cosh(arg)
2343 elif isinstance(arg,escript.Data):
2344 return arg._cosh()
2345 elif isinstance(arg,float):
2346 return math.cosh(arg)
2347 elif isinstance(arg,int):
2348 return math.cosh(arg)
2349 elif isinstance(arg,Symbol):
2350 return Cosh_Symbol(arg)
2351 else:
2352 raise TypeError,"cosh: Unknown argument type."
2353
2354 class Cosh_Symbol(DependendSymbol):
2355 """
2356 L{Symbol} representing the result of the hyperbolic cosine function.
2357 """
2358 def __init__(self,arg):
2359 """
2360 Initialization of cosh L{Symbol} with argument C{arg}.
2361
2362 @param arg: argument of function
2363 @type arg: typically L{Symbol}
2364 """
2365 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2366
2367 def getMyCode(self,argstrs,format="escript"):
2368 """
2369 Returns program code that can be used to evaluate the symbol.
2370
2371 @param argstrs: a string for each argument representing the argument
2372 for the evaluation
2373 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2374 @param format: specifies the format to be used. At the moment only
2375 "escript", "str" and "text" are supported.
2376 @type format: C{str}
2377 @return: a piece of program code which can be used to evaluate the
2378 expression assuming the values for the arguments are available
2379 @rtype: C{str}
2380 @raise NotImplementedError: if no implementation for the given format
2381 is available
2382 """
2383 if isinstance(argstrs,list):
2384 argstrs=argstrs[0]
2385 if format=="escript" or format=="str" or format=="text":
2386 return "cosh(%s)"%argstrs
2387 else:
2388 raise NotImplementedError,"Cosh_Symbol does not provide program code for format %s."%format
2389
2390 def substitute(self,argvals):
2391 """
2392 Assigns new values to symbols in the definition of the symbol.
2393 The method replaces the L{Symbol} u by argvals[u] in the expression
2394 defining this object.
2395
2396 @param argvals: new values assigned to symbols
2397 @type argvals: C{dict} with keywords of type L{Symbol}
2398 @return: result of the substitution process. Operations are executed as
2399 much as possible.
2400 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2401 depending on the degree of substitution
2402 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2403 """
2404 if argvals.has_key(self):
2405 arg=argvals[self]
2406 if self.isAppropriateValue(arg):
2407 return arg
2408 else:
2409 raise TypeError,"%s: new value is not appropriate."%str(self)
2410 else:
2411 arg=self.getSubstitutedArguments(argvals)[0]
2412 return cosh(arg)
2413
2414 def diff(self,arg):
2415 """
2416 Differential of this object.
2417
2418 @param arg: the derivative is calculated with respect to C{arg}
2419 @type arg: L{escript.Symbol}
2420 @return: derivative with respect to C{arg}
2421 @rtype: typically L{Symbol} but other types such as C{float},
2422 L{escript.Data}, C{numarray.NumArray} are possible
2423 """
2424 if arg==self:
2425 return identity(self.getShape())
2426 else:
2427 myarg=self.getArgument()[0]
2428 val=matchShape(sinh(myarg),self.getDifferentiatedArguments(arg)[0])
2429 return val[0]*val[1]
2430
2431 def tanh(arg):
2432 """
2433 Returns the hyperbolic tangent of argument C{arg}.
2434
2435 @param arg: argument
2436 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2437 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2438 on the type of C{arg}
2439 @raises TypeError: if the type of the argument is not expected
2440 """
2441 if isinstance(arg,numarray.NumArray):
2442 return numarray.tanh(arg)
2443 elif isinstance(arg,escript.Data):
2444 return arg._tanh()
2445 elif isinstance(arg,float):
2446 return math.tanh(arg)
2447 elif isinstance(arg,int):
2448 return math.tanh(arg)
2449 elif isinstance(arg,Symbol):
2450 return Tanh_Symbol(arg)
2451 else:
2452 raise TypeError,"tanh: Unknown argument type."
2453
2454 class Tanh_Symbol(DependendSymbol):
2455 """
2456 L{Symbol} representing the result of the hyperbolic tangent function.
2457 """
2458 def __init__(self,arg):
2459 """
2460 Initialization of tanh L{Symbol} with argument C{arg}.
2461
2462 @param arg: argument of function
2463 @type arg: typically L{Symbol}
2464 """
2465 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2466
2467 def getMyCode(self,argstrs,format="escript"):
2468 """
2469 Returns program code that can be used to evaluate the symbol.
2470
2471 @param argstrs: a string for each argument representing the argument
2472 for the evaluation
2473 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2474 @param format: specifies the format to be used. At the moment only
2475 "escript", "str" and "text" are supported.
2476 @type format: C{str}
2477 @return: a piece of program code which can be used to evaluate the
2478 expression assuming the values for the arguments are available
2479 @rtype: C{str}
2480 @raise NotImplementedError: if no implementation for the given format
2481 is available
2482 """
2483 if isinstance(argstrs,list):
2484 argstrs=argstrs[0]
2485 if format=="escript" or format=="str" or format=="text":
2486 return "tanh(%s)"%argstrs
2487 else:
2488 raise NotImplementedError,"Tanh_Symbol does not provide program code for format %s."%format
2489
2490 def substitute(self,argvals):
2491 """
2492 Assigns new values to symbols in the definition of the symbol.
2493 The method replaces the L{Symbol} u by argvals[u] in the expression
2494 defining this object.
2495
2496 @param argvals: new values assigned to symbols
2497 @type argvals: C{dict} with keywords of type L{Symbol}
2498 @return: result of the substitution process. Operations are executed as
2499 much as possible.
2500 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2501 depending on the degree of substitution
2502 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2503 """
2504 if argvals.has_key(self):
2505 arg=argvals[self]
2506 if self.isAppropriateValue(arg):
2507 return arg
2508 else:
2509 raise TypeError,"%s: new value is not appropriate."%str(self)
2510 else:
2511 arg=self.getSubstitutedArguments(argvals)[0]
2512 return tanh(arg)
2513
2514 def diff(self,arg):
2515 """
2516 Differential of this object.
2517
2518 @param arg: the derivative is calculated with respect to C{arg}
2519 @type arg: L{escript.Symbol}
2520 @return: derivative with respect to C{arg}
2521 @rtype: typically L{Symbol} but other types such as C{float},
2522 L{escript.Data}, C{numarray.NumArray} are possible
2523 """
2524 if arg==self:
2525 return identity(self.getShape())
2526 else:
2527 myarg=self.getArgument()[0]
2528 val=matchShape(1./cosh(myarg)**2,self.getDifferentiatedArguments(arg)[0])
2529 return val[0]*val[1]
2530
2531 def asinh(arg):
2532 """
2533 Returns the inverse hyperbolic sine of argument C{arg}.
2534
2535 @param arg: argument
2536 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2537 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2538 on the type of C{arg}
2539 @raises TypeError: if the type of the argument is not expected
2540 """
2541 if isinstance(arg,numarray.NumArray):
2542 return numarray.arcsinh(arg)
2543 elif isinstance(arg,escript.Data):
2544 return arg._asinh()
2545 elif isinstance(arg,float):
2546 return numarray.arcsinh(arg)
2547 elif isinstance(arg,int):
2548 return numarray.arcsinh(float(arg))
2549 elif isinstance(arg,Symbol):
2550 return Asinh_Symbol(arg)
2551 else:
2552 raise TypeError,"asinh: Unknown argument type."
2553
2554 class Asinh_Symbol(DependendSymbol):
2555 """
2556 L{Symbol} representing the result of the inverse hyperbolic sine function.
2557 """
2558 def __init__(self,arg):
2559 """
2560 Initialization of asinh L{Symbol} with argument C{arg}.
2561
2562 @param arg: argument of function
2563 @type arg: typically L{Symbol}
2564 """
2565 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2566
2567 def getMyCode(self,argstrs,format="escript"):
2568 """
2569 Returns program code that can be used to evaluate the symbol.
2570
2571 @param argstrs: a string for each argument representing the argument
2572 for the evaluation
2573 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2574 @param format: specifies the format to be used. At the moment only
2575 "escript", "str" and "text" are supported.
2576 @type format: C{str}
2577 @return: a piece of program code which can be used to evaluate the
2578 expression assuming the values for the arguments are available
2579 @rtype: C{str}
2580 @raise NotImplementedError: if no implementation for the given format
2581 is available
2582 """
2583 if isinstance(argstrs,list):
2584 argstrs=argstrs[0]
2585 if format=="escript" or format=="str" or format=="text":
2586 return "asinh(%s)"%argstrs
2587 else:
2588 raise NotImplementedError,"Asinh_Symbol does not provide program code for format %s."%format
2589
2590 def substitute(self,argvals):
2591 """
2592 Assigns new values to symbols in the definition of the symbol.
2593 The method replaces the L{Symbol} u by argvals[u] in the expression
2594 defining this object.
2595
2596 @param argvals: new values assigned to symbols
2597 @type argvals: C{dict} with keywords of type L{Symbol}
2598 @return: result of the substitution process. Operations are executed as
2599 much as possible.
2600 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2601 depending on the degree of substitution
2602 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2603 """
2604 if argvals.has_key(self):
2605 arg=argvals[self]
2606 if self.isAppropriateValue(arg):
2607 return arg
2608 else:
2609 raise TypeError,"%s: new value is not appropriate."%str(self)
2610 else:
2611 arg=self.getSubstitutedArguments(argvals)[0]
2612 return asinh(arg)
2613
2614 def diff(self,arg):
2615 """
2616 Differential of this object.
2617
2618 @param arg: the derivative is calculated with respect to C{arg}
2619 @type arg: L{escript.Symbol}
2620 @return: derivative with respect to C{arg}
2621 @rtype: typically L{Symbol} but other types such as C{float},
2622 L{escript.Data}, C{numarray.NumArray} are possible
2623 """
2624 if arg==self:
2625 return identity(self.getShape())
2626 else:
2627 myarg=self.getArgument()[0]
2628 val=matchShape(1./sqrt(myarg**2+1),self.getDifferentiatedArguments(arg)[0])
2629 return val[0]*val[1]
2630
2631 def acosh(arg):
2632 """
2633 Returns the inverse hyperbolic cosine of argument C{arg}.
2634
2635 @param arg: argument
2636 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2637 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2638 on the type of C{arg}
2639 @raises TypeError: if the type of the argument is not expected
2640 """
2641 if isinstance(arg,numarray.NumArray):
2642 return numarray.arccosh(arg)
2643 elif isinstance(arg,escript.Data):
2644 return arg._acosh()
2645 elif isinstance(arg,float):
2646 return numarray.arccosh(arg)
2647 elif isinstance(arg,int):
2648 return numarray.arccosh(float(arg))
2649 elif isinstance(arg,Symbol):
2650 return Acosh_Symbol(arg)
2651 else:
2652 raise TypeError,"acosh: Unknown argument type."
2653
2654 class Acosh_Symbol(DependendSymbol):
2655 """
2656 L{Symbol} representing the result of the inverse hyperbolic cosine function.
2657 """
2658 def __init__(self,arg):
2659 """
2660 Initialization of acosh L{Symbol} with argument C{arg}.
2661
2662 @param arg: argument of function
2663 @type arg: typically L{Symbol}
2664 """
2665 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2666
2667 def getMyCode(self,argstrs,format="escript"):
2668 """
2669 Returns program code that can be used to evaluate the symbol.
2670
2671 @param argstrs: a string for each argument representing the argument
2672 for the evaluation
2673 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2674 @param format: specifies the format to be used. At the moment only
2675 "escript", "str" and "text" are supported.
2676 @type format: C{str}
2677 @return: a piece of program code which can be used to evaluate the
2678 expression assuming the values for the arguments are available
2679 @rtype: C{str}
2680 @raise NotImplementedError: if no implementation for the given format
2681 is available
2682 """
2683 if isinstance(argstrs,list):
2684 argstrs=argstrs[0]
2685 if format=="escript" or format=="str" or format=="text":
2686 return "acosh(%s)"%argstrs
2687 else:
2688 raise NotImplementedError,"Acosh_Symbol does not provide program code for format %s."%format
2689
2690 def substitute(self,argvals):
2691 """
2692 Assigns new values to symbols in the definition of the symbol.
2693 The method replaces the L{Symbol} u by argvals[u] in the expression
2694 defining this object.
2695
2696 @param argvals: new values assigned to symbols
2697 @type argvals: C{dict} with keywords of type L{Symbol}
2698 @return: result of the substitution process. Operations are executed as
2699 much as possible.
2700 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2701 depending on the degree of substitution
2702 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2703 """
2704 if argvals.has_key(self):
2705 arg=argvals[self]
2706 if self.isAppropriateValue(arg):
2707 return arg
2708 else:
2709 raise TypeError,"%s: new value is not appropriate."%str(self)
2710 else:
2711 arg=self.getSubstitutedArguments(argvals)[0]
2712 return acosh(arg)
2713
2714 def diff(self,arg):
2715 """
2716 Differential of this object.
2717
2718 @param arg: the derivative is calculated with respect to C{arg}
2719 @type arg: L{escript.Symbol}
2720 @return: derivative with respect to C{arg}
2721 @rtype: typically L{Symbol} but other types such as C{float},
2722 L{escript.Data}, C{numarray.NumArray} are possible
2723 """
2724 if arg==self:
2725 return identity(self.getShape())
2726 else:
2727 myarg=self.getArgument()[0]
2728 val=matchShape(1./sqrt(myarg**2-1),self.getDifferentiatedArguments(arg)[0])
2729 return val[0]*val[1]
2730
2731 def atanh(arg):
2732 """
2733 Returns the inverse hyperbolic tangent of argument C{arg}.
2734
2735 @param arg: argument
2736 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2737 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2738 on the type of C{arg}
2739 @raises TypeError: if the type of the argument is not expected
2740 """
2741 if isinstance(arg,numarray.NumArray):
2742 return numarray.arctanh(arg)
2743 elif isinstance(arg,escript.Data):
2744 return arg._atanh()
2745 elif isinstance(arg,float):
2746 return numarray.arctanh(arg)
2747 elif isinstance(arg,int):
2748 return numarray.arctanh(float(arg))
2749 elif isinstance(arg,Symbol):
2750 return Atanh_Symbol(arg)
2751 else:
2752 raise TypeError,"atanh: Unknown argument type."
2753
2754 class Atanh_Symbol(DependendSymbol):
2755 """
2756 L{Symbol} representing the result of the inverse hyperbolic tangent function.
2757 """
2758 def __init__(self,arg):
2759 """
2760 Initialization of atanh L{Symbol} with argument C{arg}.
2761
2762 @param arg: argument of function
2763 @type arg: typically L{Symbol}
2764 """
2765 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2766
2767 def getMyCode(self,argstrs,format="escript"):
2768 """
2769 Returns program code that can be used to evaluate the symbol.
2770
2771 @param argstrs: a string for each argument representing the argument
2772 for the evaluation
2773 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2774 @param format: specifies the format to be used. At the moment only
2775 "escript", "str" and "text" are supported.
2776 @type format: C{str}
2777 @return: a piece of program code which can be used to evaluate the
2778 expression assuming the values for the arguments are available
2779 @rtype: C{str}
2780 @raise NotImplementedError: if no implementation for the given format
2781 is available
2782 """
2783 if isinstance(argstrs,list):
2784 argstrs=argstrs[0]
2785 if format=="escript" or format=="str" or format=="text":
2786 return "atanh(%s)"%argstrs
2787 else:
2788 raise NotImplementedError,"Atanh_Symbol does not provide program code for format %s."%format
2789
2790 def substitute(self,argvals):
2791 """
2792 Assigns new values to symbols in the definition of the symbol.
2793 The method replaces the L{Symbol} u by argvals[u] in the expression
2794 defining this object.
2795
2796 @param argvals: new values assigned to symbols
2797 @type argvals: C{dict} with keywords of type L{Symbol}
2798 @return: result of the substitution process. Operations are executed as
2799 much as possible.
2800 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2801 depending on the degree of substitution
2802 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2803 """
2804 if argvals.has_key(self):
2805 arg=argvals[self]
2806 if self.isAppropriateValue(arg):
2807 return arg
2808 else:
2809 raise TypeError,"%s: new value is not appropriate."%str(self)
2810 else:
2811 arg=self.getSubstitutedArguments(argvals)[0]
2812 return atanh(arg)
2813
2814 def diff(self,arg):
2815 """
2816 Differential of this object.
2817
2818 @param arg: the derivative is calculated with respect to C{arg}
2819 @type arg: L{escript.Symbol}
2820 @return: derivative with respect to C{arg}
2821 @rtype: typically L{Symbol} but other types such as C{float},
2822 L{escript.Data}, C{numarray.NumArray} are possible
2823 """
2824 if arg==self:
2825 return identity(self.getShape())
2826 else:
2827 myarg=self.getArgument()[0]
2828 val=matchShape(1./(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2829 return val[0]*val[1]
2830
2831 def exp(arg):
2832 """
2833 Returns M{e} to the power of argument C{arg}.
2834
2835 @param arg: argument
2836 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
2837 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
2838 on the type of arg
2839 @raises TypeError: if the type of the argument is not expected
2840 """
2841 if isinstance(arg,numarray.NumArray):
2842 return numarray.exp(arg)
2843 elif isinstance(arg,escript.Data):
2844 return arg._exp()
2845 elif isinstance(arg,float):
2846 return math.exp(arg)
2847 elif isinstance(arg,int):
2848 return math.exp(arg)
2849 elif isinstance(arg,Symbol):
2850 return Exp_Symbol(arg)
2851 else:
2852 raise TypeError,"exp: Unknown argument type."
2853
2854 class Exp_Symbol(DependendSymbol):
2855 """
2856 L{Symbol} representing the result of the exponential function.
2857 """
2858 def __init__(self,arg):
2859 """
2860 Initialization of exp L{Symbol} with argument C{arg}.
2861
2862 @param arg: argument of function
2863 @type arg: typically L{Symbol}
2864 """
2865 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2866
2867 def getMyCode(self,argstrs,format="escript"):
2868 """
2869 Returns program code that can be used to evaluate the symbol.
2870
2871 @param argstrs: a string for each argument representing the argument
2872 for the evaluation
2873 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2874 @param format: specifies the format to be used. At the moment only
2875 "escript", "str" and "text" are supported.
2876 @type format: C{str}
2877 @return: a piece of program code which can be used to evaluate the
2878 expression assuming the values for the arguments are available
2879 @rtype: C{str}
2880 @raise NotImplementedError: if no implementation for the given format
2881 is available
2882 """
2883 if isinstance(argstrs,list):
2884 argstrs=argstrs[0]
2885 if format=="escript" or format=="str" or format=="text":
2886 return "exp(%s)"%argstrs
2887 else:
2888 raise NotImplementedError,"Exp_Symbol does not provide program code for format %s."%format
2889
2890 def substitute(self,argvals):
2891 """
2892 Assigns new values to symbols in the definition of the symbol.
2893 The method replaces the L{Symbol} u by argvals[u] in the expression
2894 defining this object.
2895
2896 @param argvals: new values assigned to symbols
2897 @type argvals: C{dict} with keywords of type L{Symbol}
2898 @return: result of the substitution process. Operations are executed as
2899 much as possible.
2900 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
2901 depending on the degree of substitution
2902 @raise TypeError: if a value for a L{Symbol} cannot be substituted
2903 """
2904 if argvals.has_key(self):
2905 arg=argvals[self]
2906 if self.isAppropriateValue(arg):
2907 return arg
2908 else:
2909 raise TypeError,"%s: new value is not appropriate."%str(self)
2910 else:
2911 arg=self.getSubstitutedArguments(argvals)[0]
2912 return exp(arg)
2913
2914 def diff(self,arg):
2915 """
2916 Differential of this object.
2917
2918 @param arg: the derivative is calculated with respect to C{arg}
2919 @type arg: L{escript.Symbol}
2920 @return: derivative with respect to C{arg}
2921 @rtype: typically L{Symbol} but other types such as C{float},
2922 L{escript.Data}, C{numarray.NumArray} are possible
2923 """
2924 if arg==self:
2925 return identity(self.getShape())
2926 else:
2927 myarg=self.getArgument()[0]
2928 val=matchShape(self,self.getDifferentiatedArguments(arg)[0])
2929 return val[0]*val[1]
2930
2931 def sqrt(arg):
2932 """
2933 Returns the square root of argument C{arg}.
2934
2935 @param arg: argument
2936 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2937 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
2938 depending on the type of C{arg}
2939 @raises TypeError: if the type of the argument is not expected
2940 """
2941 if isinstance(arg,numarray.NumArray):
2942 return numarray.sqrt(arg)
2943 elif isinstance(arg,escript.Data):
2944 return arg._sqrt()
2945 elif isinstance(arg,float):
2946 return math.sqrt(arg)
2947 elif isinstance(arg,int):
2948 return math.sqrt(arg)
2949 elif isinstance(arg,Symbol):
2950 return Sqrt_Symbol(arg)
2951 else:
2952 raise TypeError,"sqrt: Unknown argument type."
2953
2954 class Sqrt_Symbol(DependendSymbol):
2955 """
2956 L{Symbol} representing the result of the square root function.
2957 """
2958 def __init__(self,arg):
2959 """
2960 Initialization of sqrt L{Symbol} with argument C{arg}.
2961
2962 @param arg: argument of function
2963 @type arg: typically L{Symbol}
2964 """
2965 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2966
2967 def getMyCode(self,argstrs,format="escript"):
2968 """
2969 Returns program code that can be used to evaluate the symbol.
2970
2971 @param argstrs: a string for each argument representing the argument
2972 for the evaluation
2973 @type argstrs: C{str} or a C{list} of length 1 of C{str}
2974 @param format: specifies the format to be used. At the moment only
2975 "escript", "str" and "text" are supported.
2976 @type format: C{str}
2977 @return: a piece of program code which can be used to evaluate the
2978 expression assuming the values for the arguments are available
2979 @rtype: C{str}
2980 @raise NotImplementedError: if no implementation for the given format
2981 is available
2982 """
2983 if isinstance(argstrs,list):
2984 argstrs=argstrs[0]
2985 if format=="escript" or format=="str" or format=="text":
2986 return "sqrt(%s)"%argstrs
2987 else:
2988 raise NotImplementedError,"Sqrt_Symbol does not provide program code for format %s."%format
2989
2990 def substitute(self,argvals):
2991 """
2992 Assigns new values to symbols in the definition of the symbol.
2993 The method replaces the L{Symbol} u by argvals[u] in the expression
2994 defining this object.
2995
2996 @param argvals: new values assigned to symbols
2997 @type argvals: C{dict} with keywords of type L{Symbol}
2998 @return: result of the substitution process. Operations are executed as
2999 much as possible.
3000 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
3001 depending on the degree of substitution
3002 @raise TypeError: if a value for a L{Symbol} cannot be substituted
3003 """
3004 if argvals.has_key(self):
3005 arg=argvals[self]
3006 if self.isAppropriateValue(arg):
3007 return arg
3008 else:
3009 raise TypeError,"%s: new value is not appropriate."%str(self)
3010 else:
3011 arg=self.getSubstitutedArguments(argvals)[0]
3012 return sqrt(arg)
3013
3014 def diff(self,arg):
3015 """
3016 Differential of this object.
3017
3018 @param arg: the derivative is calculated with respect to C{arg}
3019 @type arg: L{escript.Symbol}
3020 @return: derivative with respect to C{arg}
3021 @rtype: typically L{Symbol} but other types such as C{float},
3022 L{escript.Data}, C{numarray.NumArray} are possible
3023 """
3024 if arg==self:
3025 return identity(self.getShape())
3026 else:
3027 myarg=self.getArgument()[0]
3028 val=matchShape(0.5/self,self.getDifferentiatedArguments(arg)[0])
3029 return val[0]*val[1]
3030
3031 def log(arg):
3032 """
3033 Returns the natural logarithm of argument C{arg}.
3034
3035 @param arg: argument
3036 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}.
3037 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
3038 on the type of C{arg}
3039 @raises TypeError: if the type of the argument is not expected
3040 """
3041 if isinstance(arg,numarray.NumArray):
3042 return numarray.log(arg)
3043 elif isinstance(arg,escript.Data):
3044 return arg._log()
3045 elif isinstance(arg,float):
3046 return math.log(arg)
3047 elif isinstance(arg,int):
3048 return math.log(arg)
3049 elif isinstance(arg,Symbol):
3050 return Log_Symbol(arg)
3051 else:
3052 raise TypeError,"log: Unknown argument type."
3053
3054 class Log_Symbol(DependendSymbol):
3055 """
3056 L{Symbol} representing the result of the natural logarithm function.
3057 """
3058 def __init__(self,arg):
3059 """
3060 Initialization of log L{Symbol} with argument C{arg}.
3061
3062 @param arg: argument of function
3063 @type arg: typically L{Symbol}
3064 """
3065 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
3066
3067 def getMyCode(self,argstrs,format="escript"):
3068 """
3069 Returns program code that can be used to evaluate the symbol.
3070
3071 @param argstrs: a string for each argument representing the argument
3072 for the evaluation
3073 @type argstrs: C{str} or a C{list} of length 1 of C{str}
3074 @param format: specifies the format to be used. At the moment only
3075 "escript", "str" and "text" are supported.
3076 @type format: C{str}
3077 @return: a piece of program code which can be used to evaluate the
3078 expression assuming the values for the arguments are available
3079 @rtype: C{str}
3080 @raise NotImplementedError: if no implementation for the given format
3081 is available
3082 """
3083 if isinstance(argstrs,list):
3084 argstrs=argstrs[0]
3085 if format=="escript" or format=="str" or format=="text":
3086 return "log(%s)"%argstrs
3087 else:
3088 raise NotImplementedError,"Log_Symbol does not provide program code for format %s."%format
3089
3090 def substitute(self,argvals):
3091 """
3092 Assigns new values to symbols in the definition of the symbol.
3093 The method replaces the L{Symbol} u by argvals[u] in the expression
3094 defining this object.
3095
3096 @param argvals: new values assigned to symbols
3097 @type argvals: C{dict} with keywords of type L{Symbol}
3098 @return: result of the substitution process. Operations are executed as
3099 much as possible.
3100 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
3101 depending on the degree of substitution
3102 @raise TypeError: if a value for a L{Symbol} cannot be substituted
3103 """
3104 if argvals.has_key(self):
3105 arg=argvals[self]
3106 if self.isAppropriateValue(arg):
3107 return arg
3108 else:
3109 raise TypeError,"%s: new value is not appropriate."%str(self)
3110 else:
3111 arg=self.getSubstitutedArguments(argvals)[0]
3112 return log(arg)
3113
3114 def diff(self,arg):
3115 """
3116 Differential of this object.
3117
3118 @param arg: the derivative is calculated with respect to C{arg}
3119 @type arg: L{escript.Symbol}
3120 @return: derivative with respect to C{arg}
3121 @rtype: typically L{Symbol} but other types such as C{float},
3122 L{escript.Data}, C{numarray.NumArray} are possible
3123 """
3124 if arg==self:
3125 return identity(self.getShape())
3126 else:
3127 myarg=self.getArgument()[0]
3128 val=matchShape(1./arg,self.getDifferentiatedArguments(arg)[0])
3129 return val[0]*val[1]
3130
3131 def sign(arg):
3132 """
3133 Returns the sign of argument C{arg}.
3134
3135 @param arg: argument
3136 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
3137 @rtype: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending
3138 on the type of C{arg}
3139 @raises TypeError: if the type of the argument is not expected
3140 """
3141 if isinstance(arg,numarray.NumArray):
3142 return wherePositive(arg)-whereNegative(arg)
3143 elif isinstance(arg,escript.Data):
3144 return arg._sign()
3145 elif isinstance(arg,float):
3146 if arg>0:
3147 return 1.
3148 elif arg<0:
3149 return -1.
3150 else:
3151 return 0.
3152 elif isinstance(arg,int):
3153 if float(arg)>0:
3154 return 1.
3155 elif float(arg)<0:
3156 return -1.
3157 else:
3158 return 0.
3159 elif isinstance(arg,Symbol):
3160 return wherePositive(arg)-whereNegative(arg)
3161 else:
3162 raise TypeError,"sign: Unknown argument type."
3163
3164 class Abs_Symbol(DependendSymbol):
3165 """
3166 L{Symbol} representing the result of the absolute value function.
3167 """
3168 def __init__(self,arg):
3169 """
3170 Initialization of abs L{Symbol} with argument C{arg}.
3171
3172 @param arg: argument of function
3173 @type arg: typically L{Symbol}
3174 """
3175 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
3176
3177 def getMyCode(self,argstrs,format="escript"):
3178 """
3179 Returns program code that can be used to evaluate the symbol.
3180
3181 @param argstrs: a string for each argument representing the argument
3182 for the evaluation
3183 @type argstrs: C{str} or a C{list} of length 1 of C{str}
3184 @param format: specifies the format to be used. At the moment only
3185 "escript", "str" and "text" are supported.
3186 @type format: C{str}
3187 @return: a piece of program code which can be used to evaluate the
3188 expression assuming the values for the arguments are available
3189 @rtype: C{str}
3190 @raise NotImplementedError: if no implementation for the given format
3191 is available
3192 """
3193 if isinstance(argstrs,list):
3194 argstrs=argstrs[0]
3195 if format=="escript" or format=="str" or format=="text":
3196 return "abs(%s)"%argstrs
3197 else:
3198 raise NotImplementedError,"Abs_Symbol does not provide program code for format %s."%format
3199
3200 def substitute(self,argvals):
3201 """
3202 Assigns new values to symbols in the definition of the symbol.
3203 The method replaces the L{Symbol} u by argvals[u] in the expression
3204 defining this object.
3205
3206 @param argvals: new values assigned to symbols
3207 @type argvals: C{dict} with keywords of type L{Symbol}
3208 @return: result of the substitution process. Operations are executed as
3209 much as possible.
3210 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
3211 depending on the degree of substitution
3212 @raise TypeError: if a value for a L{Symbol} cannot be substituted
3213 """
3214 if argvals.has_key(self):
3215 arg=argvals[self]
3216 if self.isAppropriateValue(arg):
3217 return arg
3218 else:
3219 raise TypeError,"%s: new value is not appropriate."%str(self)
3220 else:
3221 arg=self.getSubstitutedArguments(argvals)[0]
3222 return abs(arg)
3223
3224 def diff(self,arg):
3225 """
3226 Differential of this object.
3227
3228 @param arg: the derivative is calculated with respect to C{arg}
3229 @type arg: L{escript.Symbol}
3230 @return: derivative with respect to C{arg}
3231 @rtype: typically L{Symbol} but other types such as C{float},
3232 L{escript.Data}, C{numarray.NumArray} are possible
3233 """
3234 if arg==self:
3235 return identity(self.getShape())
3236 else:
3237 myarg=self.getArgument()[0]
3238 val=matchShape(sign(myarg),self.getDifferentiatedArguments(arg)[0])
3239 return val[0]*val[1]
3240
3241 def minval(arg):
3242 """
3243 Returns the minimum value over all components of C{arg} at each data point.
3244
3245 @param arg: argument
3246 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
3247 @rtype: C{float}, L{escript.Data}, L{Symbol} depending on the type of C{arg}
3248 @raises TypeError: if the type of the argument is not expected
3249 """
3250 if isinstance(arg,numarray.NumArray):
3251 if arg.rank==0:
3252 return float(arg)
3253 else:
3254 return arg.min()
3255 elif isinstance(arg,escript.Data):
3256 return arg._minval()
3257 elif isinstance(arg,float):
3258 return arg
3259 elif isinstance(arg,int):
3260 return float(arg)
3261 elif isinstance(arg,Symbol):
3262 return Minval_Symbol(arg)
3263 else:
3264 raise TypeError,"minval: Unknown argument type."
3265
3266 class Minval_Symbol(DependendSymbol):
3267 """
3268 L{Symbol} representing the result of the minimum value function.
3269 """
3270 def __init__(self,arg):
3271 """
3272 Initialization of minimum value L{Symbol} with argument C{arg}.
3273
3274 @param arg: argument of function
3275 @type arg: typically L{Symbol}
3276 """
3277 DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
3278
3279 def getMyCode(self,argstrs,format="escript"):
3280 """
3281 Returns program code that can be used to evaluate the symbol.
3282
3283 @param argstrs: a string for each argument representing the argument
3284 for the evaluation
3285 @type argstrs: C{str} or a C{list} of length 1 of C{str}
3286 @param format: specifies the format to be used. At the moment only
3287 "escript", "str" and "text" are supported.
3288 @type format: C{str}
3289 @return: a piece of program code which can be used to evaluate the
3290 expression assuming the values for the arguments are available
3291 @rtype: C{str}
3292 @raise NotImplementedError: if no implementation for the given format
3293 is available
3294 """
3295 if isinstance(argstrs,list):
3296 argstrs=argstrs[0]
3297 if format=="escript" or format=="str" or format=="text":
3298 return "minval(%s)"%argstrs
3299 else:
3300 raise NotImplementedError,"Minval_Symbol does not provide program code for format %s."%format
3301
3302 def substitute(self,argvals):
3303 """
3304 Assigns new values to symbols in the definition of the symbol.
3305 The method replaces the L{Symbol} u by argvals[u] in the expression
3306 defining this object.
3307
3308 @param argvals: new values assigned to symbols
3309 @type argvals: C{dict} with keywords of type L{Symbol}
3310 @return: result of the substitution process. Operations are executed as
3311 much as possible.
3312 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
3313 depending on the degree of substitution
3314 @raise TypeError: if a value for a L{Symbol} cannot be substituted
3315 """
3316 if argvals.has_key(self):
3317 arg=argvals[self]
3318 if self.isAppropriateValue(arg):
3319 return arg
3320 else:
3321 raise TypeError,"%s: new value is not appropriate."%str(self)
3322 else:
3323 arg=self.getSubstitutedArguments(argvals)[0]
3324 return minval(arg)
3325
3326 def maxval(arg):
3327 """
3328 Returns the maximum value over all components of C{arg} at each data point.
3329
3330 @param arg: argument
3331 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
3332 @rtype: C{float}, L{escript.Data}, L{Symbol} depending on the type of C{arg}
3333 @raises TypeError: if the type of the argument is not expected
3334 """
3335 if isinstance(arg,numarray.NumArray):
3336 if arg.rank==0:
3337 return float(arg)
3338 else:
3339 return arg.max()
3340 elif isinstance(arg,escript.Data):
3341 return arg._maxval()
3342 elif isinstance(arg,float):
3343 return arg
3344 elif isinstance(arg,int):
3345 return float(arg)
3346 elif isinstance(arg,Symbol):
3347 return Maxval_Symbol(arg)
3348 else:
3349 raise TypeError,"maxval: Unknown argument type."
3350
3351 class Maxval_Symbol(DependendSymbol):
3352 """
3353 L{Symbol} representing the result of the maximum value function.
3354 """
3355 def __init__(self,arg):
3356 """
3357 Initialization of maximum value L{Symbol} with argument C{arg}.
3358
3359 @param arg: argument of function
3360 @type arg: typically L{Symbol}
3361 """
3362 DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
3363
3364 def getMyCode(self,argstrs,format="escript"):
3365 """
3366 Returns program code that can be used to evaluate the symbol.
3367
3368 @param argstrs: a string for each argument representing the argument
3369 for the evaluation
3370 @type argstrs: C{str} or a C{list} of length 1 of C{str}
3371 @param format: specifies the format to be used. At the moment only
3372 "escript", "str" and "text" are supported.
3373 @type format: C{str}
3374 @return: a piece of program code which can be used to evaluate the
3375 expression assuming the values for the arguments are available
3376 @rtype: C{str}
3377 @raise NotImplementedError: if no implementation for the given format
3378 is available
3379 """
3380 if isinstance(argstrs,list):
3381 argstrs=argstrs[0]
3382 if format=="escript" or format=="str" or format=="text":
3383 return "maxval(%s)"%argstrs
3384 else:
3385 raise NotImplementedError,"Maxval_Symbol does not provide program code for format %s."%format
3386
3387 def substitute(self,argvals):
3388 """
3389 Assigns new values to symbols in the definition of the symbol.
3390 The method replaces the L{Symbol} u by argvals[u] in the expression
3391 defining this object.
3392
3393 @param argvals: new values assigned to symbols
3394 @type argvals: C{dict} with keywords of type L{Symbol}
3395 @return: result of the substitution process. Operations are executed as
3396 much as possible.
3397 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
3398 depending on the degree of substitution
3399 @raise TypeError: if a value for a L{Symbol} cannot be substituted
3400 """
3401 if argvals.has_key(self):
3402 arg=argvals[self]
3403 if self.isAppropriateValue(arg):
3404 return arg
3405 else:
3406 raise TypeError,"%s: new value is not appropriate."%str(self)
3407 else:
3408 arg=self.getSubstitutedArguments(argvals)[0]
3409 return maxval(arg)
3410
3411 def length(arg):
3412 """
3413 Returns the length (Euclidean norm) of argument C{arg} at each data point.
3414
3415 @param arg: argument
3416 @type arg: C{float}, L{escript.Data}, L{Symbol}, C{numarray.NumArray}
3417 @rtype: C{float}, L{escript.Data}, L{Symbol} depending on the type of C{arg}
3418 """
3419 return sqrt(inner(arg,arg))
3420
3421 def trace(arg,axis_offset=0):
3422 """
3423 Returns the trace of C{arg} which is the sum of C{arg[k,k]} over k.
3424
3425 @param arg: argument
3426 @type arg: L{escript.Data}, L{Symbol}, C{numarray.NumArray}
3427 @param axis_offset: C{axis_offset} to components to sum over. C{axis_offset}
3428 must be non-negative and less than the rank of C{arg} +1.
3429 The dimensions of component C{axis_offset} and
3430 axis_offset+1 must be equal.
3431 @type axis_offset: C{int}
3432 @return: trace of arg. The rank of the returned object is rank of C{arg}
3433 minus 2.
3434 @rtype: L{escript.Data}, L{Symbol}, C{numarray.NumArray} depending on the
3435 type of C{arg}
3436 """
3437 if isinstance(arg,numarray.NumArray):
3438 sh=arg.shape
3439 if len(sh)<2:
3440 raise ValueError,"rank of argument must be greater than 1"
3441 if axis_offset<0 or axis_offset>len(sh)-2:
3442 raise ValueError,"axis_offset must be between 0 and %d"%(len(sh)-2)
3443 s1=1
3444 for i in range(axis_offset): s1*=sh[i]
3445 s2=1
3446 for i in range(axis_offset+2,len(sh)): s2*=sh[i]
3447 if not sh[axis_offset] == sh[axis_offset+1]:
3448 raise ValueError,"dimensions of component %d and %d must match."%(axis_offset,axis_offset+1)
3449 arg_reshaped=numarray.reshape(arg,(s1,sh[axis_offset],sh[axis_offset],s2))
3450 out=numarray.zeros([s1,s2],numarray.Float64)
3451 for i1 in range(s1):
3452 for i2 in range(s2):
3453 for j in range(sh[axis_offset]): out[i1,i2]+=arg_reshaped[i1,j,j,i2]
3454 out.resize(sh[:axis_offset]+sh[axis_offset+2:])
3455 return out
3456 elif isinstance(arg,escript.Data):
3457 if arg.getRank()<2:
3458 raise ValueError,"rank of argument must be greater than 1"
3459 if axis_offset<0 or axis_offset>arg.getRank()-2:
3460 raise ValueError,"axis_offset must be between 0 and %d"%(arg.getRank()-2)
3461 s=list(arg.getShape())
3462 if not s[axis_offset] == s[axis_offset+1]:
3463 raise ValueError,"dimensions of component %d and %d must match."%(axis_offset,axis_offset+1)
3464 return arg._trace(axis_offset)
3465 elif isinstance(arg,float):
3466 raise TypeError,"illegal argument type float."
3467 elif isinstance(arg,int):
3468 raise TypeError,"illegal argument type int."
3469 elif isinstance(arg,Symbol):
3470 return Trace_Symbol(arg,axis_offset)
3471 else:
3472 raise TypeError,"Unknown argument type."
3473
3474 class Trace_Symbol(DependendSymbol):
3475 """
3476 L{Symbol} representing the result of the trace function.
3477 """
3478 def __init__(self,arg,axis_offset=0):
3479 """
3480 Initialization of trace L{Symbol} with argument C{arg}.
3481
3482 @param arg: argument of function
3483 @type arg: L{Symbol}
3484 @param axis_offset: C{axis_offset} to components to sum over.
3485 C{axis_offset} must be non-negative and less than the
3486 rank of C{arg} +1. The dimensions on component
3487 C{axis_offset} and axis_offset+1 must be equal.
3488 @type axis_offset: C{int}
3489 """
3490 if arg.getRank()<2:
3491 raise ValueError,"rank of argument must be greater than 1"
3492 if axis_offset<0 or axis_offset>arg.getRank()-2:
3493 raise ValueError,"axis_offset must be between 0 and %d"%(arg.getRank()-2)
3494 s=list(arg.getShape())
3495 if not s[axis_offset] == s[axis_offset+1]:
3496 raise ValueError,"dimensions of component %d and %d must match."%(axis_offset,axis_offset+1)
3497 super(Trace_Symbol,self).__init__(args=[arg,axis_offset],shape=tuple(s[0:axis_offset]+s[axis_offset+2:]),dim=arg.getDim())
3498
3499 def getMyCode(self,argstrs,format="escript"):
3500 """
3501 Returns program code that can be used to evaluate the symbol.
3502
3503 @param argstrs: a string for each argument representing the argument
3504 for the evaluation
3505 @type argstrs: C{str} or a C{list} of length 1 of C{str}
3506 @param format: specifies the format to be used. At the moment only
3507 "escript", "str" and "text" are supported.
3508 @type format: C{str}
3509 @return: a piece of program code which can be used to evaluate the
3510 expression assuming the values for the arguments are available
3511 @rtype: C{str}
3512 @raise NotImplementedError: if no implementation for the given format
3513 is available
3514 """
3515 if format=="escript" or format=="str" or format=="text":
3516 return "trace(%s,axis_offset=%s)"%(argstrs[0],argstrs[1])
3517 else:
3518 raise NotImplementedError,"Trace_Symbol does not provide program code for format %s."%format
3519
3520 def substitute(self,argvals):
3521 """
3522 Assigns new values to symbols in the definition of the symbol.
3523 The method replaces the L{Symbol} u by argvals[u] in the expression
3524 defining this object.
3525
3526 @param argvals: new values assigned to symbols
3527 @type argvals: C{dict} with keywords of type L{Symbol}
3528 @return: result of the substitution process. Operations are executed as
3529 much as possible.
3530 @rtype: L{escript.Symbol}, C{float}, L{escript.Data}, C{numarray.NumArray}
3531 depending on the degree of substitution
3532 @raise TypeError: if a value for a L{Symbol} cannot be substituted
3533 """
3534 if argvals.has_key(self):
3535 arg=argvals[self]
3536 if self.isAppropriateValue(arg):
3537 return arg
3538 else:
3539 raise TypeError,"%s: new value is not appropriate."%str(self)
3540 else:
3541 arg=self.getSubstitutedArguments(argvals)
3542 return trace(arg[0],axis_offset=arg[1])
3543
3544 def diff(self,arg):
3545 """
3546 Differential of this object.
3547
3548 @param arg: the derivative is calculated with respect to C{arg}
3549 @type arg: L{escript.Symbol}
3550 @return: derivative with respect to C{arg}
3551 @rtype: typically L{Symbol} but other types such as C{float},
3552 L{escript.Data}, C{numarray.NumArray} are possible
3553 """
3554 if arg==self:
3555 return identity(self.getShape())
3556 else:
3557 return trace(self.getDifferentiatedArguments(arg)[0],axis_offset=self.getArgument()[1])
3558
3559 def