/[escript]/branches/more_shared_ptrs_from_1812/escript/src/Data.h
ViewVC logotype

Contents of /branches/more_shared_ptrs_from_1812/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 147 - (show annotations)
Fri Aug 12 01:45:47 2005 UTC (14 years, 3 months ago) by jgs
Original Path: trunk/esys2/escript/src/Data/Data.h
File MIME type: text/plain
File size: 36537 byte(s)
erge of development branch dev-02 back to main trunk on 2005-08-12

1 // $Id$
2 /*
3 ******************************************************************************
4 * *
5 * COPYRIGHT ACcESS 2004 - All Rights Reserved *
6 * *
7 * This software is the property of ACcESS. No part of this code *
8 * may be copied in any form or by any means without the expressed written *
9 * consent of ACcESS. Copying, use or modification of this software *
10 * by any unauthorised person is illegal unless that *
11 * person has a software license agreement with ACcESS. *
12 * *
13 ******************************************************************************
14 */
15
16 /** \file Data.h */
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/DataAlgorithm.h"
24 #include "escript/Data/FunctionSpace.h"
25 #include "escript/Data/BinaryOp.h"
26 #include "escript/Data/UnaryOp.h"
27 #include "escript/Data/DataException.h"
28
29 extern "C" {
30 #include "escript/Data/DataC.h"
31 }
32
33 #include <iostream>
34 #include <string>
35 #include <memory>
36 #include <algorithm>
37
38 #include <boost/shared_ptr.hpp>
39 #include <boost/python/object.hpp>
40 #include <boost/python/list.hpp>
41 #include <boost/python/tuple.hpp>
42 #include <boost/python/numeric.hpp>
43
44 namespace escript {
45
46 //
47 // Forward declaration for various implimentations of Data.
48 class DataEmpty;
49 class DataConstant;
50 class DataTagged;
51 class DataExpanded;
52
53 /**
54 \brief
55 Data creates the appropriate Data object for the given construction
56 arguments.
57
58 Description:
59 Data is essentially a factory class which creates the appropriate Data
60 object for the given construction arguments. It retains control over
61 the object created for the lifetime of the object.
62 The type of Data object referred to may change during the lifetime of
63 the Data object.
64 */
65 class Data {
66
67 public:
68
69 // These typedefs allow function names to be cast to pointers
70 // to functions of the appropriate type when calling unaryOp etc.
71 typedef double (*UnaryDFunPtr)(double);
72 typedef double (*BinaryDFunPtr)(double,double);
73
74 /**
75 Constructors.
76 */
77
78 /**
79 \brief
80 Default constructor.
81 Creates a DataEmpty object.
82 */
83 Data();
84
85 /**
86 \brief
87 Copy constructor.
88 WARNING: Only performs a shallow copy.
89 */
90 Data(const Data& inData);
91
92 /**
93 \brief
94 Constructor from another Data object. If "what" is different from the
95 function space of inData the inData are tried to be interpolated to what,
96 otherwise a shallow copy of inData is returned.
97 */
98 Data(const Data& inData,
99 const FunctionSpace& what);
100
101 /**
102 \brief
103 Constructor which copies data from a DataArrayView.
104
105 \param value - Input - Data value for a single point.
106 \param what - Input - A description of what this data represents.
107 \param expanded - Input - Flag, if true fill the entire container with
108 the value. Otherwise a more efficient storage
109 mechanism will be used.
110 */
111 Data(const DataArrayView& value,
112 const FunctionSpace& what=FunctionSpace(),
113 bool expanded=false);
114
115 /**
116 \brief
117 Constructor which creates a Data from a DataArrayView shape.
118
119 \param value - Input - Single value applied to all Data.
120 \param dataPointShape - Input - The shape of each data point.
121 \param what - Input - A description of what this data represents.
122 \param expanded - Input - Flag, if true fill the entire container with
123 the given value. Otherwise a more efficient storage
124 mechanism will be used.
125 */
126 Data(double value,
127 const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(),
128 const FunctionSpace& what=FunctionSpace(),
129 bool expanded=false);
130
131 /**
132 \brief
133 Constructor which performs a deep copy of a region from another Data object.
134
135 \param inData - Input - Input Data object.
136 \param region - Input - Region to copy.
137 */
138 Data(const Data& inData,
139 const DataArrayView::RegionType& region);
140
141 /**
142 \brief
143 Constructor which will create Tagged data if expanded is false.
144 No attempt is made to ensure the tag keys match the tag keys
145 within the function space.
146
147 \param tagKeys - Input - List of tag values.
148 \param values - Input - List of values, one for each tag.
149 \param defaultValue - Input - A default value, used if tag doesn't exist.
150 \param what - Input - A description of what this data represents.
151 \param expanded - Input - Flag, if true fill the entire container with
152 the appropriate values.
153 */
154 Data(const DataTagged::TagListType& tagKeys,
155 const DataTagged::ValueListType& values,
156 const DataArrayView& defaultValue,
157 const FunctionSpace& what=FunctionSpace(),
158 bool expanded=false);
159
160 /**
161 \brief
162 Constructor which copies data from a python numarray.
163
164 \param value - Input - Data value for a single point.
165 \param what - Input - A description of what this data represents.
166 \param expanded - Input - Flag, if true fill the entire container with
167 the value. Otherwise a more efficient storage
168 mechanism will be used.
169 */
170 Data(const boost::python::numeric::array& value,
171 const FunctionSpace& what=FunctionSpace(),
172 bool expanded=false);
173
174 /**
175 \brief
176 Constructor which copies data from any object that can be converted into
177 a python numarray.
178
179 \param value - Input - Input data.
180 \param what - Input - A description of what this data represents.
181 \param expanded - Input - Flag, if true fill the entire container with
182 the value. Otherwise a more efficient storage
183 mechanism will be used.
184 */
185 Data(const boost::python::object& value,
186 const FunctionSpace& what=FunctionSpace(),
187 bool expanded=false);
188
189 /**
190 \brief
191 Constructor which creates a DataConstant.
192 Copies data from any object that can be converted
193 into a numarray. All other parameters are copied from other.
194
195 \param value - Input - Input data.
196 \param other - Input - contains all other parameters.
197 */
198 Data(const boost::python::object& value,
199 const Data& other);
200
201 /**
202 \brief
203 Constructor which creates a DataConstant of "shape" with constant value.
204 */
205 Data(double value,
206 const boost::python::tuple& shape=boost::python::make_tuple(),
207 const FunctionSpace& what=FunctionSpace(),
208 bool expanded=false);
209
210 /**
211 \brief
212 Perform a deep copy.
213 */
214 void
215 copy(const Data& other);
216
217 /**
218 Member access methods.
219 */
220
221 /**
222 \brief
223 Return the values of all data-points as a single python numarray object.
224 */
225 const boost::python::numeric::array
226 convertToNumArray();
227
228 /**
229 \brief fills the expanded Data object from values of a python numarray object.
230
231 */
232 void
233 fillFromNumArray(const boost::python::numeric::array);
234 /**
235 \brief
236 Return the values of all data-points for the given sample as a single python numarray object.
237 */
238 const boost::python::numeric::array
239 convertToNumArrayFromSampleNo(int sampleNo);
240
241 /**
242 \brief
243 Return the value of the specified data-point as a single python numarray object.
244 */
245 const boost::python::numeric::array
246 convertToNumArrayFromDPNo(int sampleNo,
247 int dataPointNo);
248
249 /**
250 \brief
251 Return the C wrapper for the Data object.
252 */
253 escriptDataC
254 getDataC();
255
256 /**
257 \brief
258 Return the C wrapper for the Data object - const version.
259 */
260 escriptDataC
261 getDataC() const;
262
263 /**
264 \brief
265 Write the data as a string.
266 */
267 inline
268 std::string
269 toString() const
270 {
271 return m_data->toString();
272 }
273
274 /**
275 \brief
276 Return the DataArrayView of the point data. This essentially contains
277 the shape information for each data point although it also may be used
278 to manipulate the point data.
279 */
280 inline
281 const DataArrayView&
282 getPointDataView() const
283 {
284 return m_data->getPointDataView();
285 }
286
287 /**
288 \brief
289 Whatever the current Data type make this into a DataExpanded.
290 */
291 void
292 expand();
293
294 /**
295 \brief
296 If possible convert this Data to DataTagged. This will only allow
297 Constant data to be converted to tagged. An attempt to convert
298 Expanded data to tagged will throw an exception.
299 */
300 void
301 tag();
302
303 /**
304 \brief
305 Return true if this Data is expanded.
306 */
307 bool
308 isExpanded() const;
309
310 /**
311 \brief
312 Return true if this Data is tagged.
313 */
314 bool
315 isTagged() const;
316
317 /**
318 \brief
319 Return true if this Data is constant.
320 */
321 bool
322 isConstant() const;
323
324 /**
325 \brief
326 Return true if this Data is empty.
327 */
328 bool
329 isEmpty() const;
330
331 /**
332 \brief
333 Return the function space.
334 */
335 inline
336 const FunctionSpace&
337 getFunctionSpace() const
338 {
339 return m_data->getFunctionSpace();
340 }
341
342 /**
343 \brief
344 Return a copy of the function space.
345 */
346 const FunctionSpace
347 getCopyOfFunctionSpace() const;
348
349 /**
350 \brief
351 Return the domain.
352 */
353 inline
354 const AbstractDomain&
355 getDomain() const
356 {
357 return getFunctionSpace().getDomain();
358 }
359
360 /**
361 \brief
362 Return a copy of the domain.
363 */
364 const AbstractDomain
365 getCopyOfDomain() const;
366
367 /**
368 \brief
369 Return the rank of the point data.
370 */
371 inline
372 int
373 getDataPointRank() const
374 {
375 return m_data->getPointDataView().getRank();
376 }
377
378 /**
379 \brief
380 Return the number of samples.
381 */
382 inline
383 int
384 getNumSamples() const
385 {
386 return m_data->getNumSamples();
387 }
388
389 /**
390 \brief
391 Return the number of data points per sample.
392 */
393 inline
394 int
395 getNumDataPointsPerSample() const
396 {
397 return m_data->getNumDPPSample();
398 }
399
400 /**
401 \brief
402 Return the sample data for the given sample no. This is not the
403 preferred interface but is provided for use by C code.
404 \param sampleNo - Input - the given sample no.
405 */
406 inline
407 DataAbstract::ValueType::value_type*
408 getSampleData(DataAbstract::ValueType::size_type sampleNo)
409 {
410 return m_data->getSampleData(sampleNo);
411 }
412
413 /**
414 \brief
415 Return the sample data for the given tag. If an attempt is made to
416 access data that isn't tagged an exception will be thrown.
417 \param tag - Input - the tag key.
418 */
419 inline
420 DataAbstract::ValueType::value_type*
421 getSampleDataByTag(int tag)
422 {
423 return m_data->getSampleDataByTag(tag);
424 }
425
426 /**
427 \brief
428 Assign the given value to the data-points referenced by the given
429 reference number.
430
431 The value supplied is a python numarray object. The data from this numarray
432 is unpacked into a DataArray, and this is used to set the corresponding
433 data-points in the underlying Data object.
434
435 If the underlying Data object cannot be accessed via reference numbers, an
436 exception will be thrown.
437
438 \param ref - Input - reference number.
439 \param value - Input - value to assign to data-points associated with
440 the given reference number.
441 */
442 void
443 setRefValue(int ref,
444 const boost::python::numeric::array& value);
445
446 /**
447 \brief
448 Return the values associated with the data-points referenced by the given
449 reference number.
450
451 The value supplied is a python numarray object. The data from the corresponding
452 data-points in this Data object are packed into the given numarray object.
453
454 If the underlying Data object cannot be accessed via reference numbers, an
455 exception will be thrown.
456
457 \param ref - Input - reference number.
458 \param value - Output - object to receive values from data-points
459 associated with the given reference number.
460 */
461 void
462 getRefValue(int ref,
463 boost::python::numeric::array& value);
464
465 /**
466 \brief
467 Return a view into the data for the data point specified.
468 NOTE: Construction of the DataArrayView is a relatively expensive
469 operation.
470 \param sampleNo - Input -
471 \param dataPointNo - Input -
472 */
473 inline
474 DataArrayView
475 getDataPoint(int sampleNo,
476 int dataPointNo)
477 {
478 return m_data->getDataPoint(sampleNo,dataPointNo);
479 }
480
481 /**
482 \brief
483 Return a reference to the data point shape.
484 */
485 const DataArrayView::ShapeType&
486 getDataPointShape() const;
487
488 /**
489 \brief
490 Return the data point shape as a tuple of integers.
491 */
492 const boost::python::tuple
493 getShapeTuple() const;
494
495 /**
496 \brief
497 Return the size of the data point. It is the product of the
498 data point shape dimensions.
499 */
500 int
501 getDataPointSize() const;
502
503 /**
504 \brief
505 Return the number of doubles stored for this Data.
506 */
507 DataArrayView::ValueType::size_type
508 getLength() const;
509
510 /**
511 \brief
512 Assign the given value to the tag. Implicitly converts this
513 object to type DataTagged. Throws an exception if this object
514 cannot be converted to a DataTagged object.
515 \param tagKey - Input - Integer key.
516 \param value - Input - Value to associate with given key.
517 */
518 void
519 setTaggedValue(int tagKey,
520 const boost::python::object& value);
521
522 /**
523 \brief
524 Assign the given value to the tag. Implicitly converts this
525 object to type DataTagged. Throws an exception if this object
526 cannot be converted to a DataTagged object.
527 \param tagKey - Input - Integer key.
528 \param value - Input - Value to associate with given key.
529 */
530 void
531 setTaggedValueFromCPP(int tagKey,
532 const DataArrayView& value);
533
534 /**
535 \brief
536 Copy other Data object into this Data object where mask is positive.
537 */
538 void
539 copyWithMask(const Data& other,
540 const Data& mask);
541
542 /**
543 Data object operation methods and operators.
544 */
545
546 /**
547 \brief
548 Interpolates this onto the given functionspace and returns
549 the result as a Data object.
550 *
551 */
552 Data
553 interpolate(const FunctionSpace& functionspace) const;
554
555 /**
556 \brief
557 Calculates the gradient of the data at the data points of functionspace.
558 If functionspace is not present the function space of Function(getDomain()) is used.
559 *
560 */
561 Data
562 gradOn(const FunctionSpace& functionspace) const;
563
564 Data
565 grad() const;
566
567 /**
568 \brief
569 Calculate the integral over the function space domain.
570 *
571 */
572 boost::python::numeric::array
573 integrate() const;
574
575 /**
576 \brief
577 Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.
578 *
579 */
580 Data
581 wherePositive() const;
582
583 /**
584 \brief
585 Return a Data with a 1 for -ive values and a 0 for +ive or 0 values.
586 *
587 */
588 Data
589 whereNegative() const;
590
591 /**
592 \brief
593 Return a Data with a 1 for +ive or 0 values and a 0 for -ive values.
594 *
595 */
596 Data
597 whereNonNegative() const;
598
599 /**
600 \brief
601 Return a Data with a 1 for -ive or 0 values and a 0 for +ive values.
602 *
603 */
604 Data
605 whereNonPositive() const;
606
607 /**
608 \brief
609 Return a Data with a 1 for 0 values and a 0 for +ive or -ive values.
610 *
611 */
612 Data
613 whereZero() const;
614
615 /**
616 \brief
617 Return a Data with a 0 for 0 values and a 1 for +ive or -ive values.
618 *
619 */
620 Data
621 whereNonZero() const;
622
623 /**
624 \brief
625 Return the maximum absolute value of this Data object.
626 *
627 */
628 double
629 Lsup() const;
630
631 /**
632 \brief
633 Return the minimum absolute value of this Data object.
634 *
635 */
636 double
637 Linf() const;
638
639 /**
640 \brief
641 Return the maximum value of this Data object.
642 *
643 */
644 double
645 sup() const;
646
647 /**
648 \brief
649 Return the minimum value of this Data object.
650 *
651 */
652 double
653 inf() const;
654
655 /**
656 \brief
657 Return the absolute value of each data point of this Data object.
658 *
659 */
660 Data
661 abs() const;
662
663 /**
664 \brief
665 Return the maximum value of each data point of this Data object.
666 *
667 */
668 Data
669 maxval() const;
670
671 /**
672 \brief
673 Return the minimum value of each data point of this Data object.
674 *
675 */
676 Data
677 minval() const;
678
679 /**
680 \brief
681 Return the (sample number, data-point number) of the data point with
682 the minimum value in this Data object.
683 */
684 const boost::python::tuple
685 mindp() const;
686
687 /**
688 \brief
689 Return the length of each data point of this Data object.
690 sqrt(sum(A[i,j,k,l]^2))
691 *
692 */
693 Data
694 length() const;
695
696 /**
697 \brief
698 Return the sign of each data point of this Data object.
699 -1 for negative values, zero for zero values, 1 for positive values.
700 *
701 */
702 Data
703 sign() const;
704
705 /**
706 \brief
707 Transpose each data point of this Data object around the given axis.
708 --* not implemented yet *--
709 *
710 */
711 Data
712 transpose(int axis) const;
713
714 /**
715 \brief
716 Calculate the trace of each data point of this Data object.
717 sum(A[i,i,i,i])
718 *
719 */
720 Data
721 trace() const;
722
723 /**
724 \brief
725 Return the sin of each data point of this Data object.
726 *
727 */
728 Data
729 sin() const;
730
731 /**
732 \brief
733 Return the cos of each data point of this Data object.
734 *
735 */
736 Data
737 cos() const;
738
739 /**
740 \brief
741 Return the tan of each data point of this Data object.
742 *
743 */
744 Data
745 tan() const;
746
747 /**
748 \brief
749 Return the log to base 10 of each data point of this Data object.
750 *
751 */
752 Data
753 log() const;
754
755 /**
756 \brief
757 Return the natural log of each data point of this Data object.
758 *
759 */
760 Data
761 ln() const;
762
763 /**
764 \brief
765 Return the exponential function of each data point of this Data object.
766 *
767 */
768 Data
769 exp() const;
770
771 /**
772 \brief
773 Return the square root of each data point of this Data object.
774 *
775 */
776 Data
777 sqrt() const;
778
779 /**
780 \brief
781 Return the negation of each data point of this Data object.
782 *
783 */
784 Data
785 neg() const;
786
787 /**
788 \brief
789 Return the identity of each data point of this Data object.
790 Simply returns this object unmodified.
791 *
792 */
793 Data
794 pos() const;
795
796 /**
797 \brief
798 Return the given power of each data point of this Data object.
799
800 \param right Input - the power to raise the object to.
801 *
802 */
803 Data
804 powD(const Data& right) const;
805
806 /**
807 \brief
808 Return the given power of each data point of this boost python object.
809
810 \param right Input - the power to raise the object to.
811 *
812 */
813 Data
814 powO(const boost::python::object& right) const;
815
816 /**
817 \brief
818 writes the object to a file in the DX file format
819 */
820 void
821 saveDX(std::string fileName) const;
822
823 /**
824 \brief
825 writes the object to a file in the VTK file format
826 */
827 void
828 saveVTK(std::string fileName) const;
829
830 /**
831 \brief
832 Overloaded operator +=
833 \param right - Input - The right hand side.
834 *
835 */
836 Data& operator+=(const Data& right);
837 Data& operator+=(const boost::python::object& right);
838
839 /**
840 \brief
841 Overloaded operator -=
842 \param right - Input - The right hand side.
843 *
844 */
845 Data& operator-=(const Data& right);
846 Data& operator-=(const boost::python::object& right);
847
848 /**
849 \brief
850 Overloaded operator *=
851 \param right - Input - The right hand side.
852 *
853 */
854 Data& operator*=(const Data& right);
855 Data& operator*=(const boost::python::object& right);
856
857 /**
858 \brief
859 Overloaded operator /=
860 \param right - Input - The right hand side.
861 *
862 */
863 Data& operator/=(const Data& right);
864 Data& operator/=(const boost::python::object& right);
865
866 /**
867 \brief
868 Returns true if this can be interpolated to functionspace.
869 */
870 bool
871 probeInterpolation(const FunctionSpace& functionspace) const;
872
873 /**
874 Data object slicing methods.
875 */
876
877 /**
878 \brief
879 Returns a slice from this Data object.
880
881 /description
882 Implements the [] get operator in python.
883 Calls getSlice.
884
885 \param key - Input - python slice tuple specifying
886 slice to return.
887 */
888 Data
889 getItem(const boost::python::object& key) const;
890
891 /**
892 \brief
893 Copies slice from value into this Data object.
894
895 Implements the [] set operator in python.
896 Calls setSlice.
897
898 \param key - Input - python slice tuple specifying
899 slice to copy from value.
900 \param value - Input - Data object to copy from.
901 */
902 void
903 setItemD(const boost::python::object& key,
904 const Data& value);
905
906 void
907 setItemO(const boost::python::object& key,
908 const boost::python::object& value);
909
910 // These following public methods should be treated as private.
911
912 /**
913 \brief
914 Perform the given unary operation on every element of every data point in
915 this Data object.
916 */
917 template <class UnaryFunction>
918 inline
919 void
920 unaryOp(UnaryFunction operation);
921
922 /**
923 \brief
924 Return a Data object containing the specified slice of
925 this Data object.
926 \param region - Input - Region to copy.
927 *
928 */
929 Data
930 getSlice(const DataArrayView::RegionType& region) const;
931
932 /**
933 \brief
934 Copy the specified slice from the given value into this
935 Data object.
936 \param value - Input - Data to copy from.
937 \param region - Input - Region to copy.
938 *
939 */
940 void
941 setSlice(const Data& value,
942 const DataArrayView::RegionType& region);
943
944 /**
945 \brief
946 Archive the current Data object to the given file.
947 \param fileName - Input - file to archive to.
948 */
949 void
950 archiveData(const std::string fileName);
951
952 /**
953 \brief
954 Extract the Data object archived in the given file, overwriting
955 the current Data object.
956 Note - the current object must be of type DataEmpty.
957 \param fileName - Input - file to extract from.
958 \param fspace - Input - a suitable FunctionSpace descibing the data.
959 */
960 void
961 extractData(const std::string fileName,
962 const FunctionSpace& fspace);
963
964 protected:
965
966 private:
967
968 /**
969 \brief
970 Check *this and the right operand are compatible. Throws
971 an exception if they aren't.
972 \param right - Input - The right hand side.
973 */
974 inline
975 void
976 operandCheck(const Data& right) const
977 {
978 return m_data->operandCheck(*(right.m_data.get()));
979 }
980
981 /**
982 \brief
983 Perform the specified reduction algorithm on every element of every data point in
984 this Data object according to the given function and return the single value result.
985 */
986 template <class BinaryFunction>
987 inline
988 double
989 algorithm(BinaryFunction operation,
990 double initial_value) const;
991
992 /**
993 \brief
994 Reduce each data-point in this Data object using the given operation. Return a Data
995 object with the same number of data-points, but with each data-point containing only
996 one value - the result of the reduction operation on the corresponding data-point in
997 this Data object
998 */
999 template <class BinaryFunction>
1000 inline
1001 Data
1002 dp_algorithm(BinaryFunction operation,
1003 double initial_value) const;
1004
1005 /**
1006 \brief
1007 Perform the given binary operation on all of the data's elements.
1008 The underlying type of the right hand side (right) determines the final
1009 type of *this after the operation. For example if the right hand side
1010 is expanded *this will be expanded if necessary.
1011 RHS is a Data object.
1012 */
1013 template <class BinaryFunction>
1014 inline
1015 void
1016 binaryOp(const Data& right,
1017 BinaryFunction operation);
1018
1019 /**
1020 \brief
1021 Perform the given binary operation on all of the data's elements.
1022 RHS is a boost::python object.
1023 */
1024 template <class BinaryFunction>
1025 inline
1026 void
1027 binaryOp(const boost::python::object& right,
1028 BinaryFunction operation);
1029
1030 /**
1031 \brief
1032 Convert the data type of the RHS to match this.
1033 \param right - Input - data type to match.
1034 */
1035 void
1036 typeMatchLeft(Data& right) const;
1037
1038 /**
1039 \brief
1040 Convert the data type of this to match the RHS.
1041 \param right - Input - data type to match.
1042 */
1043 void
1044 typeMatchRight(const Data& right);
1045
1046 /**
1047 \brief
1048 Construct a Data object of the appropriate type.
1049 */
1050 template <class IValueType>
1051 void
1052 initialise(const IValueType& value,
1053 const FunctionSpace& what,
1054 bool expanded);
1055
1056 /**
1057 \brief
1058 Reshape the data point if the data point is currently rank 0.
1059 Will throw an exception if the data points are not rank 0.
1060 The original data point value is used for all values of the new
1061 data point.
1062 */
1063 void
1064 reshapeDataPoint(const DataArrayView::ShapeType& shape);
1065
1066 //
1067 // pointer to the actual data object
1068 boost::shared_ptr<DataAbstract> m_data;
1069
1070 //
1071 // pointer to the internal profiling data
1072 struct profDataEntry *profData;
1073
1074 };
1075
1076 template <class IValueType>
1077 void
1078 Data::initialise(const IValueType& value,
1079 const FunctionSpace& what,
1080 bool expanded)
1081 {
1082 //
1083 // Construct a Data object of the appropriate type.
1084 // Construct the object first as there seems to be a bug which causes
1085 // undefined behaviour if an exception is thrown during construction
1086 // within the shared_ptr constructor.
1087 if (expanded) {
1088 DataAbstract* temp=new DataExpanded(value,what);
1089 boost::shared_ptr<DataAbstract> temp_data(temp);
1090 m_data=temp_data;
1091 } else {
1092 DataAbstract* temp=new DataConstant(value,what);
1093 boost::shared_ptr<DataAbstract> temp_data(temp);
1094 m_data=temp_data;
1095 }
1096 }
1097
1098 /**
1099 Binary Data object operators.
1100 */
1101
1102 /**
1103 \brief
1104 Operator+
1105 Takes two Data objects.
1106 */
1107 Data operator+(const Data& left, const Data& right);
1108
1109 /**
1110 \brief
1111 Operator-
1112 Takes two Data objects.
1113 */
1114 Data operator-(const Data& left, const Data& right);
1115
1116 /**
1117 \brief
1118 Operator*
1119 Takes two Data objects.
1120 */
1121 Data operator*(const Data& left, const Data& right);
1122
1123 /**
1124 \brief
1125 Operator/
1126 Takes two Data objects.
1127 */
1128 Data operator/(const Data& left, const Data& right);
1129
1130 /**
1131 \brief
1132 Operator+
1133 Takes LHS Data object and RHS python::object.
1134 python::object must be convertable to Data type.
1135 */
1136 Data operator+(const Data& left, const boost::python::object& right);
1137
1138 /**
1139 \brief
1140 Operator-
1141 Takes LHS Data object and RHS python::object.
1142 python::object must be convertable to Data type.
1143 */
1144 Data operator-(const Data& left, const boost::python::object& right);
1145
1146 /**
1147 \brief
1148 Operator*
1149 Takes LHS Data object and RHS python::object.
1150 python::object must be convertable to Data type.
1151 */
1152 Data operator*(const Data& left, const boost::python::object& right);
1153
1154 /**
1155 \brief
1156 Operator/
1157 Takes LHS Data object and RHS python::object.
1158 python::object must be convertable to Data type.
1159 */
1160 Data operator/(const Data& left, const boost::python::object& right);
1161
1162 /**
1163 \brief
1164 Operator+
1165 Takes LHS python::object and RHS Data object.
1166 python::object must be convertable to Data type.
1167 */
1168 Data operator+(const boost::python::object& left, const Data& right);
1169
1170 /**
1171 \brief
1172 Operator-
1173 Takes LHS python::object and RHS Data object.
1174 python::object must be convertable to Data type.
1175 */
1176 Data operator-(const boost::python::object& left, const Data& right);
1177
1178 /**
1179 \brief
1180 Operator*
1181 Takes LHS python::object and RHS Data object.
1182 python::object must be convertable to Data type.
1183 */
1184 Data operator*(const boost::python::object& left, const Data& right);
1185
1186 /**
1187 \brief
1188 Operator/
1189 Takes LHS python::object and RHS Data object.
1190 python::object must be convertable to Data type.
1191 */
1192 Data operator/(const boost::python::object& left, const Data& right);
1193
1194 /**
1195 \brief
1196 Output operator
1197 */
1198 std::ostream& operator<<(std::ostream& o, const Data& data);
1199
1200 /**
1201 \brief
1202 Return true if operands are equivalent, else return false.
1203 NB: this operator does very little at this point, and isn't to
1204 be relied on. Requires further implementation.
1205 */
1206 //bool operator==(const Data& left, const Data& right);
1207
1208 /**
1209 \brief
1210 Perform the given binary operation with this and right as operands.
1211 Right is a Data object.
1212 */
1213 template <class BinaryFunction>
1214 inline
1215 void
1216 Data::binaryOp(const Data& right,
1217 BinaryFunction operation)
1218 {
1219 //
1220 // if this has a rank of zero promote it to the rank of the RHS
1221 if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {
1222 reshapeDataPoint(right.getPointDataView().getShape());
1223 }
1224 //
1225 // initially make the temporary a shallow copy
1226 Data tempRight(right);
1227 if (getFunctionSpace()!=right.getFunctionSpace()) {
1228 if (right.probeInterpolation(getFunctionSpace())) {
1229 //
1230 // an interpolation is required so create a new Data
1231 tempRight=Data(right,this->getFunctionSpace());
1232 } else if (probeInterpolation(right.getFunctionSpace())) {
1233 //
1234 // interpolate onto the RHS function space
1235 Data tempLeft(*this,right.getFunctionSpace());
1236 m_data=tempLeft.m_data;
1237 }
1238 }
1239 operandCheck(tempRight);
1240 //
1241 // ensure this has the right type for the RHS
1242 typeMatchRight(tempRight);
1243 //
1244 // Need to cast to the concrete types so that the correct binaryOp
1245 // is called.
1246 if (isExpanded()) {
1247 //
1248 // Expanded data will be done in parallel, the right hand side can be
1249 // of any data type
1250 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1251 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1252 escript::binaryOp(*leftC,*(tempRight.m_data.get()),operation);
1253 } else if (isTagged()) {
1254 //
1255 // Tagged data is operated on serially, the right hand side can be
1256 // either DataConstant or DataTagged
1257 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1258 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1259 if (right.isTagged()) {
1260 DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get());
1261 EsysAssert((rightC!=0), "Programming error - casting to DataTagged.");
1262 escript::binaryOp(*leftC,*rightC,operation);
1263 } else {
1264 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1265 EsysAssert((rightC!=0), "Programming error - casting to DataConstant.");
1266 escript::binaryOp(*leftC,*rightC,operation);
1267 }
1268 } else if (isConstant()) {
1269 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1270 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1271 EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1272 escript::binaryOp(*leftC,*rightC,operation);
1273 }
1274 }
1275
1276 /**
1277 \brief
1278 Perform the given binary operation with this and right as operands.
1279 Right is a boost::python object.
1280 */
1281 template <class BinaryFunction>
1282 inline
1283 void
1284 Data::binaryOp(const boost::python::object& right,
1285 BinaryFunction operation)
1286 {
1287 DataArray temp(right);
1288 //
1289 // if this has a rank of zero promote it to the rank of the RHS.
1290 if (getPointDataView().getRank()==0 && temp.getView().getRank()!=0) {
1291 reshapeDataPoint(temp.getView().getShape());
1292 }
1293 //
1294 // Always allow scalar values for the RHS but check other shapes
1295 if (temp.getView().getRank()!=0) {
1296 if (!getPointDataView().checkShape(temp.getView().getShape())) {
1297 throw DataException(getPointDataView().createShapeErrorMessage(
1298 "Error - RHS shape doesn't match LHS shape.",temp.getView().getShape()));
1299 }
1300 }
1301 if (isExpanded()) {
1302 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1303 EsysAssert((leftC!=0),"Programming error - casting to DataExpanded.");
1304 escript::binaryOp(*leftC,temp.getView(),operation);
1305 } else if (isTagged()) {
1306 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1307 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1308 escript::binaryOp(*leftC,temp.getView(),operation);
1309 } else if (isConstant()) {
1310 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1311 EsysAssert((leftC!=0),"Programming error - casting to DataConstant.");
1312 escript::binaryOp(*leftC,temp.getView(),operation);
1313 }
1314 }
1315
1316 /**
1317 \brief
1318 Perform the given unary operation on other and return the result.
1319 Given operation is performed on each element of each data point, thus
1320 argument object is a rank n Data object, and returned object is a rank n
1321 Data object.
1322 Calls Data::unaryOp.
1323 */
1324 template <class UnaryFunction>
1325 inline
1326 Data
1327 unaryOp(const Data& other,
1328 UnaryFunction operation)
1329 {
1330 Data result;
1331 result.copy(other);
1332 result.unaryOp(operation);
1333 return result;
1334 }
1335
1336 /**
1337 \brief
1338 Perform the given unary operation on this.
1339 Given operation is performed on each element of each data point.
1340 Calls escript::unaryOp.
1341 */
1342 template <class UnaryFunction>
1343 inline
1344 void
1345 Data::unaryOp(UnaryFunction operation)
1346 {
1347 if (isExpanded()) {
1348 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1349 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1350 escript::unaryOp(*leftC,operation);
1351 } else if (isTagged()) {
1352 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1353 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1354 escript::unaryOp(*leftC,operation);
1355 } else if (isConstant()) {
1356 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1357 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1358 escript::unaryOp(*leftC,operation);
1359 }
1360 }
1361
1362 /**
1363 \brief
1364 Perform the given Data object reduction algorithm on this and return the result.
1365 Given operation combines each element of each data point, thus argument
1366 object (*this) is a rank n Data object, and returned object is a scalar.
1367 Calls escript::algorithm.
1368 */
1369 template <class BinaryFunction>
1370 inline
1371 double
1372 Data::algorithm(BinaryFunction operation, double initial_value) const
1373 {
1374 if (isExpanded()) {
1375 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1376 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1377 return escript::algorithm(*leftC,operation,initial_value);
1378 } else if (isTagged()) {
1379 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1380 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1381 return escript::algorithm(*leftC,operation,initial_value);
1382 } else if (isConstant()) {
1383 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1384 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1385 return escript::algorithm(*leftC,operation,initial_value);
1386 }
1387 return 0;
1388 }
1389
1390 /**
1391 \brief
1392 Perform the given data point reduction algorithm on data and return the result.
1393 Given operation combines each element within each data point into a scalar,
1394 thus argument object is a rank n Data object, and returned object is a
1395 rank 0 Data object.
1396 Calls escript::dp_algorithm.
1397 */
1398 template <class BinaryFunction>
1399 inline
1400 Data
1401 Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1402 {
1403 Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());
1404 if (isExpanded()) {
1405 DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1406 DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1407 EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1408 EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1409 escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1410 } else if (isTagged()) {
1411 DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
1412 DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());
1413 EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1414 EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");
1415 escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1416 } else if (isConstant()) {
1417 DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1418 DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1419 EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1420 EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1421 escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1422 }
1423 return result;
1424 }
1425
1426 }
1427 #endif

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26