/[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 148 - (show annotations)
Tue Aug 23 01:24:31 2005 UTC (14 years, 1 month ago) by jgs
Original Path: trunk/esys2/escript/src/Data/Data.h
File MIME type: text/plain
File size: 36611 byte(s)
Merge of development branch dev-02 back to main trunk on 2005-08-23

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 void
688 calc_mindp(int& SampleNo,
689 int& DataPointNo) const;
690
691 /**
692 \brief
693 Return the length of each data point of this Data object.
694 sqrt(sum(A[i,j,k,l]^2))
695 *
696 */
697 Data
698 length() const;
699
700 /**
701 \brief
702 Return the sign of each data point of this Data object.
703 -1 for negative values, zero for zero values, 1 for positive values.
704 *
705 */
706 Data
707 sign() const;
708
709 /**
710 \brief
711 Transpose each data point of this Data object around the given axis.
712 --* not implemented yet *--
713 *
714 */
715 Data
716 transpose(int axis) const;
717
718 /**
719 \brief
720 Calculate the trace of each data point of this Data object.
721 sum(A[i,i,i,i])
722 *
723 */
724 Data
725 trace() const;
726
727 /**
728 \brief
729 Return the sin of each data point of this Data object.
730 *
731 */
732 Data
733 sin() const;
734
735 /**
736 \brief
737 Return the cos of each data point of this Data object.
738 *
739 */
740 Data
741 cos() const;
742
743 /**
744 \brief
745 Return the tan of each data point of this Data object.
746 *
747 */
748 Data
749 tan() const;
750
751 /**
752 \brief
753 Return the log to base 10 of each data point of this Data object.
754 *
755 */
756 Data
757 log() const;
758
759 /**
760 \brief
761 Return the natural log of each data point of this Data object.
762 *
763 */
764 Data
765 ln() const;
766
767 /**
768 \brief
769 Return the exponential function of each data point of this Data object.
770 *
771 */
772 Data
773 exp() const;
774
775 /**
776 \brief
777 Return the square root of each data point of this Data object.
778 *
779 */
780 Data
781 sqrt() const;
782
783 /**
784 \brief
785 Return the negation of each data point of this Data object.
786 *
787 */
788 Data
789 neg() const;
790
791 /**
792 \brief
793 Return the identity of each data point of this Data object.
794 Simply returns this object unmodified.
795 *
796 */
797 Data
798 pos() const;
799
800 /**
801 \brief
802 Return the given power of each data point of this Data object.
803
804 \param right Input - the power to raise the object to.
805 *
806 */
807 Data
808 powD(const Data& right) const;
809
810 /**
811 \brief
812 Return the given power of each data point of this boost python object.
813
814 \param right Input - the power to raise the object to.
815 *
816 */
817 Data
818 powO(const boost::python::object& right) const;
819
820 /**
821 \brief
822 writes the object to a file in the DX file format
823 */
824 void
825 saveDX(std::string fileName) const;
826
827 /**
828 \brief
829 writes the object to a file in the VTK file format
830 */
831 void
832 saveVTK(std::string fileName) const;
833
834 /**
835 \brief
836 Overloaded operator +=
837 \param right - Input - The right hand side.
838 *
839 */
840 Data& operator+=(const Data& right);
841 Data& operator+=(const boost::python::object& right);
842
843 /**
844 \brief
845 Overloaded operator -=
846 \param right - Input - The right hand side.
847 *
848 */
849 Data& operator-=(const Data& right);
850 Data& operator-=(const boost::python::object& right);
851
852 /**
853 \brief
854 Overloaded operator *=
855 \param right - Input - The right hand side.
856 *
857 */
858 Data& operator*=(const Data& right);
859 Data& operator*=(const boost::python::object& right);
860
861 /**
862 \brief
863 Overloaded operator /=
864 \param right - Input - The right hand side.
865 *
866 */
867 Data& operator/=(const Data& right);
868 Data& operator/=(const boost::python::object& right);
869
870 /**
871 \brief
872 Returns true if this can be interpolated to functionspace.
873 */
874 bool
875 probeInterpolation(const FunctionSpace& functionspace) const;
876
877 /**
878 Data object slicing methods.
879 */
880
881 /**
882 \brief
883 Returns a slice from this Data object.
884
885 /description
886 Implements the [] get operator in python.
887 Calls getSlice.
888
889 \param key - Input - python slice tuple specifying
890 slice to return.
891 */
892 Data
893 getItem(const boost::python::object& key) const;
894
895 /**
896 \brief
897 Copies slice from value into this Data object.
898
899 Implements the [] set operator in python.
900 Calls setSlice.
901
902 \param key - Input - python slice tuple specifying
903 slice to copy from value.
904 \param value - Input - Data object to copy from.
905 */
906 void
907 setItemD(const boost::python::object& key,
908 const Data& value);
909
910 void
911 setItemO(const boost::python::object& key,
912 const boost::python::object& value);
913
914 // These following public methods should be treated as private.
915
916 /**
917 \brief
918 Perform the given unary operation on every element of every data point in
919 this Data object.
920 */
921 template <class UnaryFunction>
922 inline
923 void
924 unaryOp(UnaryFunction operation);
925
926 /**
927 \brief
928 Return a Data object containing the specified slice of
929 this Data object.
930 \param region - Input - Region to copy.
931 *
932 */
933 Data
934 getSlice(const DataArrayView::RegionType& region) const;
935
936 /**
937 \brief
938 Copy the specified slice from the given value into this
939 Data object.
940 \param value - Input - Data to copy from.
941 \param region - Input - Region to copy.
942 *
943 */
944 void
945 setSlice(const Data& value,
946 const DataArrayView::RegionType& region);
947
948 /**
949 \brief
950 Archive the current Data object to the given file.
951 \param fileName - Input - file to archive to.
952 */
953 void
954 archiveData(const std::string fileName);
955
956 /**
957 \brief
958 Extract the Data object archived in the given file, overwriting
959 the current Data object.
960 Note - the current object must be of type DataEmpty.
961 \param fileName - Input - file to extract from.
962 \param fspace - Input - a suitable FunctionSpace descibing the data.
963 */
964 void
965 extractData(const std::string fileName,
966 const FunctionSpace& fspace);
967
968 protected:
969
970 private:
971
972 /**
973 \brief
974 Check *this and the right operand are compatible. Throws
975 an exception if they aren't.
976 \param right - Input - The right hand side.
977 */
978 inline
979 void
980 operandCheck(const Data& right) const
981 {
982 return m_data->operandCheck(*(right.m_data.get()));
983 }
984
985 /**
986 \brief
987 Perform the specified reduction algorithm on every element of every data point in
988 this Data object according to the given function and return the single value result.
989 */
990 template <class BinaryFunction>
991 inline
992 double
993 algorithm(BinaryFunction operation,
994 double initial_value) const;
995
996 /**
997 \brief
998 Reduce each data-point in this Data object using the given operation. Return a Data
999 object with the same number of data-points, but with each data-point containing only
1000 one value - the result of the reduction operation on the corresponding data-point in
1001 this Data object
1002 */
1003 template <class BinaryFunction>
1004 inline
1005 Data
1006 dp_algorithm(BinaryFunction operation,
1007 double initial_value) const;
1008
1009 /**
1010 \brief
1011 Perform the given binary operation on all of the data's elements.
1012 The underlying type of the right hand side (right) determines the final
1013 type of *this after the operation. For example if the right hand side
1014 is expanded *this will be expanded if necessary.
1015 RHS is a Data object.
1016 */
1017 template <class BinaryFunction>
1018 inline
1019 void
1020 binaryOp(const Data& right,
1021 BinaryFunction operation);
1022
1023 /**
1024 \brief
1025 Perform the given binary operation on all of the data's elements.
1026 RHS is a boost::python object.
1027 */
1028 template <class BinaryFunction>
1029 inline
1030 void
1031 binaryOp(const boost::python::object& right,
1032 BinaryFunction operation);
1033
1034 /**
1035 \brief
1036 Convert the data type of the RHS to match this.
1037 \param right - Input - data type to match.
1038 */
1039 void
1040 typeMatchLeft(Data& right) const;
1041
1042 /**
1043 \brief
1044 Convert the data type of this to match the RHS.
1045 \param right - Input - data type to match.
1046 */
1047 void
1048 typeMatchRight(const Data& right);
1049
1050 /**
1051 \brief
1052 Construct a Data object of the appropriate type.
1053 */
1054 template <class IValueType>
1055 void
1056 initialise(const IValueType& value,
1057 const FunctionSpace& what,
1058 bool expanded);
1059
1060 /**
1061 \brief
1062 Reshape the data point if the data point is currently rank 0.
1063 Will throw an exception if the data points are not rank 0.
1064 The original data point value is used for all values of the new
1065 data point.
1066 */
1067 void
1068 reshapeDataPoint(const DataArrayView::ShapeType& shape);
1069
1070 //
1071 // pointer to the actual data object
1072 boost::shared_ptr<DataAbstract> m_data;
1073
1074 //
1075 // pointer to the internal profiling data
1076 struct profDataEntry *profData;
1077
1078 };
1079
1080 template <class IValueType>
1081 void
1082 Data::initialise(const IValueType& value,
1083 const FunctionSpace& what,
1084 bool expanded)
1085 {
1086 //
1087 // Construct a Data object of the appropriate type.
1088 // Construct the object first as there seems to be a bug which causes
1089 // undefined behaviour if an exception is thrown during construction
1090 // within the shared_ptr constructor.
1091 if (expanded) {
1092 DataAbstract* temp=new DataExpanded(value,what);
1093 boost::shared_ptr<DataAbstract> temp_data(temp);
1094 m_data=temp_data;
1095 } else {
1096 DataAbstract* temp=new DataConstant(value,what);
1097 boost::shared_ptr<DataAbstract> temp_data(temp);
1098 m_data=temp_data;
1099 }
1100 }
1101
1102 /**
1103 Binary Data object operators.
1104 */
1105
1106 /**
1107 \brief
1108 Operator+
1109 Takes two Data objects.
1110 */
1111 Data operator+(const Data& left, const Data& right);
1112
1113 /**
1114 \brief
1115 Operator-
1116 Takes two Data objects.
1117 */
1118 Data operator-(const Data& left, const Data& right);
1119
1120 /**
1121 \brief
1122 Operator*
1123 Takes two Data objects.
1124 */
1125 Data operator*(const Data& left, const Data& right);
1126
1127 /**
1128 \brief
1129 Operator/
1130 Takes two Data objects.
1131 */
1132 Data operator/(const Data& left, const Data& right);
1133
1134 /**
1135 \brief
1136 Operator+
1137 Takes LHS Data object and RHS python::object.
1138 python::object must be convertable to Data type.
1139 */
1140 Data operator+(const Data& left, const boost::python::object& right);
1141
1142 /**
1143 \brief
1144 Operator-
1145 Takes LHS Data object and RHS python::object.
1146 python::object must be convertable to Data type.
1147 */
1148 Data operator-(const Data& left, const boost::python::object& right);
1149
1150 /**
1151 \brief
1152 Operator*
1153 Takes LHS Data object and RHS python::object.
1154 python::object must be convertable to Data type.
1155 */
1156 Data operator*(const Data& left, const boost::python::object& right);
1157
1158 /**
1159 \brief
1160 Operator/
1161 Takes LHS Data object and RHS python::object.
1162 python::object must be convertable to Data type.
1163 */
1164 Data operator/(const Data& left, const boost::python::object& right);
1165
1166 /**
1167 \brief
1168 Operator+
1169 Takes LHS python::object and RHS Data object.
1170 python::object must be convertable to Data type.
1171 */
1172 Data operator+(const boost::python::object& left, const Data& right);
1173
1174 /**
1175 \brief
1176 Operator-
1177 Takes LHS python::object and RHS Data object.
1178 python::object must be convertable to Data type.
1179 */
1180 Data operator-(const boost::python::object& left, const Data& right);
1181
1182 /**
1183 \brief
1184 Operator*
1185 Takes LHS python::object and RHS Data object.
1186 python::object must be convertable to Data type.
1187 */
1188 Data operator*(const boost::python::object& left, const Data& right);
1189
1190 /**
1191 \brief
1192 Operator/
1193 Takes LHS python::object and RHS Data object.
1194 python::object must be convertable to Data type.
1195 */
1196 Data operator/(const boost::python::object& left, const Data& right);
1197
1198 /**
1199 \brief
1200 Output operator
1201 */
1202 std::ostream& operator<<(std::ostream& o, const Data& data);
1203
1204 /**
1205 \brief
1206 Return true if operands are equivalent, else return false.
1207 NB: this operator does very little at this point, and isn't to
1208 be relied on. Requires further implementation.
1209 */
1210 //bool operator==(const Data& left, const Data& right);
1211
1212 /**
1213 \brief
1214 Perform the given binary operation with this and right as operands.
1215 Right is a Data object.
1216 */
1217 template <class BinaryFunction>
1218 inline
1219 void
1220 Data::binaryOp(const Data& right,
1221 BinaryFunction operation)
1222 {
1223 //
1224 // if this has a rank of zero promote it to the rank of the RHS
1225 if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {
1226 reshapeDataPoint(right.getPointDataView().getShape());
1227 }
1228 //
1229 // initially make the temporary a shallow copy
1230 Data tempRight(right);
1231 if (getFunctionSpace()!=right.getFunctionSpace()) {
1232 if (right.probeInterpolation(getFunctionSpace())) {
1233 //
1234 // an interpolation is required so create a new Data
1235 tempRight=Data(right,this->getFunctionSpace());
1236 } else if (probeInterpolation(right.getFunctionSpace())) {
1237 //
1238 // interpolate onto the RHS function space
1239 Data tempLeft(*this,right.getFunctionSpace());
1240 m_data=tempLeft.m_data;
1241 }
1242 }
1243 operandCheck(tempRight);
1244 //
1245 // ensure this has the right type for the RHS
1246 typeMatchRight(tempRight);
1247 //
1248 // Need to cast to the concrete types so that the correct binaryOp
1249 // is called.
1250 if (isExpanded()) {
1251 //
1252 // Expanded data will be done in parallel, the right hand side can be
1253 // of any data type
1254 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1255 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1256 escript::binaryOp(*leftC,*(tempRight.m_data.get()),operation);
1257 } else if (isTagged()) {
1258 //
1259 // Tagged data is operated on serially, the right hand side can be
1260 // either DataConstant or DataTagged
1261 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1262 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1263 if (right.isTagged()) {
1264 DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get());
1265 EsysAssert((rightC!=0), "Programming error - casting to DataTagged.");
1266 escript::binaryOp(*leftC,*rightC,operation);
1267 } else {
1268 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1269 EsysAssert((rightC!=0), "Programming error - casting to DataConstant.");
1270 escript::binaryOp(*leftC,*rightC,operation);
1271 }
1272 } else if (isConstant()) {
1273 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1274 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1275 EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1276 escript::binaryOp(*leftC,*rightC,operation);
1277 }
1278 }
1279
1280 /**
1281 \brief
1282 Perform the given binary operation with this and right as operands.
1283 Right is a boost::python object.
1284 */
1285 template <class BinaryFunction>
1286 inline
1287 void
1288 Data::binaryOp(const boost::python::object& right,
1289 BinaryFunction operation)
1290 {
1291 DataArray temp(right);
1292 //
1293 // if this has a rank of zero promote it to the rank of the RHS.
1294 if (getPointDataView().getRank()==0 && temp.getView().getRank()!=0) {
1295 reshapeDataPoint(temp.getView().getShape());
1296 }
1297 //
1298 // Always allow scalar values for the RHS but check other shapes
1299 if (temp.getView().getRank()!=0) {
1300 if (!getPointDataView().checkShape(temp.getView().getShape())) {
1301 throw DataException(getPointDataView().createShapeErrorMessage(
1302 "Error - RHS shape doesn't match LHS shape.",temp.getView().getShape()));
1303 }
1304 }
1305 if (isExpanded()) {
1306 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1307 EsysAssert((leftC!=0),"Programming error - casting to DataExpanded.");
1308 escript::binaryOp(*leftC,temp.getView(),operation);
1309 } else if (isTagged()) {
1310 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1311 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1312 escript::binaryOp(*leftC,temp.getView(),operation);
1313 } else if (isConstant()) {
1314 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1315 EsysAssert((leftC!=0),"Programming error - casting to DataConstant.");
1316 escript::binaryOp(*leftC,temp.getView(),operation);
1317 }
1318 }
1319
1320 /**
1321 \brief
1322 Perform the given unary operation on other and return the result.
1323 Given operation is performed on each element of each data point, thus
1324 argument object is a rank n Data object, and returned object is a rank n
1325 Data object.
1326 Calls Data::unaryOp.
1327 */
1328 template <class UnaryFunction>
1329 inline
1330 Data
1331 unaryOp(const Data& other,
1332 UnaryFunction operation)
1333 {
1334 Data result;
1335 result.copy(other);
1336 result.unaryOp(operation);
1337 return result;
1338 }
1339
1340 /**
1341 \brief
1342 Perform the given unary operation on this.
1343 Given operation is performed on each element of each data point.
1344 Calls escript::unaryOp.
1345 */
1346 template <class UnaryFunction>
1347 inline
1348 void
1349 Data::unaryOp(UnaryFunction operation)
1350 {
1351 if (isExpanded()) {
1352 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1353 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1354 escript::unaryOp(*leftC,operation);
1355 } else if (isTagged()) {
1356 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1357 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1358 escript::unaryOp(*leftC,operation);
1359 } else if (isConstant()) {
1360 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1361 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1362 escript::unaryOp(*leftC,operation);
1363 }
1364 }
1365
1366 /**
1367 \brief
1368 Perform the given Data object reduction algorithm on this and return the result.
1369 Given operation combines each element of each data point, thus argument
1370 object (*this) is a rank n Data object, and returned object is a scalar.
1371 Calls escript::algorithm.
1372 */
1373 template <class BinaryFunction>
1374 inline
1375 double
1376 Data::algorithm(BinaryFunction operation, double initial_value) const
1377 {
1378 if (isExpanded()) {
1379 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1380 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1381 return escript::algorithm(*leftC,operation,initial_value);
1382 } else if (isTagged()) {
1383 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1384 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1385 return escript::algorithm(*leftC,operation,initial_value);
1386 } else if (isConstant()) {
1387 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1388 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1389 return escript::algorithm(*leftC,operation,initial_value);
1390 }
1391 return 0;
1392 }
1393
1394 /**
1395 \brief
1396 Perform the given data point reduction algorithm on data and return the result.
1397 Given operation combines each element within each data point into a scalar,
1398 thus argument object is a rank n Data object, and returned object is a
1399 rank 0 Data object.
1400 Calls escript::dp_algorithm.
1401 */
1402 template <class BinaryFunction>
1403 inline
1404 Data
1405 Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1406 {
1407 Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());
1408 if (isExpanded()) {
1409 DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1410 DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1411 EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1412 EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1413 escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1414 } else if (isTagged()) {
1415 DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
1416 DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());
1417 EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1418 EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");
1419 escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1420 } else if (isConstant()) {
1421 DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1422 DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1423 EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1424 EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1425 escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1426 }
1427 return result;
1428 }
1429
1430 }
1431 #endif

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26