/[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 2599 - (show annotations)
Fri Aug 7 00:16:02 2009 UTC (10 years, 10 months ago) by caltinay
File MIME type: text/x-python
File size: 232662 byte(s)
saveESD: added option to save mesh at each timestep if required.

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