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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 97 - (show annotations)
Tue Dec 14 05:39:33 2004 UTC (14 years, 8 months ago) by jgs
File MIME type: text/plain
File size: 32276 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 */
647 Data
648 transpose(int axis) const;
649
650 /**
651 \trace
652 Calculate the trace of each data point of this Data object.
653 sum(A[i,i,i,i])
654 */
655 Data
656 trace() const;
657
658 /**
659 \exp
660 Return the exponential function of each data point of this Data object.
661 */
662 Data
663 exp() const;
664
665 /**
666 \sqrt
667 Return the square root of each data point of this Data object.
668 */
669 Data
670 sqrt() const;
671
672 /**
673 \brief
674 Return the given power of each data point of this Data object.
675 */
676 Data
677 powD(const Data& right) const;
678
679 Data
680 powO(const boost::python::object& right) const;
681
682 /**
683 \brief
684 Return the negation of each data point of this Data object.
685 */
686 Data
687 neg() const;
688
689 /**
690 \brief
691 Return the identity of each data point of this Data object.
692 Simply returns this object unmodified.
693 */
694 Data
695 pos() const;
696
697 /**
698 \brief
699 Overloaded operator +=
700 \param right - Input - The right hand side.
701 */
702 Data& operator+=(const Data& right);
703 Data& operator+=(const boost::python::object& right);
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 Returns true if this can be interpolated to functionspace.
732 */
733 bool
734 probeInterpolation(const FunctionSpace& functionspace) const;
735
736 /**
737 Data object slicing methods.
738 */
739
740 /**
741 \brief
742 Returns a slice from this Data object.
743
744 /description
745 Implements the [] get operator in python.
746 Calls getSlice.
747
748 \param key - Input - python slice tuple specifying
749 slice to return.
750 */
751 Data
752 getItem(const boost::python::object& key) const;
753
754 /**
755 \brief
756 Copies slice from value into this Data object.
757
758 \description
759 Implements the [] set operator in python.
760 Calls setSlice.
761
762 \param key - Input - python slice tuple specifying
763 slice to copy from value.
764 \param value - Input - Data object to copy from.
765 */
766 void
767 setItemD(const boost::python::object& key,
768 const Data& value);
769
770 void
771 setItemO(const boost::python::object& key,
772 const boost::python::object& value);
773
774 // These following public methods should be treated as private.
775
776 /**
777 \brief
778 Perform the given unary operation on every element of every data point in
779 this Data object.
780 */
781 template <class UnaryFunction>
782 inline
783 void
784 unaryOp(UnaryFunction operation);
785
786 /**
787 \brief
788 Return a Data object containing the specified slice of
789 this Data object.
790 \param region - Input - Region to copy.
791 */
792 Data
793 getSlice(const DataArrayView::RegionType& region) const;
794
795 /**
796 \brief
797 Copy the specified slice from the given value into this
798 Data object.
799 \param value - Input - Data to copy from.
800 \param region - Input - Region to copy.
801 */
802 void
803 setSlice(const Data& value,
804 const DataArrayView::RegionType& region);
805
806 protected:
807
808 private:
809
810 /**
811 \brief
812 Check *this and the right operand are compatible. Throws
813 an exception if they aren't.
814 \param right - Input - The right hand side.
815 */
816 inline
817 void
818 operandCheck(const Data& right) const
819 {
820 return m_data->operandCheck(*(right.m_data.get()));
821 }
822
823 /**
824 \brief
825 Perform the specified reduction algorithm on every element of every data point in
826 this Data object and return the single double value result.
827 */
828 template <class UnaryFunction>
829 inline
830 double
831 algorithm(UnaryFunction operation) const;
832
833 /**
834 \brief
835 Perform the given binary operation on all of the data's elements.
836 The underlying type of the right hand side (right) determines the final
837 type of *this after the operation. For example if the right hand side
838 is expanded *this will be expanded if necessary.
839 RHS is a Data object.
840 */
841 template <class BinaryFunction>
842 inline
843 void
844 binaryOp(const Data& right,
845 BinaryFunction operation);
846
847 /**
848 \brief
849 Perform the given binary operation on all of the data's elements.
850 RHS is a boost::python object.
851 */
852 template <class BinaryFunction>
853 inline
854 void
855 binaryOp(const boost::python::object& right,
856 BinaryFunction operation);
857
858 /**
859 \brief
860 Convert the data type of the RHS to match this.
861 \param right - Input - data type to match.
862 */
863 void
864 typeMatchLeft(Data& right) const;
865
866 /**
867 \brief
868 Convert the data type of this to match the RHS.
869 \param right - Input - data type to match.
870 */
871 void
872 typeMatchRight(const Data& right);
873
874 /**
875 \brief
876 Construct a Data object of the appropriate type.
877 */
878 template <class IValueType>
879 void
880 initialise(const IValueType& value,
881 const FunctionSpace& what,
882 bool expanded);
883
884 /**
885 \brief
886 Reshape the data point if the data point is currently rank 0.
887 Will throw an exception if the data points are not rank 0.
888 The original data point value is used for all values of the new
889 data point.
890 */
891 void
892 reshapeDataPoint(const DataArrayView::ShapeType& shape);
893
894 //
895 // pointer to the actual data object
896 boost::shared_ptr<DataAbstract> m_data;
897
898 };
899
900 template <class IValueType>
901 void
902 Data::initialise(const IValueType& value,
903 const FunctionSpace& what,
904 bool expanded)
905 {
906 //
907 // Construct a Data object of the appropriate type.
908 // Construct the object first as there seems to be a bug which causes
909 // undefined behaviour if an exception is thrown during construction
910 // within the shared_ptr constructor.
911 if (expanded) {
912 DataAbstract* temp=new DataExpanded(value,what);
913 boost::shared_ptr<DataAbstract> temp_data(temp);
914 m_data=temp_data;
915 } else {
916 DataAbstract* temp=new DataConstant(value,what);
917 boost::shared_ptr<DataAbstract> temp_data(temp);
918 m_data=temp_data;
919 }
920 }
921
922 /**
923 Binary Data object operators.
924 */
925
926 /**
927 \brief
928 Operator+
929 Takes two Data objects.
930 */
931 Data operator+(const Data& left, const Data& right);
932
933 /**
934 \brief
935 Operator-
936 Takes two Data objects.
937 */
938 Data operator-(const Data& left, const Data& right);
939
940 /**
941 \brief
942 Operator*
943 Takes two Data objects.
944 */
945 Data operator*(const Data& left, const Data& right);
946
947 /**
948 \brief
949 Operator/
950 Takes two Data objects.
951 */
952 Data operator/(const Data& left, const Data& right);
953
954 /**
955 \brief
956 Operator+
957 Takes LHS Data object and RHS python::object.
958 python::object must be convertable to Data type.
959 */
960 Data operator+(const Data& left, const boost::python::object& right);
961
962 /**
963 \brief
964 Operator-
965 Takes LHS Data object and RHS python::object.
966 python::object must be convertable to Data type.
967 */
968 Data operator-(const Data& left, const boost::python::object& right);
969
970 /**
971 \brief
972 Operator*
973 Takes LHS Data object and RHS python::object.
974 python::object must be convertable to Data type.
975 */
976 Data operator*(const Data& left, const boost::python::object& right);
977
978 /**
979 \brief
980 Operator/
981 Takes LHS Data object and RHS python::object.
982 python::object must be convertable to Data type.
983 */
984 Data operator/(const Data& left, const boost::python::object& right);
985
986 /**
987 \brief
988 Operator+
989 Takes LHS python::object and RHS Data object.
990 python::object must be convertable to Data type.
991 */
992 Data operator+(const boost::python::object& left, const Data& right);
993
994 /**
995 \brief
996 Operator-
997 Takes LHS python::object and RHS Data object.
998 python::object must be convertable to Data type.
999 */
1000 Data operator-(const boost::python::object& left, const Data& right);
1001
1002 /**
1003 \brief
1004 Operator*
1005 Takes LHS python::object and RHS Data object.
1006 python::object must be convertable to Data type.
1007 */
1008 Data operator*(const boost::python::object& left, const Data& right);
1009
1010 /**
1011 \brief
1012 Operator/
1013 Takes LHS python::object and RHS Data object.
1014 python::object must be convertable to Data type.
1015 */
1016 Data operator/(const boost::python::object& left, const Data& right);
1017
1018 /**
1019 \brief
1020 Output operator
1021 */
1022 std::ostream& operator<<(std::ostream& o, const Data& data);
1023
1024 /**
1025 \brief
1026 Return true if operands are equivalent, else return false.
1027 NB: this operator does very little at this point, and isn't to
1028 be relied on. Requires further implementation.
1029 */
1030 //bool operator==(const Data& left, const Data& right);
1031
1032 /**
1033 \brief
1034 Perform the given binary operation with this and right as operands.
1035 Right is a Data object.
1036 */
1037 template <class BinaryFunction>
1038 inline
1039 void
1040 Data::binaryOp(const Data& right,
1041 BinaryFunction operation)
1042 {
1043 //
1044 // if this has a rank of zero promote it to the rank of the RHS
1045 if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {
1046 reshapeDataPoint(right.getPointDataView().getShape());
1047 }
1048 //
1049 // initially make the temporary a shallow copy
1050 Data tempRight(right);
1051 if (getFunctionSpace()!=right.getFunctionSpace()) {
1052 if (right.probeInterpolation(getFunctionSpace())) {
1053 //
1054 // an interpolation is required so create a new Data
1055 tempRight=Data(right,this->getFunctionSpace());
1056 } else if (probeInterpolation(right.getFunctionSpace())) {
1057 //
1058 // interpolate onto the RHS function space
1059 Data tempLeft(*this,right.getFunctionSpace());
1060 m_data=tempLeft.m_data;
1061 }
1062 }
1063 operandCheck(tempRight);
1064 //
1065 // ensure this has the right type for the RHS
1066 typeMatchRight(tempRight);
1067 //
1068 // Need to cast to the concrete types so that the correct binaryOp
1069 // is called.
1070 if (isExpanded()) {
1071 //
1072 // Expanded data will be done in parallel, the right hand side can be
1073 // of any data type
1074 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1075 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1076 escript::binaryOp(*leftC,*(tempRight.m_data.get()),operation);
1077 } else if (isTagged()) {
1078 //
1079 // Tagged data is operated on serially, the right hand side can be
1080 // either DataConstant or DataTagged
1081 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1082 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1083 if (right.isTagged()) {
1084 DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get());
1085 EsysAssert((rightC!=0), "Programming error - casting to DataTagged.");
1086 escript::binaryOp(*leftC,*rightC,operation);
1087 } else {
1088 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1089 EsysAssert((rightC!=0), "Programming error - casting to DataConstant.");
1090 escript::binaryOp(*leftC,*rightC,operation);
1091 }
1092 } else if (isConstant()) {
1093 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1094 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1095 EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1096 escript::binaryOp(*leftC,*rightC,operation);
1097 }
1098 }
1099
1100 /**
1101 \brief
1102 Perform the given binary operation with this and right as operands.
1103 Right is a boost::python object.
1104 */
1105 template <class BinaryFunction>
1106 inline
1107 void
1108 Data::binaryOp(const boost::python::object& right,
1109 BinaryFunction operation)
1110 {
1111 DataArray temp(right);
1112 //
1113 // if this has a rank of zero promote it to the rank of the RHS.
1114 if (getPointDataView().getRank()==0 && temp.getView().getRank()!=0) {
1115 reshapeDataPoint(temp.getView().getShape());
1116 }
1117 //
1118 // Always allow scalar values for the RHS but check other shapes
1119 if (temp.getView().getRank()!=0) {
1120 if (!getPointDataView().checkShape(temp.getView().getShape())) {
1121 throw DataException(getPointDataView().createShapeErrorMessage(
1122 "Error - RHS shape doesn't match LHS shape.",temp.getView().getShape()));
1123 }
1124 }
1125 if (isExpanded()) {
1126 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1127 EsysAssert((leftC!=0),"Programming error - casting to DataExpanded.");
1128 escript::binaryOp(*leftC,temp.getView(),operation);
1129 } else if (isTagged()) {
1130 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1131 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1132 escript::binaryOp(*leftC,temp.getView(),operation);
1133 } else if (isConstant()) {
1134 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1135 EsysAssert((leftC!=0),"Programming error - casting to DataConstant.");
1136 escript::binaryOp(*leftC,temp.getView(),operation);
1137 }
1138 }
1139
1140 /**
1141 \brief
1142 Perform the given unary operation on other and return the result.
1143 Given operation is performed on each element of each data point, thus
1144 argument object is a rank n Data object, and returned object is a rank n
1145 Data object.
1146 Calls Data::unaryOp.
1147 */
1148 template <class UnaryFunction>
1149 inline
1150 Data
1151 unaryOp(const Data& other,
1152 UnaryFunction operation)
1153 {
1154 Data result;
1155 result.copy(other);
1156 result.unaryOp(operation);
1157 return result;
1158 }
1159
1160 /**
1161 \brief
1162 Perform the given unary operation on this.
1163 Given operation is performed on each element of each data point.
1164 Calls escript::unaryOp.
1165 */
1166 template <class UnaryFunction>
1167 inline
1168 void
1169 Data::unaryOp(UnaryFunction operation)
1170 {
1171 if (isExpanded()) {
1172 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1173 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1174 escript::unaryOp(*leftC,operation);
1175 } else if (isTagged()) {
1176 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1177 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1178 escript::unaryOp(*leftC,operation);
1179 } else if (isConstant()) {
1180 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1181 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1182 escript::unaryOp(*leftC,operation);
1183 }
1184 }
1185
1186 /**
1187 \brief
1188 Perform the given Data object reduction algorithm on this and return the result.
1189 Given operation combines each element of each data point, thus argument
1190 object (*this) is a rank n Data object, and returned object is a scalar.
1191 Calls escript::algorithm.
1192 */
1193 template <class UnaryFunction>
1194 inline
1195 double
1196 Data::algorithm(UnaryFunction operation) const
1197 {
1198 if (isExpanded()) {
1199 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1200 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1201 return escript::algorithm(*leftC,operation);
1202 } else if (isTagged()) {
1203 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1204 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1205 return escript::algorithm(*leftC,operation);
1206 } else if (isConstant()) {
1207 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1208 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1209 return escript::algorithm(*leftC,operation);
1210 }
1211 return 0;
1212 }
1213
1214 /**
1215 \brief
1216 Perform the given data point reduction algorithm on data and return the result.
1217 Given operation combines each element within each data point into a scalar,
1218 thus argument object is a rank n Data object, and returned object is a
1219 rank 0 Data object.
1220 Calls escript::dp_algorithm.
1221 */
1222 template <class UnaryFunction>
1223 inline
1224 Data
1225 dp_algorithm(const Data& data,
1226 UnaryFunction operation)
1227 {
1228 Data result(0,DataArrayView::ShapeType(),data.getFunctionSpace(),data.isExpanded());
1229 if (data.isExpanded()) {
1230 DataExpanded* dataE=dynamic_cast<DataExpanded*>(data.m_data.get());
1231 DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1232 EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1233 EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1234 escript::dp_algorithm(*dataE,*resultE,operation);
1235 } else if (data.isTagged()) {
1236 DataTagged* dataT=dynamic_cast<DataTagged*>(data.m_data.get());
1237 DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());
1238 EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1239 EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");
1240 escript::dp_algorithm(*dataT,*resultT,operation);
1241 } else if (data.isConstant()) {
1242 DataConstant* dataC=dynamic_cast<DataConstant*>(data.m_data.get());
1243 DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1244 EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1245 EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1246 escript::dp_algorithm(*dataC,*resultC,operation);
1247 }
1248 return result;
1249 }
1250
1251 }
1252 #endif

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26