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