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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26