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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26