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