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