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