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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 106 - (show annotations)
Thu Dec 23 07:20:12 2004 UTC (14 years, 4 months ago) by jgs
Original Path: trunk/esys2/escript/src/Data/Data.h
File MIME type: text/plain
File size: 32468 byte(s)
*** empty log message ***

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26