/[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 3344 - (show annotations)
Thu Nov 11 23:26:52 2010 UTC (8 years, 4 months ago) by caltinay
File MIME type: text/x-python
File size: 234346 byte(s)
Phew!
-escript, finley, and dudley now uses weipa's saveVTK implementation
-moved tests from finley to weipa accordingly; dudley still to do
-rebaselined all test files
-fixed a few issues in weipa.saveVTK, e.g. saving metadata without schema
-added a deprecation warning to esys.escript.util.saveVTK
-todo: change doco, tests and other places to use weipa.saveVTK


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