/[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 3892 - (show annotations)
Tue Apr 10 08:57:23 2012 UTC (6 years, 11 months ago) by jfenwick
File MIME type: text/x-python
File size: 237069 byte(s)
Merged changes across from the attempt2 branch.
This version builds and passes python2 tests.
It also passes most python3 tests.



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