1 |
jgs |
82 |
// $Id$ |
2 |
|
|
/*============================================================================= |
3 |
|
|
|
4 |
|
|
****************************************************************************** |
5 |
|
|
* * |
6 |
|
|
* COPYRIGHT ACcESS 2004 - All Rights Reserved * |
7 |
|
|
* * |
8 |
|
|
* This software is the property of ACcESS. No part of this code * |
9 |
|
|
* may be copied in any form or by any means without the expressed written * |
10 |
|
|
* consent of ACcESS. Copying, use or modification of this software * |
11 |
|
|
* by any unauthorised person is illegal unless that * |
12 |
|
|
* person has a software license agreement with ACcESS. * |
13 |
|
|
* * |
14 |
|
|
****************************************************************************** |
15 |
|
|
|
16 |
|
|
******************************************************************************/ |
17 |
|
|
|
18 |
|
|
#ifndef DATA_H |
19 |
|
|
#define DATA_H |
20 |
|
|
|
21 |
|
|
#include "escript/Data/DataAbstract.h" |
22 |
|
|
#include "escript/Data/DataTagged.h" |
23 |
|
|
#include "escript/Data/FunctionSpace.h" |
24 |
|
|
#include "escript/Data/BinaryOp.h" |
25 |
|
|
#include "escript/Data/UnaryOp.h" |
26 |
|
|
|
27 |
|
|
extern "C" { |
28 |
|
|
#include "escript/Data/DataC.h" |
29 |
|
|
} |
30 |
|
|
|
31 |
|
|
#include <iostream> |
32 |
|
|
#include <string> |
33 |
|
|
#include <memory> |
34 |
|
|
#include <algorithm> |
35 |
|
|
|
36 |
|
|
#include <boost/shared_ptr.hpp> |
37 |
|
|
#include <boost/python/object.hpp> |
38 |
|
|
#include <boost/python/list.hpp> |
39 |
|
|
#include <boost/python/tuple.hpp> |
40 |
|
|
#include <boost/python/numeric.hpp> |
41 |
|
|
|
42 |
|
|
/** |
43 |
|
|
\brief |
44 |
|
|
Data is essentially a factory class which creates the appropriate Data |
45 |
|
|
object for the given construction arguments. It retains control over |
46 |
|
|
the object created for the lifetime of the object. |
47 |
|
|
The type of Data object referred to may change during the lifetime of |
48 |
|
|
the Data object. |
49 |
|
|
|
50 |
|
|
Description: |
51 |
|
|
Data is essentially a factory class which creates the appropriate Data |
52 |
|
|
object for the given construction arguments. It retains control over |
53 |
|
|
the object created for the lifetime of the object. |
54 |
|
|
The type of Data object referred to may change during the lifetime of |
55 |
|
|
the Data object. |
56 |
|
|
*/ |
57 |
|
|
|
58 |
|
|
namespace escript { |
59 |
|
|
|
60 |
|
|
// |
61 |
|
|
// Forward declaration for various implimentations of Data. |
62 |
|
|
class DataEmpty; |
63 |
|
|
class DataConstant; |
64 |
|
|
class DataTagged; |
65 |
|
|
class DataExpanded; |
66 |
|
|
|
67 |
|
|
class Data { |
68 |
|
|
|
69 |
|
|
public: |
70 |
|
|
|
71 |
|
|
typedef double (*UnaryDFunPtr)(double); |
72 |
|
|
typedef double (*BinaryDFunPtr)(double,double); |
73 |
|
|
|
74 |
|
|
/** |
75 |
|
|
\brief |
76 |
|
|
Default constructor. |
77 |
|
|
Creates a DataEmpty object. |
78 |
|
|
*/ |
79 |
|
|
Data(); |
80 |
|
|
|
81 |
|
|
/** |
82 |
|
|
\brief |
83 |
|
|
Copy constructor. |
84 |
|
|
WARNING: Only performs a shallow copy. |
85 |
|
|
*/ |
86 |
|
|
Data(const Data& inData); |
87 |
|
|
|
88 |
|
|
/** |
89 |
|
|
\brief |
90 |
|
|
Constructor from another Data object. If "what" is different from the |
91 |
|
|
function space of inData the inData are tried to be interpolated to what |
92 |
|
|
otherwise a shallow copy of inData is returned. |
93 |
|
|
*/ |
94 |
|
|
Data(const Data& inData, |
95 |
|
|
const FunctionSpace& what); |
96 |
|
|
|
97 |
|
|
/** |
98 |
|
|
\brief |
99 |
|
|
Constructor which copies data from a DataArrayView. |
100 |
|
|
|
101 |
|
|
\param value - Input - Data value for a single point. |
102 |
|
|
\param what - Input - A description of what this data represents. |
103 |
|
|
\param expanded - Input - Flag, if true fill the entire container with |
104 |
|
|
the value. Otherwise a more efficient storage |
105 |
|
|
mechanism will be used. |
106 |
|
|
*/ |
107 |
|
|
Data(const DataArrayView& value, |
108 |
|
|
const FunctionSpace& what=FunctionSpace(), |
109 |
|
|
bool expanded=false); |
110 |
|
|
|
111 |
|
|
/** |
112 |
|
|
\brief |
113 |
|
|
Constructor which creates a Data from a DataArrayView shape. |
114 |
|
|
|
115 |
|
|
\param value - Input - Single value applied to all Data. |
116 |
|
|
\param dataPointShape - Input - The shape of each data point. |
117 |
|
|
\param what - Input - A description of what this data represents. |
118 |
|
|
\param expanded - Input - Flag, if true fill the entire container with |
119 |
|
|
the given value. Otherwise a more efficient storage |
120 |
|
|
mechanism will be used. |
121 |
|
|
*/ |
122 |
|
|
Data(double value, |
123 |
|
|
const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(), |
124 |
|
|
const FunctionSpace& what=FunctionSpace(), |
125 |
|
|
bool expanded=false); |
126 |
|
|
|
127 |
|
|
/** |
128 |
|
|
\brief |
129 |
|
|
Constructor which performs a deep copy of a region from another Data object. |
130 |
|
|
|
131 |
|
|
\param inData - Input - Input Data object. |
132 |
|
|
\param region - Input - Region to copy. |
133 |
|
|
*/ |
134 |
|
|
Data(const Data& inData, |
135 |
|
|
const DataArrayView::RegionType& region); |
136 |
|
|
|
137 |
|
|
/** |
138 |
|
|
\brief |
139 |
|
|
Constructor which will create Tagged data if expanded is false. |
140 |
|
|
No attempt is made to ensure the tag keys match the tag keys |
141 |
|
|
within the function space. |
142 |
|
|
|
143 |
|
|
\param tagKeys - Input - List of tag values. |
144 |
|
|
\param values - Input - List of values, one for each tag. |
145 |
|
|
\param defaultValue - Input - A default value, used if tag doesn't exist. |
146 |
|
|
\param what - Input - A description of what this data represents. |
147 |
|
|
\param expanded - Input - Flag, if true fill the entire container with |
148 |
|
|
the appropriate values. |
149 |
|
|
*/ |
150 |
|
|
Data(const DataTagged::TagListType& tagKeys, |
151 |
|
|
const DataTagged::ValueListType& values, |
152 |
|
|
const DataArrayView& defaultValue, |
153 |
|
|
const FunctionSpace& what=FunctionSpace(), |
154 |
|
|
bool expanded=false); |
155 |
|
|
|
156 |
|
|
/** |
157 |
|
|
\brief |
158 |
|
|
Constructor which copies data from a python numarray. |
159 |
|
|
|
160 |
|
|
\param value - Input - Data value for a single point. |
161 |
|
|
\param what - Input - A description of what this data represents. |
162 |
|
|
\param expanded - Input - Flag, if true fill the entire container with |
163 |
|
|
the value. Otherwise a more efficient storage |
164 |
|
|
mechanism will be used. |
165 |
|
|
*/ |
166 |
|
|
Data(const boost::python::numeric::array& value, |
167 |
|
|
const FunctionSpace& what=FunctionSpace(), |
168 |
|
|
bool expanded=false); |
169 |
|
|
|
170 |
|
|
/** |
171 |
|
|
\brief |
172 |
|
|
Constructor which copies data from any object that can be converted into |
173 |
|
|
a python numarray. |
174 |
|
|
|
175 |
|
|
\param value - Input - Input data. |
176 |
|
|
\param what - Input - A description of what this data represents. |
177 |
|
|
\param expanded - Input - Flag, if true fill the entire container with |
178 |
|
|
the value. Otherwise a more efficient storage |
179 |
|
|
mechanism will be used. |
180 |
|
|
*/ |
181 |
|
|
Data(const boost::python::object& value, |
182 |
|
|
const FunctionSpace& what=FunctionSpace(), |
183 |
|
|
bool expanded=false); |
184 |
|
|
|
185 |
|
|
/** |
186 |
|
|
\brief |
187 |
|
|
Constructor which creates a DataConstant. |
188 |
|
|
Copies data from any object that can be converted |
189 |
|
|
into a numarray. All other parameters are copied from other. |
190 |
|
|
|
191 |
|
|
\param value - Input - Input data. |
192 |
|
|
\param other - Input - contains all other parameters. |
193 |
|
|
*/ |
194 |
|
|
Data(const boost::python::object& value, |
195 |
|
|
const Data& other); |
196 |
|
|
|
197 |
|
|
/** |
198 |
|
|
\brief |
199 |
|
|
Constructor which creates a DataConstant of "shape" with constant value. |
200 |
|
|
*/ |
201 |
|
|
Data(double value, |
202 |
|
|
const boost::python::tuple& shape=boost::python::make_tuple(), |
203 |
|
|
const FunctionSpace& what=FunctionSpace(), |
204 |
|
|
bool expanded=false); |
205 |
|
|
|
206 |
|
|
/** |
207 |
|
|
\brief |
208 |
|
|
Perform the specified algorithm on the Data and return result. |
209 |
|
|
*/ |
210 |
|
|
template <class UnaryFunction> |
211 |
|
|
inline double |
212 |
|
|
algorithm(UnaryFunction operation) const; |
213 |
|
|
|
214 |
|
|
/** |
215 |
|
|
\brief |
216 |
|
|
Perform the given unary operation on all of the data's elements. |
217 |
|
|
*/ |
218 |
|
|
template <class UnaryFunction> |
219 |
|
|
void |
220 |
|
|
unaryOp(UnaryFunction operation); |
221 |
|
|
|
222 |
|
|
/** |
223 |
|
|
\brief |
224 |
|
|
Perform the given binary operation on all of the data's elements. |
225 |
|
|
The underlying type of the right hand side (right) determines the final |
226 |
|
|
type of *this after the operation. For example if the right hand side |
227 |
|
|
is expanded *this will be expanded if necessary. |
228 |
|
|
*/ |
229 |
|
|
template <class BinaryFunction> |
230 |
|
|
void |
231 |
|
|
binaryOp(const Data& right, |
232 |
|
|
BinaryFunction operation); |
233 |
|
|
|
234 |
|
|
/** |
235 |
|
|
\brief |
236 |
|
|
Perform the given binary operation on all of the data's elements. |
237 |
|
|
*/ |
238 |
|
|
template <class BinaryFunction> |
239 |
|
|
void |
240 |
|
|
binaryOp(const boost::python::object& right, |
241 |
|
|
BinaryFunction operation); |
242 |
|
|
|
243 |
|
|
/** |
244 |
|
|
\brief |
245 |
|
|
Overloaded operator += |
246 |
|
|
\param right - Input - The right hand side. |
247 |
|
|
*/ |
248 |
|
|
Data& operator+=(const Data& right); |
249 |
|
|
Data& operator+=(const boost::python::object& right); |
250 |
|
|
|
251 |
|
|
/** |
252 |
|
|
\brief |
253 |
|
|
Overloaded operator -= |
254 |
|
|
\param right - Input - The right hand side. |
255 |
|
|
*/ |
256 |
|
|
Data& operator-=(const Data& right); |
257 |
|
|
Data& operator-=(const boost::python::object& right); |
258 |
|
|
|
259 |
|
|
/** |
260 |
|
|
\brief |
261 |
|
|
Overloaded operator *= |
262 |
|
|
\param right - Input - The right hand side. |
263 |
|
|
*/ |
264 |
|
|
Data& operator*=(const Data& right); |
265 |
|
|
Data& operator*=(const boost::python::object& right); |
266 |
|
|
|
267 |
|
|
/** |
268 |
|
|
\brief |
269 |
|
|
Overloaded operator /= |
270 |
|
|
\param right - Input - The right hand side. |
271 |
|
|
*/ |
272 |
|
|
Data& operator/=(const Data& right); |
273 |
|
|
Data& operator/=(const boost::python::object& right); |
274 |
|
|
|
275 |
|
|
/** |
276 |
|
|
\brief |
277 |
|
|
Return the power of Data. |
278 |
|
|
*/ |
279 |
|
|
Data powD(const Data& right) const; |
280 |
|
|
Data powO(const boost::python::object& right) const; |
281 |
|
|
|
282 |
|
|
/** |
283 |
|
|
\brief |
284 |
|
|
Return the C wrapper for the Data object. |
285 |
|
|
*/ |
286 |
|
|
escriptDataC getDataC(); |
287 |
|
|
|
288 |
|
|
/** |
289 |
|
|
\brief |
290 |
|
|
Return the C wrapper for the Data object - const version. |
291 |
|
|
*/ |
292 |
|
|
escriptDataC getDataC() const; |
293 |
|
|
|
294 |
|
|
/** |
295 |
|
|
\brief |
296 |
|
|
Write the data as a string. |
297 |
|
|
*/ |
298 |
|
|
std::string toString() const; |
299 |
|
|
|
300 |
|
|
/** |
301 |
|
|
\brief |
302 |
|
|
Return the DataArrayView of the point data. This essentially contains |
303 |
|
|
the shape information for each data point although it also may be used |
304 |
|
|
to manipulate the point data. |
305 |
|
|
*/ |
306 |
|
|
inline |
307 |
|
|
const DataArrayView& |
308 |
|
|
getPointDataView() const |
309 |
|
|
{ |
310 |
|
|
return m_data->getPointDataView(); |
311 |
|
|
} |
312 |
|
|
|
313 |
|
|
/** |
314 |
|
|
\brief |
315 |
|
|
Perform a deep copy. |
316 |
|
|
*/ |
317 |
|
|
void |
318 |
|
|
copy(const Data& other); |
319 |
|
|
|
320 |
|
|
/** |
321 |
|
|
\brief |
322 |
|
|
Copy other Data object into this Data object where mask is positive. |
323 |
|
|
*/ |
324 |
|
|
void |
325 |
|
|
copyWithMask(const Data& other, |
326 |
|
|
const Data& mask); |
327 |
|
|
|
328 |
|
|
/** |
329 |
|
|
\brief |
330 |
|
|
Whatever the current Data type make it expanded. |
331 |
|
|
*/ |
332 |
|
|
void |
333 |
|
|
expand(); |
334 |
|
|
|
335 |
|
|
/** |
336 |
|
|
\brief |
337 |
|
|
If possible convert the Data type to tagged. This will only allow |
338 |
|
|
Constant data to be converted to tagged. An attempt to convert |
339 |
|
|
Expanded data to tagged will throw an exception. |
340 |
|
|
*/ |
341 |
|
|
void |
342 |
|
|
tag(); |
343 |
|
|
|
344 |
|
|
/** |
345 |
|
|
\brief |
346 |
|
|
Return true if this Data is expanded. |
347 |
|
|
*/ |
348 |
|
|
bool |
349 |
|
|
isExpanded() const; |
350 |
|
|
|
351 |
|
|
/** |
352 |
|
|
\brief |
353 |
|
|
Return true if this Data is tagged. |
354 |
|
|
*/ |
355 |
|
|
bool |
356 |
|
|
isTagged() const; |
357 |
|
|
|
358 |
|
|
/** |
359 |
|
|
\brief |
360 |
|
|
Return true if this Data is empty. |
361 |
|
|
*/ |
362 |
|
|
bool |
363 |
|
|
isEmpty() const; |
364 |
|
|
|
365 |
|
|
/** |
366 |
|
|
\brief |
367 |
|
|
Return true if this Data is constant. |
368 |
|
|
*/ |
369 |
|
|
bool |
370 |
|
|
isConstant() const; |
371 |
|
|
|
372 |
|
|
/** |
373 |
|
|
\brief |
374 |
|
|
Return the function space. |
375 |
|
|
*/ |
376 |
|
|
inline |
377 |
|
|
const FunctionSpace& |
378 |
|
|
getFunctionSpace() const |
379 |
|
|
{ |
380 |
|
|
return m_data->getFunctionSpace(); |
381 |
|
|
} |
382 |
|
|
|
383 |
|
|
/** |
384 |
|
|
\brief |
385 |
|
|
Return a copy of the function space. |
386 |
|
|
*/ |
387 |
|
|
const FunctionSpace |
388 |
|
|
getCopyOfFunctionSpace() const; |
389 |
|
|
|
390 |
|
|
/** |
391 |
|
|
\brief |
392 |
|
|
Return the domain. |
393 |
|
|
*/ |
394 |
|
|
inline |
395 |
|
|
const AbstractDomain& |
396 |
|
|
getDomain() const |
397 |
|
|
{ |
398 |
|
|
return getFunctionSpace().getDomain(); |
399 |
|
|
} |
400 |
|
|
|
401 |
|
|
/** |
402 |
|
|
\brief |
403 |
|
|
Return a copy of the domain. |
404 |
|
|
*/ |
405 |
|
|
const AbstractDomain |
406 |
|
|
getCopyOfDomain() const; |
407 |
|
|
|
408 |
|
|
/** |
409 |
|
|
\brief |
410 |
|
|
Return the rank of the point data. |
411 |
|
|
*/ |
412 |
|
|
inline |
413 |
|
|
int |
414 |
|
|
getDataPointRank() const |
415 |
|
|
{ |
416 |
|
|
return m_data->getPointDataView().getRank(); |
417 |
|
|
} |
418 |
|
|
|
419 |
|
|
/** |
420 |
|
|
\brief |
421 |
|
|
Return the number of data points per sample. |
422 |
|
|
*/ |
423 |
|
|
inline |
424 |
|
|
int |
425 |
|
|
getNumDataPointsPerSample() const |
426 |
|
|
{ |
427 |
|
|
return m_data->getNumDPPSample(); |
428 |
|
|
} |
429 |
|
|
|
430 |
|
|
/** |
431 |
|
|
\brief |
432 |
|
|
Return the number of samples. |
433 |
|
|
*/ |
434 |
|
|
int |
435 |
|
|
getNumSamples() const; |
436 |
|
|
|
437 |
|
|
/** |
438 |
|
|
\brief |
439 |
|
|
Check *this and the right operand are compatible. Throws |
440 |
|
|
an exception if they aren't. |
441 |
|
|
\param right - Input - The right hand side. |
442 |
|
|
*/ |
443 |
|
|
void |
444 |
|
|
operandCheck(const Data& right) const; |
445 |
|
|
|
446 |
|
|
/** |
447 |
|
|
\brief |
448 |
|
|
Return the sample data for the given sample no. This is not the |
449 |
|
|
preferred interface but is provided for use by C code. |
450 |
|
|
\param sampleNo - Input - the given sample no. |
451 |
|
|
*/ |
452 |
|
|
DataAbstract::ValueType::value_type* |
453 |
|
|
getSampleData(DataAbstract::ShapeType::size_type sampleNo); |
454 |
|
|
|
455 |
|
|
/** |
456 |
|
|
\brief |
457 |
|
|
Return the sample data for the given tag. If an attempt is made to |
458 |
|
|
access data that isn't tagged an exception will be thrown. |
459 |
|
|
\param tag - Input - the tag key. |
460 |
|
|
*/ |
461 |
|
|
DataAbstract::ValueType::value_type* |
462 |
|
|
getSampleDataByTag(int tag); |
463 |
|
|
|
464 |
|
|
/** |
465 |
|
|
\brief |
466 |
|
|
Return a view into the data for the data point specified. |
467 |
|
|
NOTE: Construction of the DataArrayView is a relatively expensive |
468 |
|
|
operation. |
469 |
|
|
\param sampleNo - Input - |
470 |
|
|
\param dataPointNo - Input - |
471 |
|
|
*/ |
472 |
|
|
inline |
473 |
|
|
DataArrayView |
474 |
|
|
getDataPoint(int sampleNo, |
475 |
|
|
int dataPointNo) |
476 |
|
|
{ |
477 |
|
|
return m_data->getDataPoint(sampleNo,dataPointNo); |
478 |
|
|
} |
479 |
|
|
|
480 |
|
|
/** |
481 |
|
|
\brief |
482 |
|
|
Return a reference to the data point shape. |
483 |
|
|
*/ |
484 |
|
|
const DataArrayView::ShapeType& |
485 |
|
|
getDataPointShape() const; |
486 |
|
|
|
487 |
|
|
/** |
488 |
|
|
\brief |
489 |
|
|
Return data point shape as a tuple of integers: |
490 |
|
|
*/ |
491 |
|
|
boost::python::tuple |
492 |
|
|
getShapeTuple() const; |
493 |
|
|
|
494 |
|
|
/** |
495 |
|
|
\brief |
496 |
|
|
Return the size of the data point. It is the product of the |
497 |
|
|
data point shape dimensions. |
498 |
|
|
*/ |
499 |
|
|
int |
500 |
|
|
getDataPointSize() const; |
501 |
|
|
|
502 |
|
|
/** |
503 |
|
|
\brief |
504 |
|
|
Return the number of doubles stored for Data. |
505 |
|
|
*/ |
506 |
|
|
DataArrayView::ValueType::size_type |
507 |
|
|
getLength() const; |
508 |
|
|
|
509 |
|
|
/** |
510 |
|
|
\brief |
511 |
|
|
Interpolates this onto the given functionspace and returns the result as a Data object. |
512 |
|
|
*/ |
513 |
|
|
Data |
514 |
|
|
interpolate(const FunctionSpace& functionspace) const; |
515 |
|
|
|
516 |
|
|
/** |
517 |
|
|
\brief |
518 |
|
|
Calculates the gradient of the data at the data points of functionspace. |
519 |
|
|
If functionspace is not present the function space of Function(getDomain()) is used. |
520 |
|
|
*/ |
521 |
|
|
Data |
522 |
|
|
gradOn(const FunctionSpace& functionspace) const; |
523 |
|
|
|
524 |
|
|
Data |
525 |
|
|
grad() const; |
526 |
|
|
|
527 |
|
|
/** |
528 |
|
|
\brief |
529 |
|
|
Calculate the integral over the function space domain. |
530 |
|
|
*/ |
531 |
|
|
boost::python::numeric::array |
532 |
|
|
integrate() const; |
533 |
|
|
|
534 |
|
|
/** |
535 |
|
|
\brief |
536 |
|
|
Return a Data with a 1 for +ive values and a 0 for 0 or -ive values. |
537 |
|
|
*/ |
538 |
|
|
Data |
539 |
|
|
wherePositive() const; |
540 |
|
|
|
541 |
|
|
/** |
542 |
|
|
\brief |
543 |
|
|
Return a Data with a 1 for +ive values and a 0 for -ive values. |
544 |
|
|
*/ |
545 |
|
|
Data |
546 |
|
|
whereNonNegative() const; |
547 |
|
|
|
548 |
|
|
/** |
549 |
|
|
\brief |
550 |
|
|
Return a Data with a 1 for -ive values and a 0 for +ive or 0 values. |
551 |
|
|
*/ |
552 |
|
|
Data |
553 |
|
|
whereNegative() const; |
554 |
|
|
|
555 |
|
|
/** |
556 |
|
|
\brief |
557 |
|
|
Return a Data with a 1 for 0 values a 0 for +ive or -ive. |
558 |
|
|
*/ |
559 |
|
|
Data |
560 |
|
|
whereZero() const; |
561 |
|
|
|
562 |
|
|
/** |
563 |
|
|
\brief |
564 |
|
|
Return the sin of Data. |
565 |
|
|
*/ |
566 |
|
|
Data |
567 |
|
|
sin() const; |
568 |
|
|
|
569 |
|
|
/** |
570 |
|
|
\brief |
571 |
|
|
Return the cos of Data. |
572 |
|
|
*/ |
573 |
|
|
Data |
574 |
|
|
cos() const; |
575 |
|
|
|
576 |
|
|
/** |
577 |
|
|
\brief |
578 |
|
|
Return the tan of Data. |
579 |
|
|
*/ |
580 |
|
|
Data |
581 |
|
|
tan() const; |
582 |
|
|
|
583 |
|
|
/** |
584 |
|
|
\brief |
585 |
|
|
Return the log to base 10 of Data. |
586 |
|
|
*/ |
587 |
|
|
Data |
588 |
|
|
log() const; |
589 |
|
|
|
590 |
|
|
/** |
591 |
|
|
\brief |
592 |
|
|
Return the natural log of Data. |
593 |
|
|
*/ |
594 |
|
|
Data |
595 |
|
|
ln() const; |
596 |
|
|
|
597 |
|
|
/** |
598 |
|
|
\brief |
599 |
|
|
Return a Data containing a slice of this Data. |
600 |
|
|
*/ |
601 |
|
|
Data |
602 |
|
|
getSlice(const DataArrayView::RegionType& region) const; |
603 |
|
|
|
604 |
|
|
/** |
605 |
|
|
\brief |
606 |
|
|
Copy the specified region from the given value. |
607 |
|
|
\param value - Input - Data to copy from. |
608 |
|
|
\param region - Input - Region to copy. |
609 |
|
|
*/ |
610 |
|
|
void |
611 |
|
|
setSlice(const Data& value, |
612 |
|
|
const DataArrayView::RegionType& region); |
613 |
|
|
|
614 |
|
|
/** |
615 |
|
|
\brief |
616 |
|
|
Return the maximum absolute value. |
617 |
|
|
*/ |
618 |
|
|
double |
619 |
|
|
Lsup() const; |
620 |
|
|
|
621 |
|
|
/** |
622 |
|
|
\brief |
623 |
|
|
Return the maximum value. |
624 |
|
|
*/ |
625 |
|
|
double |
626 |
|
|
sup() const; |
627 |
|
|
|
628 |
|
|
/** |
629 |
|
|
\brief |
630 |
|
|
Return the minimum value. |
631 |
|
|
*/ |
632 |
|
|
double |
633 |
|
|
inf() const; |
634 |
|
|
|
635 |
|
|
/** |
636 |
|
|
\brief |
637 |
|
|
Returns a slice from this. |
638 |
|
|
*/ |
639 |
|
|
Data |
640 |
|
|
getItem(const boost::python::object& key) const; |
641 |
|
|
|
642 |
|
|
/** |
643 |
|
|
\brief |
644 |
|
|
Copies slice from value into this. |
645 |
|
|
*/ |
646 |
|
|
void |
647 |
|
|
setItem(const boost::python::object& key, |
648 |
|
|
const Data& value); |
649 |
|
|
|
650 |
|
|
/** |
651 |
|
|
\brief |
652 |
|
|
Convert the underlying data type to match the RHS. |
653 |
|
|
\param right - Input - data type to match. |
654 |
|
|
*/ |
655 |
|
|
void |
656 |
|
|
typeMatch(const Data& right); |
657 |
|
|
|
658 |
|
|
/** |
659 |
|
|
\brief |
660 |
|
|
Returns true if this can be interpolated to functionspace. |
661 |
|
|
*/ |
662 |
|
|
bool |
663 |
|
|
probeInterpolation(const FunctionSpace& functionspace) const; |
664 |
|
|
|
665 |
|
|
/** |
666 |
|
|
\brief |
667 |
|
|
Assign the given value to the tag. Implicitly converts this |
668 |
|
|
object to type DataTagged. Throws an exception if this object |
669 |
|
|
cannot be converted to a DataTagged object. |
670 |
|
|
\param tagKey - Input - Integer key. |
671 |
|
|
\param value - Input - Value to associate with given key. |
672 |
|
|
*/ |
673 |
|
|
void |
674 |
|
|
setTaggedValue(int tagKey, |
675 |
|
|
const boost::python::object& value); |
676 |
|
|
|
677 |
|
|
/** |
678 |
|
|
\brief |
679 |
|
|
Assign the given value to the tag. Implicitly converts this |
680 |
|
|
object to type DataTagged. Throws an exception if this object |
681 |
|
|
cannot be converted to a DataTagged object. |
682 |
|
|
\param tagKey - Input - Integer key. |
683 |
|
|
\param value - Input - Value to associate with given key. |
684 |
|
|
*/ |
685 |
|
|
void |
686 |
|
|
setTaggedValue(int tagKey, |
687 |
|
|
const DataArrayView& value); |
688 |
|
|
|
689 |
|
|
private: |
690 |
|
|
|
691 |
|
|
/** |
692 |
|
|
\brief |
693 |
|
|
Construct a Data object of the appropriate type. |
694 |
|
|
*/ |
695 |
|
|
template <class IValueType> |
696 |
|
|
void |
697 |
|
|
initialise(const IValueType& value, |
698 |
|
|
const FunctionSpace& what, |
699 |
|
|
bool expanded); |
700 |
|
|
|
701 |
|
|
/** |
702 |
|
|
\brief |
703 |
|
|
Reshape the data point if the data point is currently rank 0. |
704 |
|
|
Will throw an exception if the data points are not rank 0. |
705 |
|
|
The original data point value is used for all values of the new |
706 |
|
|
data point. |
707 |
|
|
*/ |
708 |
|
|
void |
709 |
|
|
reshapeDataPoint(const DataArrayView::ShapeType& shape); |
710 |
|
|
|
711 |
|
|
// |
712 |
|
|
// pointer to the actual data |
713 |
|
|
boost::shared_ptr<DataAbstract> m_data; |
714 |
|
|
|
715 |
|
|
}; |
716 |
|
|
|
717 |
|
|
template <class IValueType> |
718 |
|
|
void |
719 |
|
|
Data::initialise(const IValueType& value, |
720 |
|
|
const FunctionSpace& what, |
721 |
|
|
bool expanded) |
722 |
|
|
{ |
723 |
|
|
// |
724 |
|
|
// Construct a Data object of the appropriate type. |
725 |
|
|
// Construct the object first as there seems to be a bug which causes |
726 |
|
|
// undefined behaviour if an exception is thrown during construction |
727 |
|
|
// within the shared_ptr constructor. |
728 |
|
|
if (expanded) { |
729 |
|
|
DataAbstract* temp=new DataExpanded(value,what); |
730 |
|
|
m_data=boost::shared_ptr<DataAbstract>(temp); |
731 |
|
|
} else { |
732 |
|
|
DataAbstract* temp=new DataConstant(value,what); |
733 |
|
|
m_data=boost::shared_ptr<DataAbstract>(temp); |
734 |
|
|
} |
735 |
|
|
} |
736 |
|
|
|
737 |
|
|
inline |
738 |
|
|
DataAbstract::ValueType::value_type* |
739 |
|
|
Data::getSampleData(DataAbstract::ValueType::size_type sampleNo) |
740 |
|
|
{ |
741 |
|
|
return m_data->getSampleData(sampleNo); |
742 |
|
|
} |
743 |
|
|
|
744 |
|
|
inline |
745 |
|
|
DataAbstract::ValueType::value_type* |
746 |
|
|
Data::getSampleDataByTag(int tag) |
747 |
|
|
{ |
748 |
|
|
return m_data->getSampleDataByTag(tag); |
749 |
|
|
} |
750 |
|
|
|
751 |
|
|
inline |
752 |
|
|
void |
753 |
|
|
Data::operandCheck(const Data& right) const |
754 |
|
|
{ |
755 |
|
|
return m_data->operandCheck(*(right.m_data.get())); |
756 |
|
|
} |
757 |
|
|
|
758 |
|
|
inline |
759 |
|
|
int |
760 |
|
|
Data::getNumSamples() const |
761 |
|
|
{ |
762 |
|
|
return m_data->getNumSamples(); |
763 |
|
|
} |
764 |
|
|
|
765 |
|
|
inline |
766 |
|
|
std::string |
767 |
|
|
Data::toString() const |
768 |
|
|
{ |
769 |
|
|
return m_data->toString(); |
770 |
|
|
} |
771 |
|
|
|
772 |
|
|
/** |
773 |
|
|
\brief |
774 |
|
|
Operator+ |
775 |
|
|
Takes two Data objects. |
776 |
|
|
*/ |
777 |
|
|
Data operator+(const Data& left, const Data& right); |
778 |
|
|
|
779 |
|
|
/** |
780 |
|
|
\brief |
781 |
|
|
Operator- |
782 |
|
|
Takes two Data objects. |
783 |
|
|
*/ |
784 |
|
|
Data operator-(const Data& left, const Data& right); |
785 |
|
|
|
786 |
|
|
/** |
787 |
|
|
\brief |
788 |
|
|
Operator* |
789 |
|
|
Takes two Data objects. |
790 |
|
|
*/ |
791 |
|
|
Data operator*(const Data& left, const Data& right); |
792 |
|
|
|
793 |
|
|
/** |
794 |
|
|
\brief |
795 |
|
|
Operator/ |
796 |
|
|
Takes two Data objects. |
797 |
|
|
*/ |
798 |
|
|
Data operator/(const Data& left, const Data& right); |
799 |
|
|
|
800 |
|
|
/** |
801 |
|
|
\brief |
802 |
|
|
Operator+ |
803 |
|
|
Takes LHS Data object and RHS python::object. |
804 |
|
|
python::object must be convertable to Data type. |
805 |
|
|
*/ |
806 |
|
|
Data operator+(const Data& left, const boost::python::object& right); |
807 |
|
|
|
808 |
|
|
/** |
809 |
|
|
\brief |
810 |
|
|
Operator- |
811 |
|
|
Takes LHS Data object and RHS python::object. |
812 |
|
|
python::object must be convertable to Data type. |
813 |
|
|
*/ |
814 |
|
|
Data operator-(const Data& left, const boost::python::object& right); |
815 |
|
|
|
816 |
|
|
/** |
817 |
|
|
\brief |
818 |
|
|
Operator* |
819 |
|
|
Takes LHS Data object and RHS python::object. |
820 |
|
|
python::object must be convertable to Data type. |
821 |
|
|
*/ |
822 |
|
|
Data operator*(const Data& left, const boost::python::object& right); |
823 |
|
|
|
824 |
|
|
/** |
825 |
|
|
\brief |
826 |
|
|
Operator/ |
827 |
|
|
Takes LHS Data object and RHS python::object. |
828 |
|
|
python::object must be convertable to Data type. |
829 |
|
|
*/ |
830 |
|
|
Data operator/(const Data& left, const boost::python::object& right); |
831 |
|
|
|
832 |
|
|
/** |
833 |
|
|
\brief |
834 |
|
|
Operator+ |
835 |
|
|
Takes LHS python::object and RHS Data object. |
836 |
|
|
python::object must be convertable to Data type. |
837 |
|
|
*/ |
838 |
|
|
Data operator+(const boost::python::object& left, const Data& right); |
839 |
|
|
|
840 |
|
|
/** |
841 |
|
|
\brief |
842 |
|
|
Operator- |
843 |
|
|
Takes LHS python::object and RHS Data object. |
844 |
|
|
python::object must be convertable to Data type. |
845 |
|
|
*/ |
846 |
|
|
Data operator-(const boost::python::object& left, const Data& right); |
847 |
|
|
|
848 |
|
|
/** |
849 |
|
|
\brief |
850 |
|
|
Operator* |
851 |
|
|
Takes LHS python::object and RHS Data object. |
852 |
|
|
python::object must be convertable to Data type. |
853 |
|
|
*/ |
854 |
|
|
Data operator*(const boost::python::object& left, const Data& right); |
855 |
|
|
|
856 |
|
|
/** |
857 |
|
|
\brief |
858 |
|
|
Operator/ |
859 |
|
|
Takes LHS python::object and RHS Data object. |
860 |
|
|
python::object must be convertable to Data type. |
861 |
|
|
*/ |
862 |
|
|
Data operator/(const boost::python::object& left, const Data& right); |
863 |
|
|
|
864 |
|
|
/** |
865 |
|
|
\brief |
866 |
|
|
Output operator |
867 |
|
|
*/ |
868 |
|
|
std::ostream& operator<<(std::ostream& o, const Data& data); |
869 |
|
|
|
870 |
|
|
/** |
871 |
|
|
\brief |
872 |
|
|
Return true if operands are equivalent, else return false. |
873 |
|
|
NB: this operator does very little at this point, and isn't to |
874 |
|
|
be relied on. Requires further implementation. |
875 |
|
|
*/ |
876 |
|
|
bool operator==(const Data& left, const Data& right); |
877 |
|
|
|
878 |
|
|
template <class BinaryFunction> |
879 |
|
|
inline |
880 |
|
|
void |
881 |
|
|
Data::binaryOp(const Data& right, |
882 |
|
|
BinaryFunction operation) |
883 |
|
|
{ |
884 |
|
|
// |
885 |
|
|
// if this has a rank of zero promote it to the rank of the RHS |
886 |
|
|
if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) { |
887 |
|
|
reshapeDataPoint(right.getPointDataView().getShape()); |
888 |
|
|
} |
889 |
|
|
// |
890 |
|
|
// initially make the temporary a shallow copy |
891 |
|
|
Data tempRight(right); |
892 |
|
|
if (getFunctionSpace()!=right.getFunctionSpace()) { |
893 |
|
|
if (right.probeInterpolation(getFunctionSpace())) { |
894 |
|
|
// |
895 |
|
|
// an interpolation is required so create a new Data |
896 |
|
|
tempRight=Data(right,this->getFunctionSpace()); |
897 |
|
|
} else if (probeInterpolation(right.getFunctionSpace())) { |
898 |
|
|
// |
899 |
|
|
// interpolate onto the RHS function space |
900 |
|
|
Data tempLeft(*this,right.getFunctionSpace()); |
901 |
|
|
m_data=tempLeft.m_data; |
902 |
|
|
} |
903 |
|
|
} |
904 |
|
|
operandCheck(tempRight); |
905 |
|
|
// |
906 |
|
|
// ensure this has the right type for the RHS |
907 |
|
|
typeMatch(tempRight); |
908 |
|
|
// |
909 |
|
|
// Need to cast to the concrete types so that the correct binaryOp |
910 |
|
|
// is called. |
911 |
|
|
if (isExpanded()) { |
912 |
|
|
// |
913 |
|
|
// Expanded data will be done in parallel, the right hand side can be |
914 |
|
|
// of any data type |
915 |
|
|
DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get()); |
916 |
|
|
EsysAssert((leftC!=0), "Programming error - casting to DataExpanded."); |
917 |
|
|
escript::binaryOp(*leftC,*(tempRight.m_data.get()),operation); |
918 |
|
|
} else if (isTagged()) { |
919 |
|
|
// |
920 |
|
|
// Tagged data is operated on serially, the right hand side can be |
921 |
|
|
// either DataConstant or DataTagged |
922 |
|
|
DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get()); |
923 |
|
|
EsysAssert((leftC!=0), "Programming error - casting to DataTagged."); |
924 |
|
|
if (right.isTagged()) { |
925 |
|
|
DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get()); |
926 |
|
|
EsysAssert((rightC!=0), "Programming error - casting to DataTagged."); |
927 |
|
|
escript::binaryOp(*leftC,*rightC,operation); |
928 |
|
|
} else { |
929 |
|
|
DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get()); |
930 |
|
|
EsysAssert((rightC!=0), "Programming error - casting to DataConstant."); |
931 |
|
|
escript::binaryOp(*leftC,*rightC,operation); |
932 |
|
|
} |
933 |
|
|
} else { |
934 |
|
|
// |
935 |
|
|
// can only be DataConstant |
936 |
|
|
DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get()); |
937 |
|
|
DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get()); |
938 |
|
|
EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant."); |
939 |
|
|
escript::binaryOp(*leftC,*rightC,operation); |
940 |
|
|
} |
941 |
|
|
} |
942 |
|
|
|
943 |
|
|
template <class BinaryFunction> |
944 |
|
|
inline |
945 |
|
|
void |
946 |
|
|
Data::binaryOp(const boost::python::object& right, |
947 |
|
|
BinaryFunction operation) |
948 |
|
|
{ |
949 |
|
|
DataArray temp(right); |
950 |
|
|
// |
951 |
|
|
// if this has a rank of zero promote it to the rank of the RHS. |
952 |
|
|
if (getPointDataView().getRank()==0 && temp.getView().getRank()!=0) { |
953 |
|
|
reshapeDataPoint(temp.getView().getShape()); |
954 |
|
|
} |
955 |
|
|
// |
956 |
|
|
// Always allow scalar values for the RHS but check other shapes |
957 |
|
|
if (temp.getView().getRank()!=0) { |
958 |
|
|
if (!getPointDataView().checkShape(temp.getView().getShape())) { |
959 |
|
|
throw DataException(getPointDataView().createShapeErrorMessage( |
960 |
|
|
"Error - RHS shape doesn't match LHS shape.",temp.getView().getShape())); |
961 |
|
|
} |
962 |
|
|
} |
963 |
|
|
|
964 |
|
|
if (isExpanded()) { |
965 |
|
|
// |
966 |
|
|
// Expanded data will be done in parallel |
967 |
|
|
DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get()); |
968 |
|
|
EsysAssert((leftC!=0),"Programming error - casting to DataExpanded."); |
969 |
|
|
escript::binaryOp(*leftC,temp.getView(),operation); |
970 |
|
|
} else if (isTagged()) { |
971 |
|
|
DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get()); |
972 |
|
|
EsysAssert((leftC!=0), "Programming error - casting to DataTagged."); |
973 |
|
|
escript::binaryOp(*leftC,temp.getView(),operation); |
974 |
|
|
} else { |
975 |
|
|
// |
976 |
|
|
// can only be DataConstant |
977 |
|
|
DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get()); |
978 |
|
|
EsysAssert((leftC!=0),"Programming error - casting to DataConstant."); |
979 |
|
|
escript::binaryOp(*leftC,temp.getView(),operation); |
980 |
|
|
} |
981 |
|
|
} |
982 |
|
|
|
983 |
|
|
template <class UnaryFunction> |
984 |
|
|
inline |
985 |
|
|
void |
986 |
|
|
Data::unaryOp(UnaryFunction operation) |
987 |
|
|
{ |
988 |
|
|
if (isExpanded()) { |
989 |
|
|
// |
990 |
|
|
// Expanded data will be done in parallel |
991 |
|
|
DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get()); |
992 |
|
|
EsysAssert((leftC!=0), "Programming error - casting to DataExpanded."); |
993 |
|
|
escript::unaryOp(*leftC,operation); |
994 |
|
|
} else if (isTagged()) { |
995 |
|
|
DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get()); |
996 |
|
|
EsysAssert((leftC!=0), "Programming error - casting to DataTagged."); |
997 |
|
|
escript::unaryOp(*leftC,operation); |
998 |
|
|
} else { |
999 |
|
|
DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get()); |
1000 |
|
|
EsysAssert((leftC!=0), "Programming error - casting to DataConstant."); |
1001 |
|
|
escript::unaryOp(*leftC,operation); |
1002 |
|
|
} |
1003 |
|
|
} |
1004 |
|
|
|
1005 |
|
|
template <class UnaryFunction> |
1006 |
|
|
inline |
1007 |
|
|
double |
1008 |
|
|
Data::algorithm(UnaryFunction operation) const |
1009 |
|
|
{ |
1010 |
|
|
if (isExpanded()) { |
1011 |
|
|
// |
1012 |
|
|
// Expanded data will be done in parallel |
1013 |
|
|
DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get()); |
1014 |
|
|
EsysAssert((leftC!=0), "Programming error - casting to DataExpanded."); |
1015 |
|
|
return escript::algorithm(*leftC,operation); |
1016 |
|
|
} |
1017 |
|
|
else if (isTagged()) { |
1018 |
|
|
DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get()); |
1019 |
|
|
EsysAssert((leftC!=0), "Programming error - casting to DataTagged."); |
1020 |
|
|
return escript::algorithm(*leftC,operation); |
1021 |
|
|
} else { |
1022 |
|
|
DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get()); |
1023 |
|
|
EsysAssert((leftC!=0), "Programming error - casting to DataConstant."); |
1024 |
|
|
return escript::algorithm(*leftC,operation); |
1025 |
|
|
} |
1026 |
|
|
} |
1027 |
|
|
|
1028 |
|
|
template <class UnaryFunction> |
1029 |
|
|
inline |
1030 |
|
|
Data |
1031 |
|
|
unaryOp(const Data& other, |
1032 |
|
|
UnaryFunction operation) |
1033 |
|
|
{ |
1034 |
|
|
// |
1035 |
|
|
// Perform the given operation on a copy of the input data and return the result |
1036 |
|
|
Data result; |
1037 |
|
|
// |
1038 |
|
|
// perform a deep copy |
1039 |
|
|
result.copy(other); |
1040 |
|
|
result.unaryOp(operation); |
1041 |
|
|
return result; |
1042 |
|
|
} |
1043 |
|
|
|
1044 |
|
|
} |
1045 |
|
|
|
1046 |
|
|
#endif |