/[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 3852 - (show annotations)
Thu Mar 1 05:34:52 2012 UTC (7 years, 7 months ago) by jfenwick
File MIME type: text/x-python
File size: 236479 byte(s)
Correcting some indent errors

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 __rdiv__(self,other):
1139 """
1140 Divides another object by this object.
1141
1142 :param other: object to be divided by this object
1143 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1144 ``numpy.ndarray``
1145 :return: a `Symbol` representing the quotient of ``other`` and this
1146 object
1147 :rtype: `DependendSymbol` or 0 if ``other`` is identical to zero
1148 """
1149 return quotient(other,self)
1150
1151 def __pow__(self,other):
1152 """
1153 Raises this object to the power of ``other``.
1154
1155 :param other: exponent
1156 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1157 ``numpy.ndarray``
1158 :return: a `Symbol` representing the power of this object to ``other``
1159 :rtype: `DependendSymbol` or 1 if ``other`` is identical to zero
1160 """
1161 return power(self,other)
1162
1163 def __rpow__(self,other):
1164 """
1165 Raises an object to the power of this object.
1166
1167 :param other: basis
1168 :type other: `escript.Symbol`, ``float``, `escript.Data`,
1169 ``numpy.ndarray``
1170 :return: a `Symbol` representing the power of ``other`` to this object
1171 :rtype: `DependendSymbol` or 0 if ``other`` is identical to zero
1172 """
1173 return power(other,self)
1174
1175 def __getitem__(self,index):
1176 """
1177 Returns the slice defined by ``index``.
1178
1179 :param index: the slice index
1180 :type index: ``slice`` or ``int`` or a ``tuple`` of them
1181 :return: a `Symbol` representing the slice defined by index
1182 :rtype: `DependendSymbol`
1183 """
1184 return GetSlice_Symbol(self,index)
1185
1186 class DependendSymbol(Symbol):
1187 """
1188 DependendSymbol extents `Symbol` by modifying the == operator to allow two
1189 instances to be equal. Two ``DependendSymbol`` s are equal if they have the
1190 same shape, the same arguments and one of them has an unspecified spatial
1191 dimension or the spatial dimension is identical.
1192
1193 Example::
1194
1195 u1=Symbol(shape=(3,4),dim=2,args=[4.])
1196 u2=Symbol(shape=(3,4),dim=2,args=[4.])
1197 print u1==u2
1198 False
1199
1200 but::
1201
1202 u1=DependendSymbol(shape=(3,4),dim=2,args=[4.])
1203 u2=DependendSymbol(shape=(3,4),dim=2,args=[4.])
1204 u3=DependendSymbol(shape=(2,),dim=2,args=[4.])
1205 print u1==u2, u1==u3
1206 True False
1207
1208 :note: DependendSymbol should be used as return value of functions with
1209 `Symbol` arguments. This will allow the optimizer to remove
1210 redundant function calls.
1211 """
1212 def __eq__(self,other):
1213 """
1214 Checks if ``other`` equals self.
1215
1216 :param other: any object
1217 :return: True if other has the same class as self and the shape, the
1218 spatial dimension and the arguments are equal, False otherwise
1219 :rtype: ``bool``
1220 """
1221 if isinstance(other,DependendSymbol):
1222 if self.__class__==other.__class__:
1223 if self.getShape()==other.getShape():
1224 if self.getArgument()==other.getArgument():
1225 if self.getDim()==None or other.getDim()==None or self.getDim()==other.getDim():
1226 return True
1227 return False
1228
1229 def __ne__(self,other):
1230 """
1231 Checks if ``other`` is not equal to self.
1232
1233 :param other: any object
1234 :return: False if other has the same class as self and the shape, the
1235 spatial dimension and the arguments are equal, True otherwise
1236 :rtype: ``bool``
1237 """
1238 return not self==other
1239 #=========================================================
1240 # Unary operations preserving the shape
1241 #========================================================
1242 class GetSlice_Symbol(DependendSymbol):
1243 """
1244 `Symbol` representing getting a slice for a `Symbol`.
1245 """
1246 def __init__(self,arg,index):
1247 """
1248 Initialization of the `Symbol` with argument ``arg``.
1249
1250 :param arg: argument
1251 :type arg: `Symbol`
1252 :param index: defines index
1253 :type index: ``slice`` or ``int`` or a ``tuple`` of them
1254 :raise IndexError: if length of index is larger than rank of arg or
1255 index start or stop is out of range
1256 :raise ValueError: if a step is given
1257 """
1258 if not isinstance(index,tuple): index=(index,)
1259 if len(index)>arg.getRank():
1260 raise IndexError("GetSlice_Symbol: index out of range.")
1261 sh=()
1262 index2=()
1263 for i in range(len(index)):
1264 ix=index[i]
1265 if isinstance(ix,int):
1266 if ix<0 or ix>=arg.getShape()[i]:
1267 raise IndexError("GetSlice_Symbol: index out of range.")
1268 index2=index2+(ix,)
1269 else:
1270 if not ix.step==None:
1271 raise ValueError("GetSlice_Symbol: stepping is not supported.")
1272 if ix.start==None:
1273 s=0
1274 else:
1275 s=ix.start
1276 if ix.stop==None:
1277 e=arg.getShape()[i]
1278 else:
1279 e=ix.stop
1280 if e>arg.getShape()[i]:
1281 raise IndexError("GetSlice_Symbol: index out of range.")
1282 index2=index2+(slice(s,e),)
1283 if e>s:
1284 sh=sh+(e-s,)
1285 elif s>e:
1286 raise IndexError("GetSlice_Symbol: slice start must be less or equal slice end")
1287 for i in range(len(index),arg.getRank()):
1288 index2=index2+(slice(0,arg.getShape()[i]),)
1289 sh=sh+(arg.getShape()[i],)
1290 super(GetSlice_Symbol, self).__init__(args=[arg,index2],shape=sh,dim=arg.getDim())
1291
1292 def getMyCode(self,argstrs,format="escript"):
1293 """
1294 Returns program code that can be used to evaluate the symbol.
1295
1296 :param argstrs: a string for each argument representing the argument
1297 for the evaluation
1298 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1299 :param format: specifies the format to be used. At the moment only
1300 "escript", "str" and "text" are supported.
1301 :type format: ``str``
1302 :return: a piece of program code which can be used to evaluate the
1303 expression assuming the values for the arguments are available
1304 :rtype: ``str``
1305 :raise NotImplementedError: if no implementation for the given format
1306 is available
1307 """
1308 if format=="escript" or format=="str" or format=="text":
1309 return "%s.__getitem__(%s)"%(argstrs[0],argstrs[1])
1310 else:
1311 raise NotImplementedError("GetItem_Symbol does not provide program code for format %s."%format)
1312
1313 def substitute(self,argvals):
1314 """
1315 Assigns new values to symbols in the definition of the symbol.
1316 The method replaces the `Symbol` u by argvals[u] in the expression
1317 defining this object.
1318
1319 :param argvals: new values assigned to symbols
1320 :type argvals: ``dict`` with keywords of type `Symbol`
1321 :return: result of the substitution process. Operations are executed as
1322 much as possible.
1323 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1324 depending on the degree of substitution
1325 :raise TypeError: if a value for a `Symbol` cannot be substituted
1326 """
1327 if self in argvals:
1328 arg=argvals[self]
1329 if self.isAppropriateValue(arg):
1330 return arg
1331 else:
1332 raise TypeError("%s: new value is not appropriate."%str(self))
1333 else:
1334 args=self.getSubstitutedArguments(argvals)
1335 arg=args[0]
1336 index=args[1]
1337 return arg.__getitem__(index)
1338
1339 def log10(arg):
1340 """
1341 Returns base-10 logarithm of argument ``arg``.
1342
1343 :param arg: argument
1344 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1345 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1346 on the type of ``arg``
1347 :raise TypeError: if the type of the argument is not expected
1348 """
1349 if isinstance(arg,numpy.ndarray):
1350 return numpy.log10(arg)
1351 elif isinstance(arg,escript.Data):
1352 return arg._log10()
1353 elif isinstance(arg,float):
1354 return math.log10(arg)
1355 elif isinstance(arg,int):
1356 return math.log10(float(arg))
1357 elif isinstance(arg,Symbol):
1358 return log(arg)/log(10.)
1359 else:
1360 raise TypeError("log10: Unknown argument type.")
1361
1362 def wherePositive(arg):
1363 """
1364 Returns mask of positive values of argument ``arg``.
1365
1366 :param arg: argument
1367 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1368 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1369 on the type of ``arg``
1370 :raise TypeError: if the type of the argument is not expected
1371 """
1372 if isinstance(arg,numpy.ndarray):
1373 out=numpy.greater(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1374 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1375 return out
1376 elif isinstance(arg,escript.Data):
1377 return arg._wherePositive()
1378 elif isinstance(arg,float):
1379 if arg>0:
1380 return 1.
1381 else:
1382 return 0.
1383 elif isinstance(arg,int):
1384 if arg>0:
1385 return 1.
1386 else:
1387 return 0.
1388 elif isinstance(arg,Symbol):
1389 return WherePositive_Symbol(arg)
1390 else:
1391 raise TypeError("wherePositive: Unknown argument type.")
1392
1393 class WherePositive_Symbol(DependendSymbol):
1394 """
1395 `Symbol` representing the result of the mask of positive values function.
1396 """
1397 def __init__(self,arg):
1398 """
1399 Initialization of wherePositive `Symbol` with argument ``arg``.
1400
1401 :param arg: argument of function
1402 :type arg: typically `Symbol`
1403 """
1404 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1405
1406 def getMyCode(self,argstrs,format="escript"):
1407 """
1408 Returns program code that can be used to evaluate the symbol.
1409
1410 :param argstrs: a string for each argument representing the argument
1411 for the evaluation
1412 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1413 :param format: specifies the format to be used. At the moment only
1414 "escript", "str" and "text" are supported.
1415 :type format: ``str``
1416 :return: a piece of program code which can be used to evaluate the
1417 expression assuming the values for the arguments are available
1418 :rtype: ``str``
1419 :raise NotImplementedError: if no implementation for the given format
1420 is available
1421 """
1422 if isinstance(argstrs,list):
1423 argstrs=argstrs[0]
1424 if format=="escript" or format=="str" or format=="text":
1425 return "wherePositive(%s)"%argstrs
1426 else:
1427 raise NotImplementedError("WherePositive_Symbol does not provide program code for format %s."%format)
1428
1429 def substitute(self,argvals):
1430 """
1431 Assigns new values to symbols in the definition of the symbol.
1432 The method replaces the `Symbol` u by argvals[u] in the expression
1433 defining this object.
1434
1435 :param argvals: new values assigned to symbols
1436 :type argvals: ``dict`` with keywords of type `Symbol`
1437 :return: result of the substitution process. Operations are executed as
1438 much as possible.
1439 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1440 depending on the degree of substitution
1441 :raise TypeError: if a value for a `Symbol` cannot be substituted
1442 """
1443 if self in argvals:
1444 arg=argvals[self]
1445 if self.isAppropriateValue(arg):
1446 return arg
1447 else:
1448 raise TypeError("%s: new value is not appropriate."%str(self))
1449 else:
1450 arg=self.getSubstitutedArguments(argvals)[0]
1451 return wherePositive(arg)
1452
1453 def whereNegative(arg):
1454 """
1455 Returns mask of negative values of argument ``arg``.
1456
1457 :param arg: argument
1458 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1459 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1460 on the type of ``arg``
1461 :raise TypeError: if the type of the argument is not expected
1462 """
1463 if isinstance(arg,numpy.ndarray):
1464 out=numpy.less(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1465 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1466 return out
1467 elif isinstance(arg,escript.Data):
1468 return arg._whereNegative()
1469 elif isinstance(arg,float):
1470 if arg<0:
1471 return 1.
1472 else:
1473 return 0.
1474 elif isinstance(arg,int):
1475 if arg<0:
1476 return 1.
1477 else:
1478 return 0.
1479 elif isinstance(arg,Symbol):
1480 return WhereNegative_Symbol(arg)
1481 else:
1482 raise TypeError("whereNegative: Unknown argument type.")
1483
1484 class WhereNegative_Symbol(DependendSymbol):
1485 """
1486 `Symbol` representing the result of the mask of negative values function.
1487 """
1488 def __init__(self,arg):
1489 """
1490 Initialization of whereNegative `Symbol` with argument ``arg``.
1491
1492 :param arg: argument of function
1493 :type arg: typically `Symbol`
1494 """
1495 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1496
1497 def getMyCode(self,argstrs,format="escript"):
1498 """
1499 Returns program code that can be used to evaluate the symbol.
1500
1501 :param argstrs: a string for each argument representing the argument
1502 for the evaluation
1503 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1504 :param format: specifies the format to be used. At the moment only
1505 "escript", "str" and "text" are supported.
1506 :type format: ``str``
1507 :return: a piece of program code which can be used to evaluate the
1508 expression assuming the values for the arguments are available
1509 :rtype: ``str``
1510 :raise NotImplementedError: if no implementation for the given format
1511 is available
1512 """
1513 if isinstance(argstrs,list):
1514 argstrs=argstrs[0]
1515 if format=="escript" or format=="str" or format=="text":
1516 return "whereNegative(%s)"%argstrs
1517 else:
1518 raise NotImplementedError("WhereNegative_Symbol does not provide program code for format %s."%format)
1519
1520 def substitute(self,argvals):
1521 """
1522 Assigns new values to symbols in the definition of the symbol.
1523 The method replaces the `Symbol` u by argvals[u] in the expression
1524 defining this object.
1525
1526 :param argvals: new values assigned to symbols
1527 :type argvals: ``dict`` with keywords of type `Symbol`
1528 :return: result of the substitution process. Operations are executed as
1529 much as possible.
1530 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1531 depending on the degree of substitution
1532 :raise TypeError: if a value for a `Symbol` cannot be substituted
1533 """
1534 if self in argvals:
1535 arg=argvals[self]
1536 if self.isAppropriateValue(arg):
1537 return arg
1538 else:
1539 raise TypeError("%s: new value is not appropriate."%str(self))
1540 else:
1541 arg=self.getSubstitutedArguments(argvals)[0]
1542 return whereNegative(arg)
1543
1544 def whereNonNegative(arg):
1545 """
1546 Returns mask of non-negative values of argument ``arg``.
1547
1548 :param arg: argument
1549 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1550 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1551 on the type of ``arg``
1552 :raise TypeError: if the type of the argument is not expected
1553 """
1554 if isinstance(arg,numpy.ndarray):
1555 out=numpy.greater_equal(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1556 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1557 return out
1558 elif isinstance(arg,escript.Data):
1559 return arg._whereNonNegative()
1560 elif isinstance(arg,float):
1561 if arg<0:
1562 return 0.
1563 else:
1564 return 1.
1565 elif isinstance(arg,int):
1566 if arg<0:
1567 return 0.
1568 else:
1569 return 1.
1570 elif isinstance(arg,Symbol):
1571 return 1.-whereNegative(arg)
1572 else:
1573 raise TypeError("whereNonNegative: Unknown argument type.")
1574
1575 def whereNonPositive(arg):
1576 """
1577 Returns mask of non-positive values of argument ``arg``.
1578
1579 :param arg: argument
1580 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1581 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1582 on the type of ``arg``
1583 :raise TypeError: if the type of the argument is not expected
1584 """
1585 if isinstance(arg,numpy.ndarray):
1586 out=numpy.less_equal(arg,numpy.zeros(arg.shape,numpy.float64))*1.
1587 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1588 return out
1589 elif isinstance(arg,escript.Data):
1590 return arg._whereNonPositive()
1591 elif isinstance(arg,float):
1592 if arg>0:
1593 return 0.
1594 else:
1595 return 1.
1596 elif isinstance(arg,int):
1597 if arg>0:
1598 return 0.
1599 else:
1600 return 1.
1601 elif isinstance(arg,Symbol):
1602 return 1.-wherePositive(arg)
1603 else:
1604 raise TypeError("whereNonPositive: Unknown argument type.")
1605
1606 def whereZero(arg,tol=None,rtol=math.sqrt(EPSILON)):
1607 """
1608 Returns mask of zero entries of argument ``arg``.
1609
1610 :param arg: argument
1611 :type arg: ``float``, `escript.Data` , `Symbol` , ``numpy.ndarray``
1612 :param tol: absolute tolerance. Values with absolute value less than tol are accepted
1613 as zero. If ``tol`` is not present ``rtol``*```Lsup` (arg)`` is used.
1614 :type tol: ``float``
1615 :param rtol: relative tolerance used to define the absolute tolerance if ``tol`` is not present.
1616 :type rtol: non-negative ``float``
1617 :rtype: ``float``, `escript.Data` , `Symbol` , ``numpy.ndarray`` depending
1618 on the type of ``arg``
1619 :raise ValueError: if ``rtol`` is non-negative.
1620 :raise TypeError: if the type of the argument is not expected
1621 """
1622 if tol == None:
1623 if not isinstance(arg,Symbol):
1624 if rtol<0: raise ValueError("rtol must be non-negative.")
1625 tol = Lsup(arg)*rtol
1626 else:
1627 tol=0.
1628 if isinstance(arg,numpy.ndarray):
1629 out=numpy.less_equal(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.
1630 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1631 return out
1632 elif isinstance(arg,escript.Data):
1633 return arg._whereZero(tol)
1634 elif isinstance(arg,float):
1635 if abs(arg)<=tol:
1636 return 1.
1637 else:
1638 return 0.
1639 elif isinstance(arg,int):
1640 if abs(float(arg))<=tol:
1641 return 1.
1642 else:
1643 return 0.
1644 elif isinstance(arg,Symbol):
1645 return WhereZero_Symbol(arg,tol)
1646 else:
1647 raise TypeError("whereZero: Unknown argument type.")
1648
1649 class WhereZero_Symbol(DependendSymbol):
1650 """
1651 `Symbol` representing the result of the mask of zero entries function.
1652 """
1653 def __init__(self,arg,tol=0.):
1654 """
1655 Initialization of whereZero `Symbol` with argument ``arg``.
1656
1657 :param arg: argument of function
1658 :type arg: typically `Symbol`
1659 """
1660 DependendSymbol.__init__(self,args=[arg,tol],shape=arg.getShape(),dim=arg.getDim())
1661
1662 def getMyCode(self,argstrs,format="escript"):
1663 """
1664 Returns program code that can be used to evaluate the symbol.
1665
1666 :param argstrs: a string for each argument representing the argument
1667 for the evaluation
1668 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1669 :param format: specifies the format to be used. At the moment only
1670 "escript", "str" and "text" are supported.
1671 :type format: ``str``
1672 :return: a piece of program code which can be used to evaluate the
1673 expression assuming the values for the arguments are available
1674 :rtype: ``str``
1675 :raise NotImplementedError: if no implementation for the given format
1676 is available
1677 """
1678 if format=="escript" or format=="str" or format=="text":
1679 return "whereZero(%s,tol=%s)"%(argstrs[0],argstrs[1])
1680 else:
1681 raise NotImplementedError("WhereZero_Symbol does not provide program code for format %s."%format)
1682
1683 def substitute(self,argvals):
1684 """
1685 Assigns new values to symbols in the definition of the symbol.
1686 The method replaces the `Symbol` u by argvals[u] in the expression
1687 defining this object.
1688
1689 :param argvals: new values assigned to symbols
1690 :type argvals: ``dict`` with keywords of type `Symbol`
1691 :return: result of the substitution process. Operations are executed as
1692 much as possible.
1693 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1694 depending on the degree of substitution
1695 :raise TypeError: if a value for a `Symbol` cannot be substituted
1696 """
1697 if self in argvals:
1698 arg=argvals[self]
1699 if self.isAppropriateValue(arg):
1700 return arg
1701 else:
1702 raise TypeError("%s: new value is not appropriate."%str(self))
1703 else:
1704 arg=self.getSubstitutedArguments(argvals)
1705 return whereZero(arg[0],arg[1])
1706
1707 def whereNonZero(arg,tol=0.):
1708 """
1709 Returns mask of values different from zero of argument ``arg``.
1710
1711 :param arg: argument
1712 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1713 :param tol: absolute tolerance. Values with absolute value less than tol are accepted
1714 as zero. If ``tol`` is not present ``rtol``*```Lsup` (arg)`` is used.
1715 :type tol: ``float``
1716 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1717 on the type of ``arg``
1718 :raise ValueError: if ``rtol`` is non-negative.
1719 :raise TypeError: if the type of the argument is not expected
1720 """
1721 if tol == None:
1722 if not isinstance(arg,Symbol):
1723 if rtol<=0: raise ValueError("rtol must be non-negative.")
1724 tol = Lsup(arg)*rtol
1725 else:
1726 tol=0.
1727 if isinstance(arg,numpy.ndarray):
1728 out=numpy.greater(abs(arg)-tol,numpy.zeros(arg.shape,numpy.float64))*1.
1729 if isinstance(out,float): out=numpy.array(out,dtype=numpy.float64)
1730 return out
1731 elif isinstance(arg,escript.Data):
1732 return arg._whereNonZero(tol)
1733 elif isinstance(arg,float):
1734 if abs(arg)>tol:
1735 return 1.
1736 else:
1737 return 0.
1738 elif isinstance(arg,int):
1739 if abs(float(arg))>tol:
1740 return 1.
1741 else:
1742 return 0.
1743 elif isinstance(arg,Symbol):
1744 return 1.-whereZero(arg,tol)
1745 else:
1746 raise TypeError("whereNonZero: Unknown argument type.")
1747
1748 def erf(arg):
1749 """
1750 Returns the error function *erf* of argument ``arg``.
1751
1752 :param arg: argument
1753 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1754 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1755 on the type of ``arg``
1756 :raise TypeError: if the type of the argument is not expected
1757 """
1758 if isinstance(arg,escript.Data):
1759 return arg._erf()
1760 else:
1761 raise TypeError("erf: Unknown argument type.")
1762
1763 def sin(arg):
1764 """
1765 Returns sine of argument ``arg``.
1766
1767 :param arg: argument
1768 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
1769 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1770 on the type of ``arg``
1771 :raise TypeError: if the type of the argument is not expected
1772 """
1773 if isinstance(arg,numpy.ndarray):
1774 return numpy.sin(arg)
1775 elif isinstance(arg,escript.Data):
1776 return arg._sin()
1777 elif isinstance(arg,float):
1778 return math.sin(arg)
1779 elif isinstance(arg,int):
1780 return math.sin(arg)
1781 elif isinstance(arg,Symbol):
1782 return Sin_Symbol(arg)
1783 else:
1784 raise TypeError("sin: Unknown argument type.")
1785
1786 class Sin_Symbol(DependendSymbol):
1787 """
1788 `Symbol` representing the result of the sine function.
1789 """
1790 def __init__(self,arg):
1791 """
1792 Initialization of sin `Symbol` with argument ``arg``.
1793
1794 :param arg: argument of function
1795 :type arg: typically `Symbol`
1796 """
1797 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1798
1799 def getMyCode(self,argstrs,format="escript"):
1800 """
1801 Returns program code that can be used to evaluate the symbol.
1802
1803 :param argstrs: a string for each argument representing the argument
1804 for the evaluation
1805 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1806 :param format: specifies the format to be used. At the moment only
1807 "escript", "str" and "text" are supported.
1808 :type format: ``str``
1809 :return: a piece of program code which can be used to evaluate the
1810 expression assuming the values for the arguments are available
1811 :rtype: ``str``
1812 :raise NotImplementedError: if no implementation for the given format
1813 is available
1814 """
1815 if isinstance(argstrs,list):
1816 argstrs=argstrs[0]
1817 if format=="escript" or format=="str" or format=="text":
1818 return "sin(%s)"%argstrs
1819 else:
1820 raise NotImplementedError("Sin_Symbol does not provide program code for format %s."%format)
1821
1822 def substitute(self,argvals):
1823 """
1824 Assigns new values to symbols in the definition of the symbol.
1825 The method replaces the `Symbol` u by argvals[u] in the expression
1826 defining this object.
1827
1828 :param argvals: new values assigned to symbols
1829 :type argvals: ``dict`` with keywords of type `Symbol`
1830 :return: result of the substitution process. Operations are executed as
1831 much as possible.
1832 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1833 depending on the degree of substitution
1834 :raise TypeError: if a value for a `Symbol` cannot be substituted
1835 """
1836 if self in argvals:
1837 arg=argvals[self]
1838 if self.isAppropriateValue(arg):
1839 return arg
1840 else:
1841 raise TypeError("%s: new value is not appropriate."%str(self))
1842 else:
1843 arg=self.getSubstitutedArguments(argvals)[0]
1844 return sin(arg)
1845
1846 def diff(self,arg):
1847 """
1848 Differential of this object.
1849
1850 :param arg: the derivative is calculated with respect to ``arg``
1851 :type arg: `escript.Symbol`
1852 :return: derivative with respect to ``arg``
1853 :rtype: typically `Symbol` but other types such as ``float``,
1854 `escript.Data`, ``numpy.ndarray`` are possible
1855 """
1856 if arg==self:
1857 return identity(self.getShape())
1858 else:
1859 myarg=self.getArgument()[0]
1860 val=matchShape(cos(myarg),self.getDifferentiatedArguments(arg)[0])
1861 return val[0]*val[1]
1862
1863 def cos(arg):
1864 """
1865 Returns cosine of argument ``arg``.
1866
1867 :param arg: argument
1868 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1869 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1870 on the type of ``arg``
1871 :raise TypeError: if the type of the argument is not expected
1872 """
1873 if isinstance(arg,numpy.ndarray):
1874 return numpy.cos(arg)
1875 elif isinstance(arg,escript.Data):
1876 return arg._cos()
1877 elif isinstance(arg,float):
1878 return math.cos(arg)
1879 elif isinstance(arg,int):
1880 return math.cos(arg)
1881 elif isinstance(arg,Symbol):
1882 return Cos_Symbol(arg)
1883 else:
1884 raise TypeError("cos: Unknown argument type.")
1885
1886 class Cos_Symbol(DependendSymbol):
1887 """
1888 `Symbol` representing the result of the cosine function.
1889 """
1890 def __init__(self,arg):
1891 """
1892 Initialization of cos `Symbol` with argument ``arg``.
1893
1894 :param arg: argument of function
1895 :type arg: typically `Symbol`
1896 """
1897 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1898
1899 def getMyCode(self,argstrs,format="escript"):
1900 """
1901 Returns program code that can be used to evaluate the symbol.
1902
1903 :param argstrs: a string for each argument representing the argument
1904 for the evaluation
1905 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
1906 :param format: specifies the format to be used. At the moment only
1907 "escript", "str" and "text" are supported.
1908 :type format: ``str``
1909 :return: a piece of program code which can be used to evaluate the
1910 expression assuming the values for the arguments are available
1911 :rtype: ``str``
1912 :raise NotImplementedError: if no implementation for the given format
1913 is available
1914 """
1915 if isinstance(argstrs,list):
1916 argstrs=argstrs[0]
1917 if format=="escript" or format=="str" or format=="text":
1918 return "cos(%s)"%argstrs
1919 else:
1920 raise NotImplementedError("Cos_Symbol does not provide program code for format %s."%format)
1921
1922 def substitute(self,argvals):
1923 """
1924 Assigns new values to symbols in the definition of the symbol.
1925 The method replaces the `Symbol` u by argvals[u] in the expression
1926 defining this object.
1927
1928 :param argvals: new values assigned to symbols
1929 :type argvals: ``dict`` with keywords of type `Symbol`
1930 :return: result of the substitution process. Operations are executed as
1931 much as possible.
1932 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
1933 depending on the degree of substitution
1934 :raise TypeError: if a value for a `Symbol` cannot be substituted
1935 """
1936 if self in argvals:
1937 arg=argvals[self]
1938 if self.isAppropriateValue(arg):
1939 return arg
1940 else:
1941 raise TypeError("%s: new value is not appropriate."%str(self))
1942 else:
1943 arg=self.getSubstitutedArguments(argvals)[0]
1944 return cos(arg)
1945
1946 def diff(self,arg):
1947 """
1948 Differential of this object.
1949
1950 :param arg: the derivative is calculated with respect to ``arg``
1951 :type arg: `escript.Symbol`
1952 :return: derivative with respect to ``arg``
1953 :rtype: typically `Symbol` but other types such as ``float``,
1954 `escript.Data`, ``numpy.ndarray`` are possible
1955 """
1956 if arg==self:
1957 return identity(self.getShape())
1958 else:
1959 myarg=self.getArgument()[0]
1960 val=matchShape(-sin(myarg),self.getDifferentiatedArguments(arg)[0])
1961 return val[0]*val[1]
1962
1963 def tan(arg):
1964 """
1965 Returns tangent of argument ``arg``.
1966
1967 :param arg: argument
1968 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
1969 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
1970 on the type of ``arg``
1971 :raise TypeError: if the type of the argument is not expected
1972 """
1973 if isinstance(arg,numpy.ndarray):
1974 return numpy.tan(arg)
1975 elif isinstance(arg,escript.Data):
1976 return arg._tan()
1977 elif isinstance(arg,float):
1978 return math.tan(arg)
1979 elif isinstance(arg,int):
1980 return math.tan(arg)
1981 elif isinstance(arg,Symbol):
1982 return Tan_Symbol(arg)
1983 else:
1984 raise TypeError("tan: Unknown argument type.")
1985
1986 class Tan_Symbol(DependendSymbol):
1987 """
1988 `Symbol` representing the result of the tangent function.
1989 """
1990 def __init__(self,arg):
1991 """
1992 Initialization of tan `Symbol` with argument ``arg``.
1993
1994 :param arg: argument of function
1995 :type arg: typically `Symbol`
1996 """
1997 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
1998
1999 def getMyCode(self,argstrs,format="escript"):
2000 """
2001 Returns program code that can be used to evaluate the symbol.
2002
2003 :param argstrs: a string for each argument representing the argument
2004 for the evaluation
2005 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2006 :param format: specifies the format to be used. At the moment only
2007 "escript", "str" and "text" are supported.
2008 :type format: ``str``
2009 :return: a piece of program code which can be used to evaluate the
2010 expression assuming the values for the arguments are available
2011 :rtype: ``str``
2012 :raise NotImplementedError: if no implementation for the given format
2013 is available
2014 """
2015 if isinstance(argstrs,list):
2016 argstrs=argstrs[0]
2017 if format=="escript" or format=="str" or format=="text":
2018 return "tan(%s)"%argstrs
2019 else:
2020 raise NotImplementedError("Tan_Symbol does not provide program code for format %s."%format)
2021
2022 def substitute(self,argvals):
2023 """
2024 Assigns new values to symbols in the definition of the symbol.
2025 The method replaces the `Symbol` u by argvals[u] in the expression
2026 defining this object.
2027
2028 :param argvals: new values assigned to symbols
2029 :type argvals: ``dict`` with keywords of type `Symbol`
2030 :return: result of the substitution process. Operations are executed as
2031 much as possible.
2032 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2033 depending on the degree of substitution
2034 :raise TypeError: if a value for a `Symbol` cannot be substituted
2035 """
2036 if self in argvals:
2037 arg=argvals[self]
2038 if self.isAppropriateValue(arg):
2039 return arg
2040 else:
2041 raise TypeError("%s: new value is not appropriate."%str(self))
2042 else:
2043 arg=self.getSubstitutedArguments(argvals)[0]
2044 return tan(arg)
2045
2046 def diff(self,arg):
2047 """
2048 Differential of this object.
2049
2050 :param arg: the derivative is calculated with respect to ``arg``
2051 :type arg: `escript.Symbol`
2052 :return: derivative with respect to ``arg``
2053 :rtype: typically `Symbol` but other types such as ``float``,
2054 `escript.Data`, ``numpy.ndarray`` are possible
2055 """
2056 if arg==self:
2057 return identity(self.getShape())
2058 else:
2059 myarg=self.getArgument()[0]
2060 val=matchShape(1./cos(myarg)**2,self.getDifferentiatedArguments(arg)[0])
2061 return val[0]*val[1]
2062
2063 def asin(arg):
2064 """
2065 Returns the inverse sine of argument ``arg``.
2066
2067 :param arg: argument
2068 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2069 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2070 on the type of ``arg``
2071 :raise TypeError: if the type of the argument is not expected
2072 """
2073 if isinstance(arg,numpy.ndarray):
2074 return numpy.arcsin(arg)
2075 elif isinstance(arg,escript.Data):
2076 return arg._asin()
2077 elif isinstance(arg,float):
2078 return math.asin(arg)
2079 elif isinstance(arg,int):
2080 return math.asin(arg)
2081 elif isinstance(arg,Symbol):
2082 return Asin_Symbol(arg)
2083 else:
2084 raise TypeError("asin: Unknown argument type.")
2085
2086 class Asin_Symbol(DependendSymbol):
2087 """
2088 `Symbol` representing the result of the inverse sine function.
2089 """
2090 def __init__(self,arg):
2091 """
2092 Initialization of asin `Symbol` with argument ``arg``.
2093
2094 :param arg: argument of function
2095 :type arg: typically `Symbol`
2096 """
2097 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2098
2099 def getMyCode(self,argstrs,format="escript"):
2100 """
2101 Returns program code that can be used to evaluate the symbol.
2102
2103 :param argstrs: a string for each argument representing the argument
2104 for the evaluation
2105 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2106 :param format: specifies the format to be used. At the moment only
2107 "escript", "str" and "text" are supported.
2108 :type format: ``str``
2109 :return: a piece of program code which can be used to evaluate the
2110 expression assuming the values for the arguments are available
2111 :rtype: ``str``
2112 :raise NotImplementedError: if no implementation for the given format
2113 is available
2114 """
2115 if isinstance(argstrs,list):
2116 argstrs=argstrs[0]
2117 if format=="escript" or format=="str" or format=="text":
2118 return "asin(%s)"%argstrs
2119 else:
2120 raise NotImplementedError("Asin_Symbol does not provide program code for format %s."%format)
2121
2122 def substitute(self,argvals):
2123 """
2124 Assigns new values to symbols in the definition of the symbol.
2125 The method replaces the `Symbol` u by argvals[u] in the expression
2126 defining this object.
2127
2128 :param argvals: new values assigned to symbols
2129 :type argvals: ``dict`` with keywords of type `Symbol`
2130 :return: result of the substitution process. Operations are executed as
2131 much as possible.
2132 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2133 depending on the degree of substitution
2134 :raise TypeError: if a value for a `Symbol` cannot be substituted
2135 """
2136 if self in argvals:
2137 arg=argvals[self]
2138 if self.isAppropriateValue(arg):
2139 return arg
2140 else:
2141 raise TypeError("%s: new value is not appropriate."%str(self))
2142 else:
2143 arg=self.getSubstitutedArguments(argvals)[0]
2144 return asin(arg)
2145
2146 def diff(self,arg):
2147 """
2148 Differential of this object.
2149
2150 :param arg: the derivative is calculated with respect to ``arg``
2151 :type arg: `escript.Symbol`
2152 :return: derivative with respect to ``arg``
2153 :rtype: typically `Symbol` but other types such as ``float``,
2154 `escript.Data`, ``numpy.ndarray`` are possible
2155 """
2156 if arg==self:
2157 return identity(self.getShape())
2158 else:
2159 myarg=self.getArgument()[0]
2160 val=matchShape(1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2161 return val[0]*val[1]
2162
2163 def acos(arg):
2164 """
2165 Returns the inverse cosine of argument ``arg``.
2166
2167 :param arg: argument
2168 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2169 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2170 on the type of ``arg``
2171 :raise TypeError: if the type of the argument is not expected
2172 """
2173 if isinstance(arg,numpy.ndarray):
2174 return numpy.arccos(arg)
2175 elif isinstance(arg,escript.Data):
2176 return arg._acos()
2177 elif isinstance(arg,float):
2178 return math.acos(arg)
2179 elif isinstance(arg,int):
2180 return math.acos(arg)
2181 elif isinstance(arg,Symbol):
2182 return Acos_Symbol(arg)
2183 else:
2184 raise TypeError("acos: Unknown argument type.")
2185
2186 class Acos_Symbol(DependendSymbol):
2187 """
2188 `Symbol` representing the result of the inverse cosine function.
2189 """
2190 def __init__(self,arg):
2191 """
2192 Initialization of acos `Symbol` with argument ``arg``.
2193
2194 :param arg: argument of function
2195 :type arg: typically `Symbol`
2196 """
2197 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2198
2199 def getMyCode(self,argstrs,format="escript"):
2200 """
2201 Returns program code that can be used to evaluate the symbol.
2202
2203 :param argstrs: a string for each argument representing the argument
2204 for the evaluation
2205 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2206 :param format: specifies the format to be used. At the moment only
2207 "escript", "str" and "text" are supported.
2208 :type format: ``str``
2209 :return: a piece of program code which can be used to evaluate the
2210 expression assuming the values for the arguments are available
2211 :rtype: ``str``
2212 :raise NotImplementedError: if no implementation for the given format
2213 is available
2214 """
2215 if isinstance(argstrs,list):
2216 argstrs=argstrs[0]
2217 if format=="escript" or format=="str" or format=="text":
2218 return "acos(%s)"%argstrs
2219 else:
2220 raise NotImplementedError("Acos_Symbol does not provide program code for format %s."%format)
2221
2222 def substitute(self,argvals):
2223 """
2224 Assigns new values to symbols in the definition of the symbol.
2225 The method replaces the `Symbol` u by argvals[u] in the expression
2226 defining this object.
2227
2228 :param argvals: new values assigned to symbols
2229 :type argvals: ``dict`` with keywords of type `Symbol`
2230 :return: result of the substitution process. Operations are executed as
2231 much as possible.
2232 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2233 depending on the degree of substitution
2234 :raise TypeError: if a value for a `Symbol` cannot be substituted
2235 """
2236 if self in argvals:
2237 arg=argvals[self]
2238 if self.isAppropriateValue(arg):
2239 return arg
2240 else:
2241 raise TypeError("%s: new value is not appropriate."%str(self))
2242 else:
2243 arg=self.getSubstitutedArguments(argvals)[0]
2244 return acos(arg)
2245
2246 def diff(self,arg):
2247 """
2248 Differential of this object.
2249
2250 :param arg: the derivative is calculated with respect to ``arg``
2251 :type arg: `escript.Symbol`
2252 :return: derivative with respect to ``arg``
2253 :rtype: typically `Symbol` but other types such as ``float``,
2254 `escript.Data`, ``numpy.ndarray`` are possible
2255 """
2256 if arg==self:
2257 return identity(self.getShape())
2258 else:
2259 myarg=self.getArgument()[0]
2260 val=matchShape(-1./sqrt(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2261 return val[0]*val[1]
2262
2263 def atan(arg):
2264 """
2265 Returns inverse tangent of argument ``arg``.
2266
2267 :param arg: argument
2268 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2269 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2270 on the type of ``arg``
2271 :raise TypeError: if the type of the argument is not expected
2272 """
2273 if isinstance(arg,numpy.ndarray):
2274 return numpy.arctan(arg)
2275 elif isinstance(arg,escript.Data):
2276 return arg._atan()
2277 elif isinstance(arg,float):
2278 return math.atan(arg)
2279 elif isinstance(arg,int):
2280 return math.atan(arg)
2281 elif isinstance(arg,Symbol):
2282 return Atan_Symbol(arg)
2283 else:
2284 raise TypeError("atan: Unknown argument type.")
2285
2286 class Atan_Symbol(DependendSymbol):
2287 """
2288 `Symbol` representing the result of the inverse tangent function.
2289 """
2290 def __init__(self,arg):
2291 """
2292 Initialization of atan `Symbol` with argument ``arg``.
2293
2294 :param arg: argument of function
2295 :type arg: typically `Symbol`
2296 """
2297 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2298
2299 def getMyCode(self,argstrs,format="escript"):
2300 """
2301 Returns program code that can be used to evaluate the symbol.
2302
2303 :param argstrs: a string for each argument representing the argument
2304 for the evaluation
2305 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2306 :param format: specifies the format to be used. At the moment only
2307 "escript", "str" and "text" are supported.
2308 :type format: ``str``
2309 :return: a piece of program code which can be used to evaluate the
2310 expression assuming the values for the arguments are available
2311 :rtype: ``str``
2312 :raise NotImplementedError: if no implementation for the given format
2313 is available
2314 """
2315 if isinstance(argstrs,list):
2316 argstrs=argstrs[0]
2317 if format=="escript" or format=="str" or format=="text":
2318 return "atan(%s)"%argstrs
2319 else:
2320 raise NotImplementedError("Atan_Symbol does not provide program code for format %s."%format)
2321
2322 def substitute(self,argvals):
2323 """
2324 Assigns new values to symbols in the definition of the symbol.
2325 The method replaces the `Symbol` u by argvals[u] in the expression
2326 defining this object.
2327
2328 :param argvals: new values assigned to symbols
2329 :type argvals: ``dict`` with keywords of type `Symbol`
2330 :return: result of the substitution process. Operations are executed as
2331 much as possible.
2332 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2333 depending on the degree of substitution
2334 :raise TypeError: if a value for a `Symbol` cannot be substituted
2335 """
2336 if self in argvals:
2337 arg=argvals[self]
2338 if self.isAppropriateValue(arg):
2339 return arg
2340 else:
2341 raise TypeError("%s: new value is not appropriate."%str(self))
2342 else:
2343 arg=self.getSubstitutedArguments(argvals)[0]
2344 return atan(arg)
2345
2346 def diff(self,arg):
2347 """
2348 Differential of this object.
2349
2350 :param arg: the derivative is calculated with respect to ``arg``
2351 :type arg: `escript.Symbol`
2352 :return: derivative with respect to ``arg``
2353 :rtype: typically `Symbol` but other types such as ``float``,
2354 `escript.Data`, ``numpy.ndarray`` are possible
2355 """
2356 if arg==self:
2357 return identity(self.getShape())
2358 else:
2359 myarg=self.getArgument()[0]
2360 val=matchShape(1./(1+myarg**2),self.getDifferentiatedArguments(arg)[0])
2361 return val[0]*val[1]
2362
2363 def sinh(arg):
2364 """
2365 Returns the hyperbolic sine of argument ``arg``.
2366
2367 :param arg: argument
2368 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2369 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2370 on the type of ``arg``
2371 :raise TypeError: if the type of the argument is not expected
2372 """
2373 if isinstance(arg,numpy.ndarray):
2374 return numpy.sinh(arg)
2375 elif isinstance(arg,escript.Data):
2376 return arg._sinh()
2377 elif isinstance(arg,float):
2378 return math.sinh(arg)
2379 elif isinstance(arg,int):
2380 return math.sinh(arg)
2381 elif isinstance(arg,Symbol):
2382 return Sinh_Symbol(arg)
2383 else:
2384 raise TypeError("sinh: Unknown argument type.")
2385
2386 class Sinh_Symbol(DependendSymbol):
2387 """
2388 `Symbol` representing the result of the hyperbolic sine function.
2389 """
2390 def __init__(self,arg):
2391 """
2392 Initialization of sinh `Symbol` with argument ``arg``.
2393
2394 :param arg: argument of function
2395 :type arg: typically `Symbol`
2396 """
2397 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2398
2399 def getMyCode(self,argstrs,format="escript"):
2400 """
2401 Returns program code that can be used to evaluate the symbol.
2402
2403 :param argstrs: a string for each argument representing the argument
2404 for the evaluation
2405 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2406 :param format: specifies the format to be used. At the moment only
2407 "escript", "str" and "text" are supported.
2408 :type format: ``str``
2409 :return: a piece of program code which can be used to evaluate the
2410 expression assuming the values for the arguments are available
2411 :rtype: ``str``
2412 :raise NotImplementedError: if no implementation for the given format
2413 is available
2414 """
2415 if isinstance(argstrs,list):
2416 argstrs=argstrs[0]
2417 if format=="escript" or format=="str" or format=="text":
2418 return "sinh(%s)"%argstrs
2419 else:
2420 raise NotImplementedError("Sinh_Symbol does not provide program code for format %s."%format)
2421
2422 def substitute(self,argvals):
2423 """
2424 Assigns new values to symbols in the definition of the symbol.
2425 The method replaces the `Symbol` u by argvals[u] in the expression
2426 defining this object.
2427
2428 :param argvals: new values assigned to symbols
2429 :type argvals: ``dict`` with keywords of type `Symbol`
2430 :return: result of the substitution process. Operations are executed as
2431 much as possible.
2432 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2433 depending on the degree of substitution
2434 :raise TypeError: if a value for a `Symbol` cannot be substituted
2435 """
2436 if self in argvals:
2437 arg=argvals[self]
2438 if self.isAppropriateValue(arg):
2439 return arg
2440 else:
2441 raise TypeError("%s: new value is not appropriate."%str(self))
2442 else:
2443 arg=self.getSubstitutedArguments(argvals)[0]
2444 return sinh(arg)
2445
2446 def diff(self,arg):
2447 """
2448 Differential of this object.
2449
2450 :param arg: the derivative is calculated with respect to ``arg``
2451 :type arg: `escript.Symbol`
2452 :return: derivative with respect to ``arg``
2453 :rtype: typically `Symbol` but other types such as ``float``,
2454 `escript.Data`, ``numpy.ndarray`` are possible
2455 """
2456 if arg==self:
2457 return identity(self.getShape())
2458 else:
2459 myarg=self.getArgument()[0]
2460 val=matchShape(cosh(myarg),self.getDifferentiatedArguments(arg)[0])
2461 return val[0]*val[1]
2462
2463 def cosh(arg):
2464 """
2465 Returns the hyperbolic cosine of argument ``arg``.
2466
2467 :param arg: argument
2468 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2469 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2470 on the type of ``arg``
2471 :raise TypeError: if the type of the argument is not expected
2472 """
2473 if isinstance(arg,numpy.ndarray):
2474 return numpy.cosh(arg)
2475 elif isinstance(arg,escript.Data):
2476 return arg._cosh()
2477 elif isinstance(arg,float):
2478 return math.cosh(arg)
2479 elif isinstance(arg,int):
2480 return math.cosh(arg)
2481 elif isinstance(arg,Symbol):
2482 return Cosh_Symbol(arg)
2483 else:
2484 raise TypeError("cosh: Unknown argument type.")
2485
2486 class Cosh_Symbol(DependendSymbol):
2487 """
2488 `Symbol` representing the result of the hyperbolic cosine function.
2489 """
2490 def __init__(self,arg):
2491 """
2492 Initialization of cosh `Symbol` with argument ``arg``.
2493
2494 :param arg: argument of function
2495 :type arg: typically `Symbol`
2496 """
2497 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2498
2499 def getMyCode(self,argstrs,format="escript"):
2500 """
2501 Returns program code that can be used to evaluate the symbol.
2502
2503 :param argstrs: a string for each argument representing the argument
2504 for the evaluation
2505 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2506 :param format: specifies the format to be used. At the moment only
2507 "escript", "str" and "text" are supported.
2508 :type format: ``str``
2509 :return: a piece of program code which can be used to evaluate the
2510 expression assuming the values for the arguments are available
2511 :rtype: ``str``
2512 :raise NotImplementedError: if no implementation for the given format
2513 is available
2514 """
2515 if isinstance(argstrs,list):
2516 argstrs=argstrs[0]
2517 if format=="escript" or format=="str" or format=="text":
2518 return "cosh(%s)"%argstrs
2519 else:
2520 raise NotImplementedError("Cosh_Symbol does not provide program code for format %s."%format)
2521
2522 def substitute(self,argvals):
2523 """
2524 Assigns new values to symbols in the definition of the symbol.
2525 The method replaces the `Symbol` u by argvals[u] in the expression
2526 defining this object.
2527
2528 :param argvals: new values assigned to symbols
2529 :type argvals: ``dict`` with keywords of type `Symbol`
2530 :return: result of the substitution process. Operations are executed as
2531 much as possible.
2532 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2533 depending on the degree of substitution
2534 :raise TypeError: if a value for a `Symbol` cannot be substituted
2535 """
2536 if self in argvals:
2537 arg=argvals[self]
2538 if self.isAppropriateValue(arg):
2539 return arg
2540 else:
2541 raise TypeError("%s: new value is not appropriate."%str(self))
2542 else:
2543 arg=self.getSubstitutedArguments(argvals)[0]
2544 return cosh(arg)
2545
2546 def diff(self,arg):
2547 """
2548 Differential of this object.
2549
2550 :param arg: the derivative is calculated with respect to ``arg``
2551 :type arg: `escript.Symbol`
2552 :return: derivative with respect to ``arg``
2553 :rtype: typically `Symbol` but other types such as ``float``,
2554 `escript.Data`, ``numpy.ndarray`` are possible
2555 """
2556 if arg==self:
2557 return identity(self.getShape())
2558 else:
2559 myarg=self.getArgument()[0]
2560 val=matchShape(sinh(myarg),self.getDifferentiatedArguments(arg)[0])
2561 return val[0]*val[1]
2562
2563 def tanh(arg):
2564 """
2565 Returns the hyperbolic tangent of argument ``arg``.
2566
2567 :param arg: argument
2568 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2569 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2570 on the type of ``arg``
2571 :raise TypeError: if the type of the argument is not expected
2572 """
2573 if isinstance(arg,numpy.ndarray):
2574 return numpy.tanh(arg)
2575 elif isinstance(arg,escript.Data):
2576 return arg._tanh()
2577 elif isinstance(arg,float):
2578 return math.tanh(arg)
2579 elif isinstance(arg,int):
2580 return math.tanh(arg)
2581 elif isinstance(arg,Symbol):
2582 return Tanh_Symbol(arg)
2583 else:
2584 raise TypeError("tanh: Unknown argument type.")
2585
2586 class Tanh_Symbol(DependendSymbol):
2587 """
2588 `Symbol` representing the result of the hyperbolic tangent function.
2589 """
2590 def __init__(self,arg):
2591 """
2592 Initialization of tanh `Symbol` with argument ``arg``.
2593
2594 :param arg: argument of function
2595 :type arg: typically `Symbol`
2596 """
2597 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2598
2599 def getMyCode(self,argstrs,format="escript"):
2600 """
2601 Returns program code that can be used to evaluate the symbol.
2602
2603 :param argstrs: a string for each argument representing the argument
2604 for the evaluation
2605 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2606 :param format: specifies the format to be used. At the moment only
2607 "escript", "str" and "text" are supported.
2608 :type format: ``str``
2609 :return: a piece of program code which can be used to evaluate the
2610 expression assuming the values for the arguments are available
2611 :rtype: ``str``
2612 :raise NotImplementedError: if no implementation for the given format
2613 is available
2614 """
2615 if isinstance(argstrs,list):
2616 argstrs=argstrs[0]
2617 if format=="escript" or format=="str" or format=="text":
2618 return "tanh(%s)"%argstrs
2619 else:
2620 raise NotImplementedError("Tanh_Symbol does not provide program code for format %s."%format)
2621
2622 def substitute(self,argvals):
2623 """
2624 Assigns new values to symbols in the definition of the symbol.
2625 The method replaces the `Symbol` u by argvals[u] in the expression
2626 defining this object.
2627
2628 :param argvals: new values assigned to symbols
2629 :type argvals: ``dict`` with keywords of type `Symbol`
2630 :return: result of the substitution process. Operations are executed as
2631 much as possible.
2632 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2633 depending on the degree of substitution
2634 :raise TypeError: if a value for a `Symbol` cannot be substituted
2635 """
2636 if self in argvals:
2637 arg=argvals[self]
2638 if self.isAppropriateValue(arg):
2639 return arg
2640 else:
2641 raise TypeError("%s: new value is not appropriate."%str(self))
2642 else:
2643 arg=self.getSubstitutedArguments(argvals)[0]
2644 return tanh(arg)
2645
2646 def diff(self,arg):
2647 """
2648 Differential of this object.
2649
2650 :param arg: the derivative is calculated with respect to ``arg``
2651 :type arg: `escript.Symbol`
2652 :return: derivative with respect to ``arg``
2653 :rtype: typically `Symbol` but other types such as ``float``,
2654 `escript.Data`, ``numpy.ndarray`` are possible
2655 """
2656 if arg==self:
2657 return identity(self.getShape())
2658 else:
2659 myarg=self.getArgument()[0]
2660 val=matchShape(1./cosh(myarg)**2,self.getDifferentiatedArguments(arg)[0])
2661 return val[0]*val[1]
2662
2663 def asinh(arg):
2664 """
2665 Returns the inverse hyperbolic sine of argument ``arg``.
2666
2667 :param arg: argument
2668 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2669 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2670 on the type of ``arg``
2671 :raise TypeError: if the type of the argument is not expected
2672 """
2673 if isinstance(arg,numpy.ndarray):
2674 return numpy.arcsinh(arg)
2675 elif isinstance(arg,escript.Data):
2676 return arg._asinh()
2677 elif isinstance(arg,float):
2678 return numpy.arcsinh(arg)
2679 elif isinstance(arg,int):
2680 return numpy.arcsinh(float(arg))
2681 elif isinstance(arg,Symbol):
2682 return Asinh_Symbol(arg)
2683 else:
2684 raise TypeError("asinh: Unknown argument type.")
2685
2686 class Asinh_Symbol(DependendSymbol):
2687 """
2688 `Symbol` representing the result of the inverse hyperbolic sine function.
2689 """
2690 def __init__(self,arg):
2691 """
2692 Initialization of asinh `Symbol` with argument ``arg``.
2693
2694 :param arg: argument of function
2695 :type arg: typically `Symbol`
2696 """
2697 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2698
2699 def getMyCode(self,argstrs,format="escript"):
2700 """
2701 Returns program code that can be used to evaluate the symbol.
2702
2703 :param argstrs: a string for each argument representing the argument
2704 for the evaluation
2705 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2706 :param format: specifies the format to be used. At the moment only
2707 "escript", "str" and "text" are supported.
2708 :type format: ``str``
2709 :return: a piece of program code which can be used to evaluate the
2710 expression assuming the values for the arguments are available
2711 :rtype: ``str``
2712 :raise NotImplementedError: if no implementation for the given format
2713 is available
2714 """
2715 if isinstance(argstrs,list):
2716 argstrs=argstrs[0]
2717 if format=="escript" or format=="str" or format=="text":
2718 return "asinh(%s)"%argstrs
2719 else:
2720 raise NotImplementedError("Asinh_Symbol does not provide program code for format %s."%format)
2721
2722 def substitute(self,argvals):
2723 """
2724 Assigns new values to symbols in the definition of the symbol.
2725 The method replaces the `Symbol` u by argvals[u] in the expression
2726 defining this object.
2727
2728 :param argvals: new values assigned to symbols
2729 :type argvals: ``dict`` with keywords of type `Symbol`
2730 :return: result of the substitution process. Operations are executed as
2731 much as possible.
2732 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2733 depending on the degree of substitution
2734 :raise TypeError: if a value for a `Symbol` cannot be substituted
2735 """
2736 if self in argvals:
2737 arg=argvals[self]
2738 if self.isAppropriateValue(arg):
2739 return arg
2740 else:
2741 raise TypeError("%s: new value is not appropriate."%str(self))
2742 else:
2743 arg=self.getSubstitutedArguments(argvals)[0]
2744 return asinh(arg)
2745
2746 def diff(self,arg):
2747 """
2748 Differential of this object.
2749
2750 :param arg: the derivative is calculated with respect to ``arg``
2751 :type arg: `escript.Symbol`
2752 :return: derivative with respect to ``arg``
2753 :rtype: typically `Symbol` but other types such as ``float``,
2754 `escript.Data`, ``numpy.ndarray`` are possible
2755 """
2756 if arg==self:
2757 return identity(self.getShape())
2758 else:
2759 myarg=self.getArgument()[0]
2760 val=matchShape(1./sqrt(myarg**2+1),self.getDifferentiatedArguments(arg)[0])
2761 return val[0]*val[1]
2762
2763 def acosh(arg):
2764 """
2765 Returns the inverse hyperbolic cosine of argument ``arg``.
2766
2767 :param arg: argument
2768 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2769 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2770 on the type of ``arg``
2771 :raise TypeError: if the type of the argument is not expected
2772 """
2773 if isinstance(arg,numpy.ndarray):
2774 return numpy.arccosh(arg)
2775 elif isinstance(arg,escript.Data):
2776 return arg._acosh()
2777 elif isinstance(arg,float):
2778 return numpy.arccosh(arg)
2779 elif isinstance(arg,int):
2780 return numpy.arccosh(float(arg))
2781 elif isinstance(arg,Symbol):
2782 return Acosh_Symbol(arg)
2783 else:
2784 raise TypeError("acosh: Unknown argument type.")
2785
2786 class Acosh_Symbol(DependendSymbol):
2787 """
2788 `Symbol` representing the result of the inverse hyperbolic cosine function.
2789 """
2790 def __init__(self,arg):
2791 """
2792 Initialization of acosh `Symbol` with argument ``arg``.
2793
2794 :param arg: argument of function
2795 :type arg: typically `Symbol`
2796 """
2797 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2798
2799 def getMyCode(self,argstrs,format="escript"):
2800 """
2801 Returns program code that can be used to evaluate the symbol.
2802
2803 :param argstrs: a string for each argument representing the argument
2804 for the evaluation
2805 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2806 :param format: specifies the format to be used. At the moment only
2807 "escript", "str" and "text" are supported.
2808 :type format: ``str``
2809 :return: a piece of program code which can be used to evaluate the
2810 expression assuming the values for the arguments are available
2811 :rtype: ``str``
2812 :raise NotImplementedError: if no implementation for the given format
2813 is available
2814 """
2815 if isinstance(argstrs,list):
2816 argstrs=argstrs[0]
2817 if format=="escript" or format=="str" or format=="text":
2818 return "acosh(%s)"%argstrs
2819 else:
2820 raise NotImplementedError("Acosh_Symbol does not provide program code for format %s."%format)
2821
2822 def substitute(self,argvals):
2823 """
2824 Assigns new values to symbols in the definition of the symbol.
2825 The method replaces the `Symbol` u by argvals[u] in the expression
2826 defining this object.
2827
2828 :param argvals: new values assigned to symbols
2829 :type argvals: ``dict`` with keywords of type `Symbol`
2830 :return: result of the substitution process. Operations are executed as
2831 much as possible.
2832 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2833 depending on the degree of substitution
2834 :raise TypeError: if a value for a `Symbol` cannot be substituted
2835 """
2836 if self in argvals:
2837 arg=argvals[self]
2838 if self.isAppropriateValue(arg):
2839 return arg
2840 else:
2841 raise TypeError("%s: new value is not appropriate."%str(self))
2842 else:
2843 arg=self.getSubstitutedArguments(argvals)[0]
2844 return acosh(arg)
2845
2846 def diff(self,arg):
2847 """
2848 Differential of this object.
2849
2850 :param arg: the derivative is calculated with respect to ``arg``
2851 :type arg: `escript.Symbol`
2852 :return: derivative with respect to ``arg``
2853 :rtype: typically `Symbol` but other types such as ``float``,
2854 `escript.Data`, ``numpy.ndarray`` are possible
2855 """
2856 if arg==self:
2857 return identity(self.getShape())
2858 else:
2859 myarg=self.getArgument()[0]
2860 val=matchShape(1./sqrt(myarg**2-1),self.getDifferentiatedArguments(arg)[0])
2861 return val[0]*val[1]
2862
2863 def atanh(arg):
2864 """
2865 Returns the inverse hyperbolic tangent of argument ``arg``.
2866
2867 :param arg: argument
2868 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
2869 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2870 on the type of ``arg``
2871 :raise TypeError: if the type of the argument is not expected
2872 """
2873 if isinstance(arg,numpy.ndarray):
2874 return numpy.arctanh(arg)
2875 elif isinstance(arg,escript.Data):
2876 return arg._atanh()
2877 elif isinstance(arg,float):
2878 return numpy.arctanh(arg)
2879 elif isinstance(arg,int):
2880 return numpy.arctanh(float(arg))
2881 elif isinstance(arg,Symbol):
2882 return Atanh_Symbol(arg)
2883 else:
2884 raise TypeError("atanh: Unknown argument type.")
2885
2886 class Atanh_Symbol(DependendSymbol):
2887 """
2888 `Symbol` representing the result of the inverse hyperbolic tangent function.
2889 """
2890 def __init__(self,arg):
2891 """
2892 Initialization of atanh `Symbol` with argument ``arg``.
2893
2894 :param arg: argument of function
2895 :type arg: typically `Symbol`
2896 """
2897 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2898
2899 def getMyCode(self,argstrs,format="escript"):
2900 """
2901 Returns program code that can be used to evaluate the symbol.
2902
2903 :param argstrs: a string for each argument representing the argument
2904 for the evaluation
2905 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
2906 :param format: specifies the format to be used. At the moment only
2907 "escript", "str" and "text" are supported.
2908 :type format: ``str``
2909 :return: a piece of program code which can be used to evaluate the
2910 expression assuming the values for the arguments are available
2911 :rtype: ``str``
2912 :raise NotImplementedError: if no implementation for the given format
2913 is available
2914 """
2915 if isinstance(argstrs,list):
2916 argstrs=argstrs[0]
2917 if format=="escript" or format=="str" or format=="text":
2918 return "atanh(%s)"%argstrs
2919 else:
2920 raise NotImplementedError("Atanh_Symbol does not provide program code for format %s."%format)
2921
2922 def substitute(self,argvals):
2923 """
2924 Assigns new values to symbols in the definition of the symbol.
2925 The method replaces the `Symbol` u by argvals[u] in the expression
2926 defining this object.
2927
2928 :param argvals: new values assigned to symbols
2929 :type argvals: ``dict`` with keywords of type `Symbol`
2930 :return: result of the substitution process. Operations are executed as
2931 much as possible.
2932 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
2933 depending on the degree of substitution
2934 :raise TypeError: if a value for a `Symbol` cannot be substituted
2935 """
2936 if self in argvals:
2937 arg=argvals[self]
2938 if self.isAppropriateValue(arg):
2939 return arg
2940 else:
2941 raise TypeError("%s: new value is not appropriate."%str(self))
2942 else:
2943 arg=self.getSubstitutedArguments(argvals)[0]
2944 return atanh(arg)
2945
2946 def diff(self,arg):
2947 """
2948 Differential of this object.
2949
2950 :param arg: the derivative is calculated with respect to ``arg``
2951 :type arg: `escript.Symbol`
2952 :return: derivative with respect to ``arg``
2953 :rtype: typically `Symbol` but other types such as ``float``,
2954 `escript.Data`, ``numpy.ndarray`` are possible
2955 """
2956 if arg==self:
2957 return identity(self.getShape())
2958 else:
2959 myarg=self.getArgument()[0]
2960 val=matchShape(1./(1.-myarg**2),self.getDifferentiatedArguments(arg)[0])
2961 return val[0]*val[1]
2962
2963 def exp(arg):
2964 """
2965 Returns *e* to the power of argument ``arg``.
2966
2967 :param arg: argument
2968 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
2969 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
2970 on the type of arg
2971 :raise TypeError: if the type of the argument is not expected
2972 """
2973 if isinstance(arg,numpy.ndarray):
2974 return numpy.exp(arg)
2975 elif isinstance(arg,escript.Data):
2976 return arg._exp()
2977 elif isinstance(arg,float):
2978 return math.exp(arg)
2979 elif isinstance(arg,int):
2980 return math.exp(arg)
2981 elif isinstance(arg,Symbol):
2982 return Exp_Symbol(arg)
2983 else:
2984 raise TypeError("exp: Unknown argument type.")
2985
2986 class Exp_Symbol(DependendSymbol):
2987 """
2988 `Symbol` representing the result of the exponential function.
2989 """
2990 def __init__(self,arg):
2991 """
2992 Initialization of exp `Symbol` with argument ``arg``.
2993
2994 :param arg: argument of function
2995 :type arg: typically `Symbol`
2996 """
2997 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
2998
2999 def getMyCode(self,argstrs,format="escript"):
3000 """
3001 Returns program code that can be used to evaluate the symbol.
3002
3003 :param argstrs: a string for each argument representing the argument
3004 for the evaluation
3005 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3006 :param format: specifies the format to be used. At the moment only
3007 "escript", "str" and "text" are supported.
3008 :type format: ``str``
3009 :return: a piece of program code which can be used to evaluate the
3010 expression assuming the values for the arguments are available
3011 :rtype: ``str``
3012 :raise NotImplementedError: if no implementation for the given format
3013 is available
3014 """
3015 if isinstance(argstrs,list):
3016 argstrs=argstrs[0]
3017 if format=="escript" or format=="str" or format=="text":
3018 return "exp(%s)"%argstrs
3019 else:
3020 raise NotImplementedError("Exp_Symbol does not provide program code for format %s."%format)
3021
3022 def substitute(self,argvals):
3023 """
3024 Assigns new values to symbols in the definition of the symbol.
3025 The method replaces the `Symbol` u by argvals[u] in the expression
3026 defining this object.
3027
3028 :param argvals: new values assigned to symbols
3029 :type argvals: ``dict`` with keywords of type `Symbol`
3030 :return: result of the substitution process. Operations are executed as
3031 much as possible.
3032 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3033 depending on the degree of substitution
3034 :raise TypeError: if a value for a `Symbol` cannot be substituted
3035 """
3036 if self in argvals:
3037 arg=argvals[self]
3038 if self.isAppropriateValue(arg):
3039 return arg
3040 else:
3041 raise TypeError("%s: new value is not appropriate."%str(self))
3042 else:
3043 arg=self.getSubstitutedArguments(argvals)[0]
3044 return exp(arg)
3045
3046 def diff(self,arg):
3047 """
3048 Differential of this object.
3049
3050 :param arg: the derivative is calculated with respect to ``arg``
3051 :type arg: `escript.Symbol`
3052 :return: derivative with respect to ``arg``
3053 :rtype: typically `Symbol` but other types such as ``float``,
3054 `escript.Data`, ``numpy.ndarray`` are possible
3055 """
3056 if arg==self:
3057 return identity(self.getShape())
3058 else:
3059 myarg=self.getArgument()[0]
3060 val=matchShape(self,self.getDifferentiatedArguments(arg)[0])
3061 return val[0]*val[1]
3062
3063 def sqrt(arg):
3064 """
3065 Returns the square root of argument ``arg``.
3066
3067 :param arg: argument
3068 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3069 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3070 depending on the type of ``arg``
3071 :raise TypeError: if the type of the argument is not expected
3072 """
3073 if isinstance(arg,numpy.ndarray):
3074 return numpy.sqrt(arg)
3075 elif isinstance(arg,escript.Data):
3076 return arg._sqrt()
3077 elif isinstance(arg,float):
3078 return math.sqrt(arg)
3079 elif isinstance(arg,int):
3080 return math.sqrt(arg)
3081 elif isinstance(arg,Symbol):
3082 return Sqrt_Symbol(arg)
3083 else:
3084 raise TypeError("sqrt: Unknown argument type.")
3085
3086 class Sqrt_Symbol(DependendSymbol):
3087 """
3088 `Symbol` representing the result of the square root function.
3089 """
3090 def __init__(self,arg):
3091 """
3092 Initialization of sqrt `Symbol` with argument ``arg``.
3093
3094 :param arg: argument of function
3095 :type arg: typically `Symbol`
3096 """
3097 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
3098
3099 def getMyCode(self,argstrs,format="escript"):
3100 """
3101 Returns program code that can be used to evaluate the symbol.
3102
3103 :param argstrs: a string for each argument representing the argument
3104 for the evaluation
3105 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3106 :param format: specifies the format to be used. At the moment only
3107 "escript", "str" and "text" are supported.
3108 :type format: ``str``
3109 :return: a piece of program code which can be used to evaluate the
3110 expression assuming the values for the arguments are available
3111 :rtype: ``str``
3112 :raise NotImplementedError: if no implementation for the given format
3113 is available
3114 """
3115 if isinstance(argstrs,list):
3116 argstrs=argstrs[0]
3117 if format=="escript" or format=="str" or format=="text":
3118 return "sqrt(%s)"%argstrs
3119 else:
3120 raise NotImplementedError("Sqrt_Symbol does not provide program code for format %s."%format)
3121
3122 def substitute(self,argvals):
3123 """
3124 Assigns new values to symbols in the definition of the symbol.
3125 The method replaces the `Symbol` u by argvals[u] in the expression
3126 defining this object.
3127
3128 :param argvals: new values assigned to symbols
3129 :type argvals: ``dict`` with keywords of type `Symbol`
3130 :return: result of the substitution process. Operations are executed as
3131 much as possible.
3132 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3133 depending on the degree of substitution
3134 :raise TypeError: if a value for a `Symbol` cannot be substituted
3135 """
3136 if self in argvals:
3137 arg=argvals[self]
3138 if self.isAppropriateValue(arg):
3139 return arg
3140 else:
3141 raise TypeError("%s: new value is not appropriate."%str(self))
3142 else:
3143 arg=self.getSubstitutedArguments(argvals)[0]
3144 return sqrt(arg)
3145
3146 def diff(self,arg):
3147 """
3148 Differential of this object.
3149
3150 :param arg: the derivative is calculated with respect to ``arg``
3151 :type arg: `escript.Symbol`
3152 :return: derivative with respect to ``arg``
3153 :rtype: typically `Symbol` but other types such as ``float``,
3154 `escript.Data`, ``numpy.ndarray`` are possible
3155 """
3156 if arg==self:
3157 return identity(self.getShape())
3158 else:
3159 myarg=self.getArgument()[0]
3160 val=matchShape(0.5/self,self.getDifferentiatedArguments(arg)[0])
3161 return val[0]*val[1]
3162
3163 def log(arg):
3164 """
3165 Returns the natural logarithm of argument ``arg``.
3166
3167 :param arg: argument
3168 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``.
3169 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
3170 on the type of ``arg``
3171 :raise TypeError: if the type of the argument is not expected
3172 """
3173 if isinstance(arg,numpy.ndarray):
3174 return numpy.log(arg)
3175 elif isinstance(arg,escript.Data):
3176 return arg._log()
3177 elif isinstance(arg,float):
3178 return math.log(arg)
3179 elif isinstance(arg,int):
3180 return math.log(arg)
3181 elif isinstance(arg,Symbol):
3182 return Log_Symbol(arg)
3183 else:
3184 raise TypeError("log: Unknown argument type.")
3185
3186 class Log_Symbol(DependendSymbol):
3187 """
3188 `Symbol` representing the result of the natural logarithm function.
3189 """
3190 def __init__(self,arg):
3191 """
3192 Initialization of log `Symbol` with argument ``arg``.
3193
3194 :param arg: argument of function
3195 :type arg: typically `Symbol`
3196 """
3197 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
3198
3199 def getMyCode(self,argstrs,format="escript"):
3200 """
3201 Returns program code that can be used to evaluate the symbol.
3202
3203 :param argstrs: a string for each argument representing the argument
3204 for the evaluation
3205 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3206 :param format: specifies the format to be used. At the moment only
3207 "escript", "str" and "text" are supported.
3208 :type format: ``str``
3209 :return: a piece of program code which can be used to evaluate the
3210 expression assuming the values for the arguments are available
3211 :rtype: ``str``
3212 :raise NotImplementedError: if no implementation for the given format
3213 is available
3214 """
3215 if isinstance(argstrs,list):
3216 argstrs=argstrs[0]
3217 if format=="escript" or format=="str" or format=="text":
3218 return "log(%s)"%argstrs
3219 else:
3220 raise NotImplementedError("Log_Symbol does not provide program code for format %s."%format)
3221
3222 def substitute(self,argvals):
3223 """
3224 Assigns new values to symbols in the definition of the symbol.
3225 The method replaces the `Symbol` u by argvals[u] in the expression
3226 defining this object.
3227
3228 :param argvals: new values assigned to symbols
3229 :type argvals: ``dict`` with keywords of type `Symbol`
3230 :return: result of the substitution process. Operations are executed as
3231 much as possible.
3232 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3233 depending on the degree of substitution
3234 :raise TypeError: if a value for a `Symbol` cannot be substituted
3235 """
3236 if self in argvals:
3237 arg=argvals[self]
3238 if self.isAppropriateValue(arg):
3239 return arg
3240 else:
3241 raise TypeError("%s: new value is not appropriate."%str(self))
3242 else:
3243 arg=self.getSubstitutedArguments(argvals)[0]
3244 return log(arg)
3245
3246 def diff(self,arg):
3247 """
3248 Differential of this object.
3249
3250 :param arg: the derivative is calculated with respect to ``arg``
3251 :type arg: `escript.Symbol`
3252 :return: derivative with respect to ``arg``
3253 :rtype: typically `Symbol` but other types such as ``float``,
3254 `escript.Data`, ``numpy.ndarray`` are possible
3255 """
3256 if arg==self:
3257 return identity(self.getShape())
3258 else:
3259 myarg=self.getArgument()[0]
3260 val=matchShape(1./arg,self.getDifferentiatedArguments(arg)[0])
3261 return val[0]*val[1]
3262
3263 def sign(arg):
3264 """
3265 Returns the sign of argument ``arg``.
3266
3267 :param arg: argument
3268 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3269 :rtype: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray`` depending
3270 on the type of ``arg``
3271 :raise TypeError: if the type of the argument is not expected
3272 """
3273 if isinstance(arg,numpy.ndarray):
3274 return wherePositive(arg)-whereNegative(arg)
3275 elif isinstance(arg,escript.Data):
3276 return arg._sign()
3277 elif isinstance(arg,float):
3278 if arg>0:
3279 return 1.
3280 elif arg<0:
3281 return -1.
3282 else:
3283 return 0.
3284 elif isinstance(arg,int):
3285 if float(arg)>0:
3286 return 1.
3287 elif float(arg)<0:
3288 return -1.
3289 else:
3290 return 0.
3291 elif isinstance(arg,Symbol):
3292 return wherePositive(arg)-whereNegative(arg)
3293 else:
3294 raise TypeError("sign: Unknown argument type.")
3295
3296 class Abs_Symbol(DependendSymbol):
3297 """
3298 `Symbol` representing the result of the absolute value function.
3299 """
3300 def __init__(self,arg):
3301 """
3302 Initialization of abs `Symbol` with argument ``arg``.
3303
3304 :param arg: argument of function
3305 :type arg: typically `Symbol`
3306 """
3307 DependendSymbol.__init__(self,args=[arg],shape=arg.getShape(),dim=arg.getDim())
3308
3309 def getMyCode(self,argstrs,format="escript"):
3310 """
3311 Returns program code that can be used to evaluate the symbol.
3312
3313 :param argstrs: a string for each argument representing the argument
3314 for the evaluation
3315 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3316 :param format: specifies the format to be used. At the moment only
3317 "escript", "str" and "text" are supported.
3318 :type format: ``str``
3319 :return: a piece of program code which can be used to evaluate the
3320 expression assuming the values for the arguments are available
3321 :rtype: ``str``
3322 :raise NotImplementedError: if no implementation for the given format
3323 is available
3324 """
3325 if isinstance(argstrs,list):
3326 argstrs=argstrs[0]
3327 if format=="escript" or format=="str" or format=="text":
3328 return "abs(%s)"%argstrs
3329 else:
3330 raise NotImplementedError("Abs_Symbol does not provide program code for format %s."%format)
3331
3332 def substitute(self,argvals):
3333 """
3334 Assigns new values to symbols in the definition of the symbol.
3335 The method replaces the `Symbol` u by argvals[u] in the expression
3336 defining this object.
3337
3338 :param argvals: new values assigned to symbols
3339 :type argvals: ``dict`` with keywords of type `Symbol`
3340 :return: result of the substitution process. Operations are executed as
3341 much as possible.
3342 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3343 depending on the degree of substitution
3344 :raise TypeError: if a value for a `Symbol` cannot be substituted
3345 """
3346 if self in argvals:
3347 arg=argvals[self]
3348 if self.isAppropriateValue(arg):
3349 return arg
3350 else:
3351 raise TypeError("%s: new value is not appropriate."%str(self))
3352 else:
3353 arg=self.getSubstitutedArguments(argvals)[0]
3354 return abs(arg)
3355
3356 def diff(self,arg):
3357 """
3358 Differential of this object.
3359
3360 :param arg: the derivative is calculated with respect to ``arg``
3361 :type arg: `escript.Symbol`
3362 :return: derivative with respect to ``arg``
3363 :rtype: typically `Symbol` but other types such as ``float``,
3364 `escript.Data`, ``numpy.ndarray`` are possible
3365 """
3366 if arg==self:
3367 return identity(self.getShape())
3368 else:
3369 myarg=self.getArgument()[0]
3370 val=matchShape(sign(myarg),self.getDifferentiatedArguments(arg)[0])
3371 return val[0]*val[1]
3372
3373 def minval(arg):
3374 """
3375 Returns the minimum value over all components of ``arg`` at each data point.
3376
3377 :param arg: argument
3378 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3379 :rtype: ``float``, `escript.Data`, `Symbol` depending on the type of ``arg``
3380 :raise TypeError: if the type of the argument is not expected
3381 """
3382 if isinstance(arg,numpy.ndarray):
3383 if arg.ndim==0:
3384 return float(arg)
3385 else:
3386 return arg.min()
3387 elif isinstance(arg,escript.Data):
3388 return arg._minval()
3389 elif isinstance(arg,float):
3390 return arg
3391 elif isinstance(arg,int):
3392 return float(arg)
3393 elif isinstance(arg,Symbol):
3394 return Minval_Symbol(arg)
3395 else:
3396 raise TypeError("minval: Unknown argument type.")
3397
3398 class Minval_Symbol(DependendSymbol):
3399 """
3400 `Symbol` representing the result of the minimum value function.
3401 """
3402 def __init__(self,arg):
3403 """
3404 Initialization of minimum value `Symbol` with argument ``arg``.
3405
3406 :param arg: argument of function
3407 :type arg: typically `Symbol`
3408 """
3409 DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
3410
3411 def getMyCode(self,argstrs,format="escript"):
3412 """
3413 Returns program code that can be used to evaluate the symbol.
3414
3415 :param argstrs: a string for each argument representing the argument
3416 for the evaluation
3417 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3418 :param format: specifies the format to be used. At the moment only
3419 "escript", "str" and "text" are supported.
3420 :type format: ``str``
3421 :return: a piece of program code which can be used to evaluate the
3422 expression assuming the values for the arguments are available
3423 :rtype: ``str``
3424 :raise NotImplementedError: if no implementation for the given format
3425 is available
3426 """
3427 if isinstance(argstrs,list):
3428 argstrs=argstrs[0]
3429 if format=="escript" or format=="str" or format=="text":
3430 return "minval(%s)"%argstrs
3431 else:
3432 raise NotImplementedError("Minval_Symbol does not provide program code for format %s."%format)
3433
3434 def substitute(self,argvals):
3435 """
3436 Assigns new values to symbols in the definition of the symbol.
3437 The method replaces the `Symbol` u by argvals[u] in the expression
3438 defining this object.
3439
3440 :param argvals: new values assigned to symbols
3441 :type argvals: ``dict`` with keywords of type `Symbol`
3442 :return: result of the substitution process. Operations are executed as
3443 much as possible.
3444 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3445 depending on the degree of substitution
3446 :raise TypeError: if a value for a `Symbol` cannot be substituted
3447 """
3448 if self in argvals:
3449 arg=argvals[self]
3450 if self.isAppropriateValue(arg):
3451 return arg
3452 else:
3453 raise TypeError("%s: new value is not appropriate."%str(self))
3454 else:
3455 arg=self.getSubstitutedArguments(argvals)[0]
3456 return minval(arg)
3457
3458 def maxval(arg):
3459 """
3460 Returns the maximum value over all components of ``arg`` at each data point.
3461
3462 :param arg: argument
3463 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3464 :rtype: ``float``, `escript.Data`, `Symbol` depending on the type of ``arg``
3465 :raise TypeError: if the type of the argument is not expected
3466 """
3467 if isinstance(arg,numpy.ndarray):
3468 if arg.ndim==0:
3469 return float(arg)
3470 else:
3471 return arg.max()
3472 elif isinstance(arg,escript.Data):
3473 return arg._maxval()
3474 elif isinstance(arg,float):
3475 return arg
3476 elif isinstance(arg,int):
3477 return float(arg)
3478 elif isinstance(arg,Symbol):
3479 return Maxval_Symbol(arg)
3480 else:
3481 raise TypeError("maxval: Unknown argument type.")
3482
3483 class Maxval_Symbol(DependendSymbol):
3484 """
3485 `Symbol` representing the result of the maximum value function.
3486 """
3487 def __init__(self,arg):
3488 """
3489 Initialization of maximum value `Symbol` with argument ``arg``.
3490
3491 :param arg: argument of function
3492 :type arg: typically `Symbol`
3493 """
3494 DependendSymbol.__init__(self,args=[arg],shape=(),dim=arg.getDim())
3495
3496 def getMyCode(self,argstrs,format="escript"):
3497 """
3498 Returns program code that can be used to evaluate the symbol.
3499
3500 :param argstrs: a string for each argument representing the argument
3501 for the evaluation
3502 :type argstrs: ``str`` or a ``list`` of length 1 of ``str``
3503 :param format: specifies the format to be used. At the moment only
3504 "escript", "str" and "text" are supported.
3505 :type format: ``str``
3506 :return: a piece of program code which can be used to evaluate the
3507 expression assuming the values for the arguments are available
3508 :rtype: ``str``
3509 :raise NotImplementedError: if no implementation for the given format
3510 is available
3511 """
3512 if isinstance(argstrs,list):
3513 argstrs=argstrs[0]
3514 if format=="escript" or format=="str" or format=="text":
3515 return "maxval(%s)"%argstrs
3516 else:
3517 raise NotImplementedError("Maxval_Symbol does not provide program code for format %s."%format)
3518
3519 def substitute(self,argvals):
3520 """
3521 Assigns new values to symbols in the definition of the symbol.
3522 The method replaces the `Symbol` u by argvals[u] in the expression
3523 defining this object.
3524
3525 :param argvals: new values assigned to symbols
3526 :type argvals: ``dict`` with keywords of type `Symbol`
3527 :return: result of the substitution process. Operations are executed as
3528 much as possible.
3529 :rtype: `escript.Symbol`, ``float``, `escript.Data`, ``numpy.ndarray``
3530 depending on the degree of substitution
3531 :raise TypeError: if a value for a `Symbol` cannot be substituted
3532 """
3533 if self in argvals:
3534 arg=argvals[self]
3535 if self.isAppropriateValue(arg):
3536 return arg
3537 else:
3538 raise TypeError("%s: new value is not appropriate."%str(self))
3539 else:
3540 arg=self.getSubstitutedArguments(argvals)[0]
3541 return maxval(arg)
3542
3543 def length(arg):
3544 """
3545 Returns the length (Euclidean norm) of argument ``arg`` at each data point.
3546
3547 :param arg: argument
3548 :type arg: ``float``, `escript.Data`, `Symbol`, ``numpy.ndarray``
3549 :rtype: ``float``, `escript.Data`, `Symbol` depending on the type of ``arg``
3550 """
3551 return sqrt(inner(arg,arg))
3552
3553 def trace(arg,axis_offset=0):
3554 """
3555 Returns the trace of ``arg`` which is the sum of ``arg[k,k]`` over k.
3556
3557 :param arg: argument
3558 :type arg: `escript.Data`, `Symbol`, ``numpy.ndarray``
3559 :param axis_offset: ``axis_offset`` to components to sum over. ``axis_offset``
3560 must be non-negative and less than the rank of ``arg`` +1.
3561 The dimensions of component ``axis_offset`` and
3562 axis_offset+1 must be equal.
3563 :type axis_offset: ``int``
3564 :return: trace of arg. The rank of the returned object is rank of ``arg``
3565 minus 2.
3566 :rtype: `escript.Data`, `Symbol`, ``numpy.ndarray`` depending on the
3567 type of ``arg``
3568 """
3569 if isinstance(arg,numpy.ndarray):
3570 sh=arg.shape
3571 if len(sh)<2:
3572 raise ValueError("rank of argument must be greater than 1")
3573 if axis_offset<0 or axis_offset>len(sh)-2: