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