/[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 2644 - (show annotations)
Wed Sep 2 04:14:03 2009 UTC (10 years, 4 months ago) by jfenwick
File MIME type: text/x-python
File size: 234231 byte(s)
Add unit tests for saveDataCSV which should be ready for use now.
Keyword args are now output in sorted order.

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