/[escript]/trunk/escript/src/Data/Data.h
ViewVC logotype

Contents of /trunk/escript/src/Data/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 149 - (show annotations)
Thu Sep 1 03:31:39 2005 UTC (14 years, 2 months ago) by jgs
Original Path: trunk/esys2/escript/src/Data/Data.h
File MIME type: text/plain
File size: 36857 byte(s)
Merge of development branch dev-02 back to main trunk on 2005-09-01

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26