/[escript]/branches/schroedinger/escript/src/Data.h
ViewVC logotype

Contents of /branches/schroedinger/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1865 - (show annotations)
Thu Oct 9 03:53:57 2008 UTC (11 years, 1 month ago) by jfenwick
File MIME type: text/plain
File size: 88667 byte(s)
Branch commit
Added some missing files.

In python can ask a data object if it-  isReady(), isConstant(), 
isLazy().



1
2 /*******************************************************
3 *
4 * Copyright (c) 2003-2008 by University of Queensland
5 * Earth Systems Science Computational Center (ESSCC)
6 * http://www.uq.edu.au/esscc
7 *
8 * Primary Business: Queensland, Australia
9 * Licensed under the Open Software License version 3.0
10 * http://www.opensource.org/licenses/osl-3.0.php
11 *
12 *******************************************************/
13
14
15 /** \file Data.h */
16
17 #ifndef DATA_H
18 #define DATA_H
19 #include "system_dep.h"
20
21 #include "DataAbstract.h"
22 #include "DataAlgorithm.h"
23 #include "FunctionSpace.h"
24 #include "BinaryOp.h"
25 #include "UnaryOp.h"
26 #include "DataException.h"
27 #include "DataTypes.h"
28
29 extern "C" {
30 #include "DataC.h"
31 /* #include "paso/Paso.h" doesn't belong in this file...causes trouble for BruceFactory.cpp */
32 }
33
34 #include "esysmpi.h"
35 #include <string>
36 #include <algorithm>
37 #include <sstream>
38
39
40 #include <boost/shared_ptr.hpp>
41 #include <boost/python/object.hpp>
42 #include <boost/python/tuple.hpp>
43 #include <boost/python/numeric.hpp>
44
45 namespace escript {
46
47 //
48 // Forward declaration for various implementations of Data.
49 class DataConstant;
50 class DataTagged;
51 class DataExpanded;
52
53 /**
54 \brief
55 Data represents a collection of datapoints.
56
57 Description:
58 Internally, the datapoints are actually stored by a DataAbstract object.
59 The specific instance of DataAbstract used may vary over the lifetime
60 of the Data object.
61 Some methods on this class return references (eg getShape()).
62 These references should not be used after an operation which changes the underlying DataAbstract object.
63 Doing so will lead to invalid memory access.
64 This should not affect any methods exposed via boost::python.
65 */
66 class Data {
67
68 public:
69
70 // These typedefs allow function names to be cast to pointers
71 // to functions of the appropriate type when calling unaryOp etc.
72 typedef double (*UnaryDFunPtr)(double);
73 typedef double (*BinaryDFunPtr)(double,double);
74
75
76 /**
77 Constructors.
78 */
79
80 /**
81 \brief
82 Default constructor.
83 Creates a DataEmpty object.
84 */
85 ESCRIPT_DLL_API
86 Data();
87
88 /**
89 \brief
90 Copy constructor.
91 WARNING: Only performs a shallow copy.
92 */
93 ESCRIPT_DLL_API
94 Data(const Data& inData);
95
96 /**
97 \brief
98 Constructor from another Data object. If "what" is different from the
99 function space of inData the inData are tried to be interpolated to what,
100 otherwise a shallow copy of inData is returned.
101 */
102 ESCRIPT_DLL_API
103 Data(const Data& inData,
104 const FunctionSpace& what);
105
106 /**
107 \brief Copy Data from an existing vector
108 */
109
110 ESCRIPT_DLL_API
111 Data(const DataTypes::ValueType& value,
112 const DataTypes::ShapeType& shape,
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 ESCRIPT_DLL_API
128 Data(double value,
129 const DataTypes::ShapeType& dataPointShape=DataTypes::ShapeType(),
130 const FunctionSpace& what=FunctionSpace(),
131 bool expanded=false);
132
133 /**
134 \brief
135 Constructor which performs a deep copy of a region from another Data object.
136
137 \param inData - Input - Input Data object.
138 \param region - Input - Region to copy.
139 */
140 ESCRIPT_DLL_API
141 Data(const Data& inData,
142 const DataTypes::RegionType& region);
143
144 /**
145 \brief
146 Constructor which copies data from a python numarray.
147
148 \param value - Input - Data value for a single point.
149 \param what - Input - A description of what this data represents.
150 \param expanded - Input - Flag, if true fill the entire container with
151 the value. Otherwise a more efficient storage
152 mechanism will be used.
153 */
154 ESCRIPT_DLL_API
155 Data(const boost::python::numeric::array& value,
156 const FunctionSpace& what=FunctionSpace(),
157 bool expanded=false);
158
159 /**
160 \brief
161 Constructor which copies data from any object that can be converted into
162 a python numarray.
163
164 \param value - Input - Input data.
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 ESCRIPT_DLL_API
171 Data(const boost::python::object& value,
172 const FunctionSpace& what=FunctionSpace(),
173 bool expanded=false);
174
175 /**
176 \brief
177 Constructor which creates a DataConstant.
178 Copies data from any object that can be converted
179 into a numarray. All other parameters are copied from other.
180
181 \param value - Input - Input data.
182 \param other - Input - contains all other parameters.
183 */
184 ESCRIPT_DLL_API
185 Data(const boost::python::object& value,
186 const Data& other);
187
188 /**
189 \brief
190 Constructor which creates a DataConstant of "shape" with constant value.
191 */
192 ESCRIPT_DLL_API
193 Data(double value,
194 const boost::python::tuple& shape=boost::python::make_tuple(),
195 const FunctionSpace& what=FunctionSpace(),
196 bool expanded=false);
197
198
199
200 /**
201 \brief Create a Data using an existing DataAbstract. Warning: The new object assumes ownership of the pointer!
202 Once you have passed the pointer, do not delete it.
203 */
204 ESCRIPT_DLL_API
205 Data(DataAbstract* underlyingdata);
206
207
208 /**
209 \brief
210 Destructor
211 */
212 ESCRIPT_DLL_API
213 ~Data();
214
215 /**
216 \brief Make this object a deep copy of "other".
217 */
218 ESCRIPT_DLL_API
219 void
220 copy(const Data& other);
221
222 /**
223 \brief Return a pointer to a deep copy of this object.
224 */
225 ESCRIPT_DLL_API
226 Data*
227 copySelf();
228
229
230 /**
231 \brief produce a delayed evaluation version of this Data.
232 */
233 ESCRIPT_DLL_API
234 Data
235 delay();
236
237 /**
238 Member access methods.
239 */
240
241 /**
242 \brief
243 switches on update protection
244
245 */
246 ESCRIPT_DLL_API
247 void
248 setProtection();
249
250 /**
251 \brief
252 Returns trueif the data object is protected against update
253
254 */
255 ESCRIPT_DLL_API
256 bool
257 isProtected() const;
258
259 /**
260 \brief
261 Return the values of a data point on this process
262 */
263 ESCRIPT_DLL_API
264 const boost::python::numeric::array
265 getValueOfDataPoint(int dataPointNo);
266
267 /**
268 \brief
269 sets the values of a data-point from a python object on this process
270 */
271 ESCRIPT_DLL_API
272 void
273 setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
274
275 /**
276 \brief
277 sets the values of a data-point from a numarray object on this process
278 */
279 ESCRIPT_DLL_API
280 void
281 setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
282
283 /**
284 \brief
285 sets the values of a data-point on this process
286 */
287 ESCRIPT_DLL_API
288 void
289 setValueOfDataPoint(int dataPointNo, const double);
290
291 /**
292 \brief
293 Return the value of the specified data-point across all processors
294 */
295 ESCRIPT_DLL_API
296 const boost::python::numeric::array
297 getValueOfGlobalDataPoint(int procNo, int dataPointNo);
298
299 /**
300 \brief
301 Return the tag number associated with the given data-point.
302
303 */
304 ESCRIPT_DLL_API
305 int
306 getTagNumber(int dpno);
307
308 /**
309 \brief
310 Return the C wrapper for the Data object.
311 */
312 ESCRIPT_DLL_API
313 escriptDataC
314 getDataC();
315
316
317
318
319
320
321 // REMOVE ME
322 // ESCRIPT_DLL_API
323 // void
324 // CompareDebug(const Data& rd);
325
326
327 /**
328 \brief
329 Return the C wrapper for the Data object - const version.
330 */
331 ESCRIPT_DLL_API
332 escriptDataC
333 getDataC() const;
334
335 /**
336 \brief
337 Write the data as a string. For large amounts of data, a summary is printed.
338 */
339 ESCRIPT_DLL_API
340 std::string
341 toString() const;
342
343 /**
344 \brief
345 Whatever the current Data type make this into a DataExpanded.
346 */
347 ESCRIPT_DLL_API
348 void
349 expand();
350
351 /**
352 \brief
353 If possible convert this Data to DataTagged. This will only allow
354 Constant data to be converted to tagged. An attempt to convert
355 Expanded data to tagged will throw an exception.
356 ==>*
357 */
358 ESCRIPT_DLL_API
359 void
360 tag();
361
362 /**
363 \brief
364 Return true if this Data is expanded.
365 */
366 ESCRIPT_DLL_API
367 bool
368 isExpanded() const;
369
370 /**
371 \brief
372 Return true if this Data is tagged.
373 */
374 ESCRIPT_DLL_API
375 bool
376 isTagged() const;
377
378 /**
379 \brief
380 Return true if this Data is constant.
381 */
382 ESCRIPT_DLL_API
383 bool
384 isConstant() const;
385
386 /**
387 \brief Return true if this Data is lazy.
388 */
389 ESCRIPT_DLL_API
390 bool
391 isLazy() const;
392
393 /**
394 \brief Return true if this data is ready.
395 */
396 ESCRIPT_DLL_API
397 bool
398 isReady() const;
399
400 /**
401 \brief
402 Return true if this Data holds an instance of DataEmpty. This is _not_ the same as asking if the object
403 contains datapoints.
404 */
405 ESCRIPT_DLL_API
406 bool
407 isEmpty() const;
408
409 /**
410 \brief
411 Return the function space.
412 */
413 ESCRIPT_DLL_API
414 inline
415 const FunctionSpace&
416 getFunctionSpace() const
417 {
418 return m_data->getFunctionSpace();
419 }
420
421 /**
422 \brief
423 Return a copy of the function space.
424 */
425 ESCRIPT_DLL_API
426 const FunctionSpace
427 getCopyOfFunctionSpace() const;
428
429 /**
430 \brief
431 Return the domain.
432 */
433 ESCRIPT_DLL_API
434 inline
435 // const AbstractDomain&
436 const_Domain_ptr
437 getDomain() const
438 {
439 return getFunctionSpace().getDomain();
440 }
441
442
443 /**
444 \brief
445 Return the domain.
446 TODO: For internal use only. This should be removed.
447 */
448 ESCRIPT_DLL_API
449 inline
450 // const AbstractDomain&
451 Domain_ptr
452 getDomainPython() const
453 {
454 return getFunctionSpace().getDomainPython();
455 }
456
457 /**
458 \brief
459 Return a copy of the domain.
460 */
461 ESCRIPT_DLL_API
462 const AbstractDomain
463 getCopyOfDomain() const;
464
465 /**
466 \brief
467 Return the rank of the point data.
468 */
469 ESCRIPT_DLL_API
470 inline
471 int
472 getDataPointRank() const
473 {
474 // return m_data->getPointDataView().getRank();
475 return m_data->getRank();
476 }
477
478 /**
479 \brief
480 Return the number of data points
481 */
482 ESCRIPT_DLL_API
483 inline
484 int
485 getNumDataPoints() const
486 {
487 return getNumSamples() * getNumDataPointsPerSample();
488 }
489 /**
490 \brief
491 Return the number of samples.
492 */
493 ESCRIPT_DLL_API
494 inline
495 int
496 getNumSamples() const
497 {
498 return m_data->getNumSamples();
499 }
500
501 /**
502 \brief
503 Return the number of data points per sample.
504 */
505 ESCRIPT_DLL_API
506 inline
507 int
508 getNumDataPointsPerSample() const
509 {
510 return m_data->getNumDPPSample();
511 }
512
513
514 /**
515 \brief
516 Return the number of values in the shape for this object.
517 */
518 ESCRIPT_DLL_API
519 int
520 getNoValues() const
521 {
522 return m_data->getNoValues();
523 }
524
525
526 /**
527 \brief
528 dumps the object into a netCDF file
529 */
530 ESCRIPT_DLL_API
531 void
532 dump(const std::string fileName) const;
533
534 /**
535 \brief
536 Return the sample data for the given sample no. This is not the
537 preferred interface but is provided for use by C code.
538 \param sampleNo - Input - the given sample no.
539 */
540 ESCRIPT_DLL_API
541 inline
542 DataAbstract::ValueType::value_type*
543 getSampleData(DataAbstract::ValueType::size_type sampleNo);
544
545 /**
546 \brief
547 Return the sample data for the given tag. If an attempt is made to
548 access data that isn't tagged an exception will be thrown.
549 \param tag - Input - the tag key.
550 */
551 ESCRIPT_DLL_API
552 inline
553 DataAbstract::ValueType::value_type*
554 getSampleDataByTag(int tag)
555 {
556 return m_data->getSampleDataByTag(tag);
557 }
558
559 /**
560 \brief
561 Return a view into the data for the data point specified.
562 NOTE: Construction of the DataArrayView is a relatively expensive
563 operation.
564 \param sampleNo - Input -
565 \param dataPointNo - Input -
566 */
567 ESCRIPT_DLL_API
568 DataTypes::ValueType::const_reference
569 getDataPoint(int sampleNo, int dataPointNo) const;
570
571
572 ESCRIPT_DLL_API
573 DataTypes::ValueType::reference
574 getDataPoint(int sampleNo, int dataPointNo);
575
576
577
578 /**
579 \brief
580 Return the offset for the given sample and point within the sample
581 */
582 ESCRIPT_DLL_API
583 inline
584 DataTypes::ValueType::size_type
585 getDataOffset(int sampleNo,
586 int dataPointNo)
587 {
588 return m_data->getPointOffset(sampleNo,dataPointNo);
589 }
590
591 /**
592 \brief
593 Return a reference to the data point shape.
594 */
595 ESCRIPT_DLL_API
596 inline
597 const DataTypes::ShapeType&
598 getDataPointShape() const
599 {
600 return m_data->getShape();
601 }
602
603 /**
604 \brief
605 Return the data point shape as a tuple of integers.
606 */
607 ESCRIPT_DLL_API
608 const boost::python::tuple
609 getShapeTuple() const;
610
611 /**
612 \brief
613 Return the size of the data point. It is the product of the
614 data point shape dimensions.
615 */
616 ESCRIPT_DLL_API
617 int
618 getDataPointSize() const;
619
620 /**
621 \brief
622 Return the number of doubles stored for this Data.
623 */
624 ESCRIPT_DLL_API
625 DataTypes::ValueType::size_type
626 getLength() const;
627
628
629
630 /**
631 \brief
632 Assign the given value to the tag assocciated with name. Implicitly converts this
633 object to type DataTagged. Throws an exception if this object
634 cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
635 \param tagKey - Input - Integer key.
636 \param value - Input - Value to associate with given key.
637 ==>*
638 */
639 ESCRIPT_DLL_API
640 void
641 setTaggedValueByName(std::string name,
642 const boost::python::object& value);
643
644 /**
645 \brief
646 Assign the given value to the tag. Implicitly converts this
647 object to type DataTagged if it is constant.
648
649 \param tagKey - Input - Integer key.
650 \param value - Input - Value to associate with given key.
651 ==>*
652 */
653 ESCRIPT_DLL_API
654 void
655 setTaggedValue(int tagKey,
656 const boost::python::object& value);
657
658 /**
659 \brief
660 Assign the given value to the tag. Implicitly converts this
661 object to type DataTagged if it is constant.
662
663 \param tagKey - Input - Integer key.
664 \param pointshape - Input - The shape of the value parameter
665 \param value - Input - Value to associate with given key.
666 \param dataOffset - Input - Offset of the begining of the point within the value parameter
667 */
668 ESCRIPT_DLL_API
669 void
670 setTaggedValueFromCPP(int tagKey,
671 const DataTypes::ShapeType& pointshape,
672 const DataTypes::ValueType& value,
673 int dataOffset=0);
674
675
676
677 /**
678 \brief
679 Copy other Data object into this Data object where mask is positive.
680 */
681 ESCRIPT_DLL_API
682 void
683 copyWithMask(const Data& other,
684 const Data& mask);
685
686 /**
687 Data object operation methods and operators.
688 */
689
690 /**
691 \brief
692 set all values to zero
693 *
694 */
695 ESCRIPT_DLL_API
696 void
697 setToZero();
698
699 /**
700 \brief
701 Interpolates this onto the given functionspace and returns
702 the result as a Data object.
703 *
704 */
705 ESCRIPT_DLL_API
706 Data
707 interpolate(const FunctionSpace& functionspace) const;
708 /**
709 \brief
710 Calculates the gradient of the data at the data points of functionspace.
711 If functionspace is not present the function space of Function(getDomain()) is used.
712 *
713 */
714 ESCRIPT_DLL_API
715 Data
716 gradOn(const FunctionSpace& functionspace) const;
717
718 ESCRIPT_DLL_API
719 Data
720 grad() const;
721
722 /**
723 \brief
724 Calculate the integral over the function space domain.
725 *
726 */
727 ESCRIPT_DLL_API
728 boost::python::numeric::array
729 integrate() const;
730
731 /**
732 \brief
733 Returns 1./ Data object
734 *
735 */
736 ESCRIPT_DLL_API
737 Data
738 oneOver() const;
739 /**
740 \brief
741 Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.
742 *
743 */
744 ESCRIPT_DLL_API
745 Data
746 wherePositive() const;
747
748 /**
749 \brief
750 Return a Data with a 1 for -ive values and a 0 for +ive or 0 values.
751 *
752 */
753 ESCRIPT_DLL_API
754 Data
755 whereNegative() const;
756
757 /**
758 \brief
759 Return a Data with a 1 for +ive or 0 values and a 0 for -ive values.
760 *
761 */
762 ESCRIPT_DLL_API
763 Data
764 whereNonNegative() const;
765
766 /**
767 \brief
768 Return a Data with a 1 for -ive or 0 values and a 0 for +ive values.
769 *
770 */
771 ESCRIPT_DLL_API
772 Data
773 whereNonPositive() const;
774
775 /**
776 \brief
777 Return a Data with a 1 for 0 values and a 0 for +ive or -ive values.
778 *
779 */
780 ESCRIPT_DLL_API
781 Data
782 whereZero(double tol=0.0) const;
783
784 /**
785 \brief
786 Return a Data with a 0 for 0 values and a 1 for +ive or -ive values.
787 *
788 */
789 ESCRIPT_DLL_API
790 Data
791 whereNonZero(double tol=0.0) const;
792
793 /**
794 \brief
795 Return the maximum absolute value of this Data object.
796 *
797 */
798 ESCRIPT_DLL_API
799 double
800 Lsup() const;
801
802 /**
803 \brief
804 Return the maximum value of this Data object.
805 *
806 */
807 ESCRIPT_DLL_API
808 double
809 sup() const;
810
811 /**
812 \brief
813 Return the minimum value of this Data object.
814 *
815 */
816 ESCRIPT_DLL_API
817 double
818 inf() const;
819
820 /**
821 \brief
822 Return the absolute value of each data point of this Data object.
823 *
824 */
825 ESCRIPT_DLL_API
826 Data
827 abs() const;
828
829 /**
830 \brief
831 Return the maximum value of each data point of this Data object.
832 *
833 */
834 ESCRIPT_DLL_API
835 Data
836 maxval() const;
837
838 /**
839 \brief
840 Return the minimum value of each data point of this Data object.
841 *
842 */
843 ESCRIPT_DLL_API
844 Data
845 minval() const;
846
847 /**
848 \brief
849 Return the (sample number, data-point number) of the data point with
850 the minimum value in this Data object.
851 */
852 ESCRIPT_DLL_API
853 const boost::python::tuple
854 minGlobalDataPoint() const;
855
856 ESCRIPT_DLL_API
857 void
858 calc_minGlobalDataPoint(int& ProcNo, int& DataPointNo) const;
859 /**
860 \brief
861 Return the sign of each data point of this Data object.
862 -1 for negative values, zero for zero values, 1 for positive values.
863 *
864 */
865 ESCRIPT_DLL_API
866 Data
867 sign() const;
868
869 /**
870 \brief
871 Return the symmetric part of a matrix which is half the matrix plus its transpose.
872 *
873 */
874 ESCRIPT_DLL_API
875 Data
876 symmetric() const;
877
878 /**
879 \brief
880 Return the nonsymmetric part of a matrix which is half the matrix minus its transpose.
881 *
882 */
883 ESCRIPT_DLL_API
884 Data
885 nonsymmetric() const;
886
887 /**
888 \brief
889 Return the trace of a matrix
890 *
891 */
892 ESCRIPT_DLL_API
893 Data
894 trace(int axis_offset) const;
895
896 /**
897 \brief
898 Transpose each data point of this Data object around the given axis.
899 *
900 */
901 ESCRIPT_DLL_API
902 Data
903 transpose(int axis_offset) const;
904
905 /**
906 \brief
907 Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.
908 Currently this function is restricted to rank 2, square shape, and dimension 3.
909 *
910 */
911 ESCRIPT_DLL_API
912 Data
913 eigenvalues() const;
914
915 /**
916 \brief
917 Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.
918 the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than
919 tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the
920 first non-zero entry is positive.
921 Currently this function is restricted to rank 2, square shape, and dimension 3
922 *
923 */
924 ESCRIPT_DLL_API
925 const boost::python::tuple
926 eigenvalues_and_eigenvectors(const double tol=1.e-12) const;
927
928 /**
929 \brief
930 swaps the components axis0 and axis1
931 *
932 */
933 ESCRIPT_DLL_API
934 Data
935 swapaxes(const int axis0, const int axis1) const;
936
937 /**
938 \brief
939 Return the error function erf of each data point of this Data object.
940 *
941 */
942 ESCRIPT_DLL_API
943 Data
944 erf() const;
945
946 /**
947 \brief
948 Return the sin of each data point of this Data object.
949 *
950 */
951 ESCRIPT_DLL_API
952 Data
953 sin() const;
954
955 /**
956 \brief
957 Return the cos of each data point of this Data object.
958 *
959 */
960 ESCRIPT_DLL_API
961 Data
962 cos() const;
963
964 /**
965 \brief
966 Return the tan of each data point of this Data object.
967 *
968 */
969 ESCRIPT_DLL_API
970 Data
971 tan() const;
972
973 /**
974 \brief
975 Return the asin of each data point of this Data object.
976 *
977 */
978 ESCRIPT_DLL_API
979 Data
980 asin() const;
981
982 /**
983 \brief
984 Return the acos of each data point of this Data object.
985 *
986 */
987 ESCRIPT_DLL_API
988 Data
989 acos() const;
990
991 /**
992 \brief
993 Return the atan of each data point of this Data object.
994 *
995 */
996 ESCRIPT_DLL_API
997 Data
998 atan() const;
999
1000 /**
1001 \brief
1002 Return the sinh of each data point of this Data object.
1003 *
1004 */
1005 ESCRIPT_DLL_API
1006 Data
1007 sinh() const;
1008
1009 /**
1010 \brief
1011 Return the cosh of each data point of this Data object.
1012 *
1013 */
1014 ESCRIPT_DLL_API
1015 Data
1016 cosh() const;
1017
1018 /**
1019 \brief
1020 Return the tanh of each data point of this Data object.
1021 *
1022 */
1023 ESCRIPT_DLL_API
1024 Data
1025 tanh() const;
1026
1027 /**
1028 \brief
1029 Return the asinh of each data point of this Data object.
1030 *
1031 */
1032 ESCRIPT_DLL_API
1033 Data
1034 asinh() const;
1035
1036 /**
1037 \brief
1038 Return the acosh of each data point of this Data object.
1039 *
1040 */
1041 ESCRIPT_DLL_API
1042 Data
1043 acosh() const;
1044
1045 /**
1046 \brief
1047 Return the atanh of each data point of this Data object.
1048 *
1049 */
1050 ESCRIPT_DLL_API
1051 Data
1052 atanh() const;
1053
1054 /**
1055 \brief
1056 Return the log to base 10 of each data point of this Data object.
1057 *
1058 */
1059 ESCRIPT_DLL_API
1060 Data
1061 log10() const;
1062
1063 /**
1064 \brief
1065 Return the natural log of each data point of this Data object.
1066 *
1067 */
1068 ESCRIPT_DLL_API
1069 Data
1070 log() const;
1071
1072 /**
1073 \brief
1074 Return the exponential function of each data point of this Data object.
1075 *
1076 */
1077 ESCRIPT_DLL_API
1078 Data
1079 exp() const;
1080
1081 /**
1082 \brief
1083 Return the square root of each data point of this Data object.
1084 *
1085 */
1086 ESCRIPT_DLL_API
1087 Data
1088 sqrt() const;
1089
1090 /**
1091 \brief
1092 Return the negation of each data point of this Data object.
1093 *
1094 */
1095 ESCRIPT_DLL_API
1096 Data
1097 neg() const;
1098
1099 /**
1100 \brief
1101 Return the identity of each data point of this Data object.
1102 Simply returns this object unmodified.
1103 *
1104 */
1105 ESCRIPT_DLL_API
1106 Data
1107 pos() const;
1108
1109 /**
1110 \brief
1111 Return the given power of each data point of this Data object.
1112
1113 \param right Input - the power to raise the object to.
1114 *
1115 */
1116 ESCRIPT_DLL_API
1117 Data
1118 powD(const Data& right) const;
1119
1120 /**
1121 \brief
1122 Return the given power of each data point of this boost python object.
1123
1124 \param right Input - the power to raise the object to.
1125 *
1126 */
1127 ESCRIPT_DLL_API
1128 Data
1129 powO(const boost::python::object& right) const;
1130
1131 /**
1132 \brief
1133 Return the given power of each data point of this boost python object.
1134
1135 \param left Input - the bases
1136 *
1137 */
1138
1139 ESCRIPT_DLL_API
1140 Data
1141 rpowO(const boost::python::object& left) const;
1142
1143 /**
1144 \brief
1145 writes the object to a file in the DX file format
1146 */
1147 ESCRIPT_DLL_API
1148 void
1149 saveDX(std::string fileName) const;
1150
1151 /**
1152 \brief
1153 writes the object to a file in the VTK file format
1154 */
1155 ESCRIPT_DLL_API
1156 void
1157 saveVTK(std::string fileName) const;
1158
1159 /**
1160 \brief
1161 Overloaded operator +=
1162 \param right - Input - The right hand side.
1163 *
1164 */
1165 ESCRIPT_DLL_API
1166 Data& operator+=(const Data& right);
1167 ESCRIPT_DLL_API
1168 Data& operator+=(const boost::python::object& right);
1169
1170 ESCRIPT_DLL_API
1171 Data& operator=(const Data& other);
1172
1173 /**
1174 \brief
1175 Overloaded operator -=
1176 \param right - Input - The right hand side.
1177 *
1178 */
1179 ESCRIPT_DLL_API
1180 Data& operator-=(const Data& right);
1181 ESCRIPT_DLL_API
1182 Data& operator-=(const boost::python::object& right);
1183
1184 /**
1185 \brief
1186 Overloaded operator *=
1187 \param right - Input - The right hand side.
1188 *
1189 */
1190 ESCRIPT_DLL_API
1191 Data& operator*=(const Data& right);
1192 ESCRIPT_DLL_API
1193 Data& operator*=(const boost::python::object& right);
1194
1195 /**
1196 \brief
1197 Overloaded operator /=
1198 \param right - Input - The right hand side.
1199 *
1200 */
1201 ESCRIPT_DLL_API
1202 Data& operator/=(const Data& right);
1203 ESCRIPT_DLL_API
1204 Data& operator/=(const boost::python::object& right);
1205
1206 /**
1207 \brief
1208 Returns true if this can be interpolated to functionspace.
1209 */
1210 ESCRIPT_DLL_API
1211 bool
1212 probeInterpolation(const FunctionSpace& functionspace) const;
1213
1214 /**
1215 Data object slicing methods.
1216 */
1217
1218 /**
1219 \brief
1220 Returns a slice from this Data object.
1221
1222 /description
1223 Implements the [] get operator in python.
1224 Calls getSlice.
1225
1226 \param key - Input - python slice tuple specifying
1227 slice to return.
1228 */
1229 ESCRIPT_DLL_API
1230 Data
1231 getItem(const boost::python::object& key) const;
1232
1233 /**
1234 \brief
1235 Copies slice from value into this Data object.
1236
1237 Implements the [] set operator in python.
1238 Calls setSlice.
1239
1240 \param key - Input - python slice tuple specifying
1241 slice to copy from value.
1242 \param value - Input - Data object to copy from.
1243 */
1244 ESCRIPT_DLL_API
1245 void
1246 setItemD(const boost::python::object& key,
1247 const Data& value);
1248
1249 ESCRIPT_DLL_API
1250 void
1251 setItemO(const boost::python::object& key,
1252 const boost::python::object& value);
1253
1254 // These following public methods should be treated as private.
1255
1256 /**
1257 \brief
1258 Perform the given unary operation on every element of every data point in
1259 this Data object.
1260 */
1261 template <class UnaryFunction>
1262 ESCRIPT_DLL_API
1263 inline
1264 void
1265 unaryOp2(UnaryFunction operation);
1266
1267 /**
1268 \brief
1269 Return a Data object containing the specified slice of
1270 this Data object.
1271 \param region - Input - Region to copy.
1272 *
1273 */
1274 ESCRIPT_DLL_API
1275 Data
1276 getSlice(const DataTypes::RegionType& region) const;
1277
1278 /**
1279 \brief
1280 Copy the specified slice from the given value into this
1281 Data object.
1282 \param value - Input - Data to copy from.
1283 \param region - Input - Region to copy.
1284 *
1285 */
1286 ESCRIPT_DLL_API
1287 void
1288 setSlice(const Data& value,
1289 const DataTypes::RegionType& region);
1290
1291 /**
1292 \brief
1293 print the data values to stdout. Used for debugging
1294 */
1295 ESCRIPT_DLL_API
1296 void
1297 print(void);
1298
1299 /**
1300 \brief
1301 return the MPI rank number of the local data
1302 MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1303 is returned
1304 */
1305 ESCRIPT_DLL_API
1306 int
1307 get_MPIRank(void) const;
1308
1309 /**
1310 \brief
1311 return the MPI rank number of the local data
1312 MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1313 is returned
1314 */
1315 ESCRIPT_DLL_API
1316 int
1317 get_MPISize(void) const;
1318
1319 /**
1320 \brief
1321 return the MPI rank number of the local data
1322 MPI_COMM_WORLD is assumed and returned.
1323 */
1324 ESCRIPT_DLL_API
1325 MPI_Comm
1326 get_MPIComm(void) const;
1327
1328 /**
1329 \brief
1330 return the object produced by the factory, which is a DataConstant or DataExpanded
1331 TODO Ownership of this object should be explained in doco.
1332 */
1333 ESCRIPT_DLL_API
1334 DataAbstract*
1335 borrowData(void) const;
1336
1337
1338 /**
1339 \brief
1340 Return a pointer to the beginning of the datapoint at the specified offset.
1341 TODO Eventually these should be inlined.
1342 \param i - position(offset) in the underlying datastructure
1343 */
1344 ESCRIPT_DLL_API
1345 DataTypes::ValueType::const_reference
1346 getDataAtOffset(DataTypes::ValueType::size_type i) const;
1347
1348
1349 ESCRIPT_DLL_API
1350 DataTypes::ValueType::reference
1351 getDataAtOffset(DataTypes::ValueType::size_type i);
1352
1353 protected:
1354
1355 private:
1356
1357 /**
1358 \brief
1359 Check *this and the right operand are compatible. Throws
1360 an exception if they aren't.
1361 \param right - Input - The right hand side.
1362 */
1363 inline
1364 void
1365 operandCheck(const Data& right) const
1366 {
1367 return m_data->operandCheck(*(right.m_data.get()));
1368 }
1369
1370 /**
1371 \brief
1372 Perform the specified reduction algorithm on every element of every data point in
1373 this Data object according to the given function and return the single value result.
1374 */
1375 template <class BinaryFunction>
1376 inline
1377 double
1378 algorithm(BinaryFunction operation,
1379 double initial_value) const;
1380
1381 /**
1382 \brief
1383 Reduce each data-point in this Data object using the given operation. Return a Data
1384 object with the same number of data-points, but with each data-point containing only
1385 one value - the result of the reduction operation on the corresponding data-point in
1386 this Data object
1387 */
1388 template <class BinaryFunction>
1389 inline
1390 Data
1391 dp_algorithm(BinaryFunction operation,
1392 double initial_value) const;
1393
1394 /**
1395 \brief
1396 Perform the given binary operation on all of the data's elements.
1397 The underlying type of the right hand side (right) determines the final
1398 type of *this after the operation. For example if the right hand side
1399 is expanded *this will be expanded if necessary.
1400 RHS is a Data object.
1401 */
1402 template <class BinaryFunction>
1403 inline
1404 void
1405 binaryOp(const Data& right,
1406 BinaryFunction operation);
1407
1408 /**
1409 \brief
1410 Convert the data type of the RHS to match this.
1411 \param right - Input - data type to match.
1412 */
1413 void
1414 typeMatchLeft(Data& right) const;
1415
1416 /**
1417 \brief
1418 Convert the data type of this to match the RHS.
1419 \param right - Input - data type to match.
1420 */
1421 void
1422 typeMatchRight(const Data& right);
1423
1424 /**
1425 \brief
1426 Construct a Data object of the appropriate type.
1427 */
1428
1429 void
1430 initialise(const DataTypes::ValueType& value,
1431 const DataTypes::ShapeType& shape,
1432 const FunctionSpace& what,
1433 bool expanded);
1434
1435 void
1436 initialise(const boost::python::numeric::array& value,
1437 const FunctionSpace& what,
1438 bool expanded);
1439
1440 //
1441 // flag to protect the data object against any update
1442 bool m_protected;
1443
1444 //
1445 // pointer to the actual data object
1446 // boost::shared_ptr<DataAbstract> m_data;
1447 DataAbstract_ptr m_data;
1448
1449 const DataReady*
1450 getReady() const;
1451
1452 DataReady*
1453 getReady();
1454
1455 };
1456
1457 } // end namespace escript
1458
1459
1460 // No, this is not supposed to be at the top of the file
1461 #include "DataReady.h"
1462
1463 namespace escript
1464 {
1465
1466 inline
1467 const DataReady*
1468 Data::getReady() const
1469 {
1470 const DataReady* dr=dynamic_cast<const DataReady*>(m_data.get());
1471 EsysAssert((dr!=0), "Error - casting to DataReady.");
1472 return dr;
1473 }
1474
1475 inline
1476 DataReady*
1477 Data::getReady()
1478 {
1479 DataReady* dr=dynamic_cast<DataReady*>(m_data.get());
1480 EsysAssert((dr!=0), "Error - casting to DataReady.");
1481 return dr;
1482 }
1483
1484 inline
1485 DataAbstract::ValueType::value_type*
1486 Data::getSampleData(DataAbstract::ValueType::size_type sampleNo)
1487 {
1488 return getReady()->getSampleData(sampleNo);
1489 }
1490
1491
1492 /**
1493 Modify a filename for MPI parallel output to multiple files
1494 */
1495 char *Escript_MPI_appendRankToFileName(const char *, int, int);
1496
1497 /**
1498 Binary Data object operators.
1499 */
1500 inline double rpow(double x,double y)
1501 {
1502 return pow(y,x);
1503 }
1504
1505 /**
1506 \brief
1507 Operator+
1508 Takes two Data objects.
1509 */
1510 ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1511
1512 /**
1513 \brief
1514 Operator-
1515 Takes two Data objects.
1516 */
1517 ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1518
1519 /**
1520 \brief
1521 Operator*
1522 Takes two Data objects.
1523 */
1524 ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1525
1526 /**
1527 \brief
1528 Operator/
1529 Takes two Data objects.
1530 */
1531 ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1532
1533 /**
1534 \brief
1535 Operator+
1536 Takes LHS Data object and RHS python::object.
1537 python::object must be convertable to Data type.
1538 */
1539 ESCRIPT_DLL_API Data operator+(const Data& left, const boost::python::object& right);
1540
1541 /**
1542 \brief
1543 Operator-
1544 Takes LHS Data object and RHS python::object.
1545 python::object must be convertable to Data type.
1546 */
1547 ESCRIPT_DLL_API Data operator-(const Data& left, const boost::python::object& right);
1548
1549 /**
1550 \brief
1551 Operator*
1552 Takes LHS Data object and RHS python::object.
1553 python::object must be convertable to Data type.
1554 */
1555 ESCRIPT_DLL_API Data operator*(const Data& left, const boost::python::object& right);
1556
1557 /**
1558 \brief
1559 Operator/
1560 Takes LHS Data object and RHS python::object.
1561 python::object must be convertable to Data type.
1562 */
1563 ESCRIPT_DLL_API Data operator/(const Data& left, const boost::python::object& right);
1564
1565 /**
1566 \brief
1567 Operator+
1568 Takes LHS python::object and RHS Data object.
1569 python::object must be convertable to Data type.
1570 */
1571 ESCRIPT_DLL_API Data operator+(const boost::python::object& left, const Data& right);
1572
1573 /**
1574 \brief
1575 Operator-
1576 Takes LHS python::object and RHS Data object.
1577 python::object must be convertable to Data type.
1578 */
1579 ESCRIPT_DLL_API Data operator-(const boost::python::object& left, const Data& right);
1580
1581 /**
1582 \brief
1583 Operator*
1584 Takes LHS python::object and RHS Data object.
1585 python::object must be convertable to Data type.
1586 */
1587 ESCRIPT_DLL_API Data operator*(const boost::python::object& left, const Data& right);
1588
1589 /**
1590 \brief
1591 Operator/
1592 Takes LHS python::object and RHS Data object.
1593 python::object must be convertable to Data type.
1594 */
1595 ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1596
1597
1598
1599 /**
1600 \brief
1601 Output operator
1602 */
1603 ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1604
1605 /**
1606 \brief
1607 Compute a tensor product of two Data objects
1608 \param arg0 - Input - Data object
1609 \param arg1 - Input - Data object
1610 \param axis_offset - Input - axis offset
1611 \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1612 */
1613 ESCRIPT_DLL_API
1614 Data
1615 C_GeneralTensorProduct(Data& arg0,
1616 Data& arg1,
1617 int axis_offset=0,
1618 int transpose=0);
1619
1620
1621
1622 // /**
1623 /* \brief
1624 Return true if operands are equivalent, else return false.
1625 NB: this operator does very little at this point, and isn't to
1626 be relied on. Requires further implementation.*/
1627 //*/
1628 // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1629
1630 /**
1631 \brief
1632 Perform the given binary operation with this and right as operands.
1633 Right is a Data object.
1634 */
1635 template <class BinaryFunction>
1636 inline
1637 void
1638 Data::binaryOp(const Data& right,
1639 BinaryFunction operation)
1640 {
1641 //
1642 // if this has a rank of zero promote it to the rank of the RHS
1643 if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1644 throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1645 }
1646
1647 if (isLazy() || right.isLazy())
1648 {
1649 throw DataException("Programmer error - attempt to call binaryOp with Lazy Data.");
1650 }
1651 //
1652 // initially make the temporary a shallow copy
1653 Data tempRight(right);
1654
1655 if (getFunctionSpace()!=right.getFunctionSpace()) {
1656 if (right.probeInterpolation(getFunctionSpace())) {
1657 //
1658 // an interpolation is required so create a new Data
1659 tempRight=Data(right,this->getFunctionSpace());
1660 } else if (probeInterpolation(right.getFunctionSpace())) {
1661 //
1662 // interpolate onto the RHS function space
1663 Data tempLeft(*this,right.getFunctionSpace());
1664 m_data=tempLeft.m_data;
1665 }
1666 }
1667 operandCheck(tempRight);
1668 //
1669 // ensure this has the right type for the RHS
1670 typeMatchRight(tempRight);
1671 //
1672 // Need to cast to the concrete types so that the correct binaryOp
1673 // is called.
1674 if (isExpanded()) {
1675 //
1676 // Expanded data will be done in parallel, the right hand side can be
1677 // of any data type
1678 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1679 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1680 escript::binaryOp(*leftC,*(tempRight.getReady()),operation);
1681 } else if (isTagged()) {
1682 //
1683 // Tagged data is operated on serially, the right hand side can be
1684 // either DataConstant or DataTagged
1685 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1686 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1687 if (right.isTagged()) {
1688 DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get());
1689 EsysAssert((rightC!=0), "Programming error - casting to DataTagged.");
1690 escript::binaryOp(*leftC,*rightC,operation);
1691 } else {
1692 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1693 EsysAssert((rightC!=0), "Programming error - casting to DataConstant.");
1694 escript::binaryOp(*leftC,*rightC,operation);
1695 }
1696 } else if (isConstant()) {
1697 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1698 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1699 EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1700 escript::binaryOp(*leftC,*rightC,operation);
1701 }
1702 }
1703
1704 /**
1705 \brief
1706 Perform the given Data object reduction algorithm on this and return the result.
1707 Given operation combines each element of each data point, thus argument
1708 object (*this) is a rank n Data object, and returned object is a scalar.
1709 Calls escript::algorithm.
1710 */
1711 template <class BinaryFunction>
1712 inline
1713 double
1714 Data::algorithm(BinaryFunction operation, double initial_value) const
1715 {
1716 if (isExpanded()) {
1717 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1718 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1719 return escript::algorithm(*leftC,operation,initial_value);
1720 } else if (isTagged()) {
1721 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1722 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1723 return escript::algorithm(*leftC,operation,initial_value);
1724 } else if (isConstant()) {
1725 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1726 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1727 return escript::algorithm(*leftC,operation,initial_value);
1728 } else if (isEmpty()) {
1729 throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1730 } else if (isLazy()) {
1731 throw DataException("Error - Operations not permitted on instances of DataLazy.");
1732 } else {
1733 throw DataException("Error - Data encapsulates an unknown type.");
1734 }
1735 }
1736
1737 /**
1738 \brief
1739 Perform the given data point reduction algorithm on data and return the result.
1740 Given operation combines each element within each data point into a scalar,
1741 thus argument object is a rank n Data object, and returned object is a
1742 rank 0 Data object.
1743 Calls escript::dp_algorithm.
1744 */
1745 template <class BinaryFunction>
1746 inline
1747 Data
1748 Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1749 {
1750 if (isEmpty()) {
1751 throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1752 }
1753 else if (isExpanded()) {
1754 Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1755 DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1756 DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1757 EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1758 EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1759 escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1760 return result;
1761 }
1762 else if (isTagged()) {
1763 DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
1764 EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1765 DataTypes::ValueType defval(1);
1766 defval[0]=0;
1767 DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1768 escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1769 return Data(resultT); // note: the Data object now owns the resultT pointer
1770 }
1771 else if (isConstant()) {
1772 Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1773 DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1774 DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1775 EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1776 EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1777 escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1778 return result;
1779 } else if (isLazy()) {
1780 throw DataException("Error - Operations not permitted on instances of DataLazy.");
1781 } else {
1782 throw DataException("Error - Data encapsulates an unknown type.");
1783 }
1784 }
1785
1786 /**
1787 \brief
1788 Compute a tensor operation with two Data objects
1789 \param arg0 - Input - Data object
1790 \param arg1 - Input - Data object
1791 \param operation - Input - Binary op functor
1792 */
1793 template <typename BinaryFunction>
1794 inline
1795 Data
1796 C_TensorBinaryOperation(Data const &arg_0,
1797 Data const &arg_1,
1798 BinaryFunction operation)
1799 {
1800 if (arg_0.isEmpty() || arg_1.isEmpty())
1801 {
1802 throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1803 }
1804 if (arg_0.isLazy() || arg_1.isLazy())
1805 {
1806 throw DataException("Error - Operations not permitted on lazy data.");
1807 }
1808 // Interpolate if necessary and find an appropriate function space
1809 Data arg_0_Z, arg_1_Z;
1810 if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1811 if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1812 arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1813 arg_1_Z = Data(arg_1);
1814 }
1815 else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1816 arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1817 arg_0_Z =Data(arg_0);
1818 }
1819 else {
1820 throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1821 }
1822 } else {
1823 arg_0_Z = Data(arg_0);
1824 arg_1_Z = Data(arg_1);
1825 }
1826 // Get rank and shape of inputs
1827 int rank0 = arg_0_Z.getDataPointRank();
1828 int rank1 = arg_1_Z.getDataPointRank();
1829 DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1830 DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1831 int size0 = arg_0_Z.getDataPointSize();
1832 int size1 = arg_1_Z.getDataPointSize();
1833
1834 // Declare output Data object
1835 Data res;
1836
1837 if (shape0 == shape1) {
1838
1839 if (arg_0_Z.isConstant() && arg_1_Z.isConstant()) {
1840 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataConstant output
1841 /* double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1842 double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1843 double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1844 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1845 double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1846 double *ptr_2 = &(res.getDataAtOffset(0));
1847
1848 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1849 }
1850 else if (arg_0_Z.isConstant() && arg_1_Z.isTagged()) {
1851
1852 // Prepare the DataConstant input
1853 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1854
1855 // Borrow DataTagged input from Data object
1856 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1857
1858 // Prepare a DataTagged output 2
1859 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataTagged output
1860 res.tag();
1861 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1862
1863 // Prepare offset into DataConstant
1864 int offset_0 = tmp_0->getPointOffset(0,0);
1865 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1866 // Get the views
1867 // DataArrayView view_1 = tmp_1->getDefaultValue();
1868 // DataArrayView view_2 = tmp_2->getDefaultValue();
1869 // // Get the pointers to the actual data
1870 // double *ptr_1 = &((view_1.getData())[0]);
1871 // double *ptr_2 = &((view_2.getData())[0]);
1872
1873 // Get the pointers to the actual data
1874 double *ptr_1 = &(tmp_1->getDefaultValue(0));
1875 double *ptr_2 = &(tmp_2->getDefaultValue(0));
1876
1877 // Compute a result for the default
1878 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1879 // Compute a result for each tag
1880 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1881 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1882 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1883 tmp_2->addTag(i->first);
1884 /* DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1885 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1886 double *ptr_1 = &view_1.getData(0);
1887 double *ptr_2 = &view_2.getData(0);*/
1888 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1889 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1890
1891 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1892 }
1893
1894 }
1895 else if (arg_0_Z.isConstant() && arg_1_Z.isExpanded()) {
1896
1897 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1898 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1899 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1900 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1901
1902 int sampleNo_1,dataPointNo_1;
1903 int numSamples_1 = arg_1_Z.getNumSamples();
1904 int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1905 int offset_0 = tmp_0->getPointOffset(0,0);
1906 #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1907 for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1908 for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1909 int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1910 int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1911 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1912 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1913 // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1914
1915 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1916 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1917 double *ptr_2 = &(res.getDataAtOffset(offset_2));
1918 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1919 }
1920 }
1921
1922 }
1923 else if (arg_0_Z.isTagged() && arg_1_Z.isConstant()) {
1924
1925 // Borrow DataTagged input from Data object
1926 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1927
1928 // Prepare the DataConstant input
1929 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1930
1931 // Prepare a DataTagged output 2
1932 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataTagged output
1933 res.tag();
1934 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1935
1936 // Prepare offset into DataConstant
1937 int offset_1 = tmp_1->getPointOffset(0,0);
1938 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1939 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1940 // Get the views
1941 // DataArrayView view_0 = tmp_0->getDefaultValue();
1942 // DataArrayView view_2 = tmp_2->getDefaultValue();
1943 // // Get the pointers to the actual data
1944 // double *ptr_0 = &((view_0.getData())[0]);
1945 // double *ptr_2 = &((view_2.getData())[0]);
1946 // Get the pointers to the actual data
1947 double *ptr_0 = &(tmp_0->getDefaultValue(0));
1948 double *ptr_2 = &(tmp_2->getDefaultValue(0));
1949 // Compute a result for the default
1950 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1951 // Compute a result for each tag
1952 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1953 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1954 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1955 tmp_2->addTag(i->first);
1956 // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1957 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1958 // double *ptr_0 = &view_0.getData(0);
1959 // double *ptr_2 = &view_2.getData(0);
1960 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1961 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1962 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1963 }
1964
1965 }
1966 else if (arg_0_Z.isTagged() && arg_1_Z.isTagged()) {
1967
1968 // Borrow DataTagged input from Data object
1969 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1970
1971 // Borrow DataTagged input from Data object
1972 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1973
1974 // Prepare a DataTagged output 2
1975 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1976 res.tag(); // DataTagged output
1977 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1978
1979 // // Get the views
1980 // DataArrayView view_0 = tmp_0->getDefaultValue();
1981 // DataArrayView view_1 = tmp_1->getDefaultValue();
1982 // DataArrayView view_2 = tmp_2->getDefaultValue();
1983 // // Get the pointers to the actual data
1984 // double *ptr_0 = &((view_0.getData())[0]);
1985 // double *ptr_1 = &((view_1.getData())[0]);
1986 // double *ptr_2 = &((view_2.getData())[0]);
1987
1988 // Get the pointers to the actual data
1989 double *ptr_0 = &(tmp_0->getDefaultValue(0));
1990 double *ptr_1 = &(tmp_1->getDefaultValue(0));
1991 double *ptr_2 = &(tmp_2->getDefaultValue(0));
1992
1993 // Compute a result for the default
1994 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1995 // Merge the tags
1996 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1997 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1998 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1999 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2000 tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2001 }
2002 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2003 tmp_2->addTag(i->first);
2004 }
2005 // Compute a result for each tag
2006 const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2007 for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2008
2009 // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2010 // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2011 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2012 // double *ptr_0 = &view_0.getData(0);
2013 // double *ptr_1 = &view_1.getData(0);
2014 // double *ptr_2 = &view_2.getData(0);
2015
2016 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2017 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2018 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2019
2020 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2021 }
2022
2023 }
2024 else if (arg_0_Z.isTagged() && arg_1_Z.isExpanded()) {
2025
2026 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2027 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2028 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2029 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2030 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2031
2032 int sampleNo_0,dataPointNo_0;
2033 int numSamples_0 = arg_0_Z.getNumSamples();
2034 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2035 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2036 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2037 int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2038 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2039 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2040 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2041 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2042
2043 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2044 // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2045 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2046 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2047
2048
2049 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2050 }
2051 }
2052
2053 }
2054 else if (arg_0_Z.isExpanded() && arg_1_Z.isConstant()) {
2055
2056 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2057 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2058 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2059 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2060
2061 int sampleNo_0,dataPointNo_0;
2062 int numSamples_0 = arg_0_Z.getNumSamples();
2063 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2064 int offset_1 = tmp_1->getPointOffset(0,0);
2065 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2066 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2067 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2068 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2069 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2070
2071 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2072 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2073 // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2074
2075 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2076 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2077 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2078
2079
2080 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2081 }
2082 }
2083
2084 }
2085 else if (arg_0_Z.isExpanded() && arg_1_Z.isTagged()) {
2086
2087 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2088 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2089 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2090 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2091 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2092
2093 int sampleNo_0,dataPointNo_0;
2094 int numSamples_0 = arg_0_Z.getNumSamples();
2095 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2096 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2097 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2098 int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2099 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2100 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2101 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2102 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2103 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2104 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2105 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2106 }
2107 }
2108
2109 }
2110 else if (arg_0_Z.isExpanded() && arg_1_Z.isExpanded()) {
2111
2112 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2113 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2114 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2115 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2116 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2117
2118 int sampleNo_0,dataPointNo_0;
2119 int numSamples_0 = arg_0_Z.getNumSamples();
2120 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2121 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2122 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2123 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2124 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2125 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2126 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2127 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2128 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2129 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2130 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2131 }
2132 }
2133
2134 }
2135 else {
2136 throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2137 }
2138
2139 } else if (0 == rank0) {
2140
2141 if (arg_0_Z.isConstant() && arg_1_Z.isConstant()) {
2142 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace()); // DataConstant output
2143 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2144 double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2145 double *ptr_2 = &(res.getDataAtOffset(0));
2146 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2147 }
2148 else if (arg_0_Z.isConstant() && arg_1_Z.isTagged()) {
2149
2150 // Prepare the DataConstant input
2151 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2152
2153 // Borrow DataTagged input from Data object
2154 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2155
2156 // Prepare a DataTagged output 2
2157 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace()); // DataTagged output
2158 res.tag();
2159 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2160
2161 // Prepare offset into DataConstant
2162 int offset_0 = tmp_0->getPointOffset(0,0);
2163 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2164 // Get the views
2165 // DataArrayView view_1 = tmp_1->getDefaultValue();
2166 // DataArrayView view_2 = tmp_2->getDefaultValue();
2167 // // Get the pointers to the actual data
2168 // double *ptr_1 = &((view_1.getData())[0]);
2169 // double *ptr_2 = &((view_2.getData())[0]);
2170 double *ptr_1 = &(tmp_1->getDefaultValue(0));
2171 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2172
2173 // Compute a result for the default
2174 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2175 // Compute a result for each tag
2176 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2177 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2178 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2179 tmp_2->addTag(i->first);
2180 // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2181 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2182 // double *ptr_1 = &view_1.getData(0);
2183 // double *ptr_2 = &view_2.getData(0);
2184 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2185 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2186 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2187 }
2188
2189 }
2190 else if (arg_0_Z.isConstant() && arg_1_Z.isExpanded()) {
2191
2192 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2193 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2194 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2195 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2196
2197 int sampleNo_1,dataPointNo_1;
2198 int numSamples_1 = arg_1_Z.getNumSamples();
2199 int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2200 int offset_0 = tmp_0->getPointOffset(0,0);
2201 #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2202 for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2203 for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2204 int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2205 int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2206 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2207 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2208 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2209 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2210
2211 }
2212 }
2213
2214 }
2215 else if (arg_0_Z.isTagged() && arg_1_Z.isConstant()) {
2216
2217 // Borrow DataTagged input from Data object
2218 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2219
2220 // Prepare the DataConstant input
2221 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2222
2223 // Prepare a DataTagged output 2
2224 res = Data(0.0, shape1, arg_0_Z.getFunctionSpace()); // DataTagged output
2225 res.tag();
2226 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2227
2228 // Prepare offset into DataConstant
2229 int offset_1 = tmp_1->getPointOffset(0,0);
2230 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2231 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2232 // Get the views
2233 /* DataArrayView view_0 = tmp_0->getDefaultValue();
2234 DataArrayView view_2 = tmp_2->getDefaultValue();
2235 // Get the pointers to the actual data
2236 double *ptr_0 = &((view_0.getData())[0]);
2237 double *ptr_2 = &((view_2.getData())[0]);*/
2238
2239 // Get the pointers to the actual data
2240 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2241 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2242
2243
2244 // Compute a result for the default
2245 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2246 // Compute a result for each tag
2247 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2248 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2249 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2250 tmp_2->addTag(i->first);
2251 /* DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2252 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2253 double *ptr_0 = &view_0.getData(0);
2254 double *ptr_2 = &view_2.getData(0);*/
2255 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2256 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2257
2258 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2259 }
2260
2261 }
2262 else if (arg_0_Z.isTagged() && arg_1_Z.isTagged()) {
2263
2264 // Borrow DataTagged input from Data object
2265 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2266
2267 // Borrow DataTagged input from Data object
2268 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2269
2270 // Prepare a DataTagged output 2
2271 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2272 res.tag(); // DataTagged output
2273 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2274
2275 // Get the views
2276 /* DataArrayView view_0 = tmp_0->getDefaultValue();
2277 DataArrayView view_1 = tmp_1->getDefaultValue();
2278 DataArrayView view_2 = tmp_2->getDefaultValue();
2279 // Get the pointers to the actual data
2280 double *ptr_0 = &((view_0.getData())[0]);
2281 double *ptr_1 = &((view_1.getData())[0]);
2282 double *ptr_2 = &((view_2.getData())[0]);*/
2283
2284 // Get the pointers to the actual data
2285 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2286 double *ptr_1 = &(tmp_1->getDefaultValue(0));
2287 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2288
2289
2290 // Compute a result for the default
2291 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2292 // Merge the tags
2293 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2294 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2295 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2296 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2297 tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2298 }
2299 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2300 tmp_2->addTag(i->first);
2301 }
2302 // Compute a result for each tag
2303 const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2304 for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2305
2306 /* DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2307 DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2308 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2309 double *ptr_0 = &view_0.getData(0);
2310 double *ptr_1 = &view_1.getData(0);
2311 double *ptr_2 = &view_2.getData(0);*/
2312
2313 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2314 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2315 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2316
2317 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2318 }
2319
2320 }
2321 else if (arg_0_Z.isTagged() && arg_1_Z.isExpanded()) {
2322
2323 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2324 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2325 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2326 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2327 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2328
2329 int sampleNo_0,dataPointNo_0;
2330 int numSamples_0 = arg_0_Z.getNumSamples();
2331 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2332 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2333 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2334 int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2335 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2336 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2337 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2338 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2339 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2340 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2341 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2342 }
2343 }
2344
2345 }
2346 else if (arg_0_Z.isExpanded() && arg_1_Z.isConstant()) {
2347
2348 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2349 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2350 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2351 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2352
2353 int sampleNo_0,dataPointNo_0;
2354 int numSamples_0 = arg_0_Z.getNumSamples();
2355 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2356 int offset_1 = tmp_1->getPointOffset(0,0);
2357 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2358 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2359 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2360 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2361 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2362 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2363 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2364 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2365 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2366 }
2367 }
2368
2369
2370 }
2371 else if (arg_0_Z.isExpanded() && arg_1_Z.isTagged()) {
2372
2373 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2374 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2375 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2376 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2377 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2378
2379 int sampleNo_0,dataPointNo_0;
2380 int numSamples_0 = arg_0_Z.getNumSamples();
2381 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2382 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2383 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2384 int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2385 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2386 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2387 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2388 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2389 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2390 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2391 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2392 }
2393 }
2394
2395 }
2396 else if (arg_0_Z.isExpanded() && arg_1_Z.isExpanded()) {
2397
2398 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2399 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2400 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2401 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2402 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2403
2404 int sampleNo_0,dataPointNo_0;
2405 int numSamples_0 = arg_0_Z.getNumSamples();
2406 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2407 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2408 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2409 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2410 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2411 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2412 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2413 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2414 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2415 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2416 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2417 }
2418 }
2419
2420 }
2421 else {
2422 throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2423 }
2424
2425 } else if (0 == rank1) {
2426
2427 if (arg_0_Z.isConstant() && arg_1_Z.isConstant()) {
2428 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataConstant output
2429 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2430 double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2431 double *ptr_2 = &(res.getDataAtOffset(0));
2432 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2433 }
2434 else if (arg_0_Z.isConstant() && arg_1_Z.isTagged()) {
2435
2436 // Prepare the DataConstant input
2437 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2438
2439 // Borrow DataTagged input from Data object
2440 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2441
2442 // Prepare a DataTagged output 2
2443 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataTagged output
2444 res.tag();
2445 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2446
2447 // Prepare offset into DataConstant
2448 int offset_0 = tmp_0->getPointOffset(0,0);
2449 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2450 // Get the views
2451 /* DataArrayView view_1 = tmp_1->getDefaultValue();
2452 DataArrayView view_2 = tmp_2->getDefaultValue();
2453 // Get the pointers to the actual data
2454 double *ptr_1 = &((view_1.getData())[0]);
2455 double *ptr_2 = &((view_2.getData())[0]);*/
2456 //Get the pointers to the actual data
2457 double *ptr_1 = &(tmp_1->getDefaultValue(0));
2458 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2459
2460 // Compute a result for the default
2461 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2462 // Compute a result for each tag
2463 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2464 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2465 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2466 tmp_2->addTag(i->first);
2467 // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2468 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2469 // double *ptr_1 = &view_1.getData(0);
2470 // double *ptr_2 = &view_2.getData(0);
2471 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2472 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2473
2474
2475 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2476 }
2477
2478 }
2479 else if (arg_0_Z.isConstant() && arg_1_Z.isExpanded()) {
2480
2481 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2482 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2483 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2484 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2485
2486 int sampleNo_1,dataPointNo_1;
2487 int numSamples_1 = arg_1_Z.getNumSamples();
2488 int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2489 int offset_0 = tmp_0->getPointOffset(0,0);
2490 #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2491 for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2492 for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2493 int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2494 int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2495 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2496 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2497 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2498 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2499 }
2500 }
2501
2502 }
2503 else if (arg_0_Z.isTagged() && arg_1_Z.isConstant()) {
2504
2505 // Borrow DataTagged input from Data object
2506 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2507
2508 // Prepare the DataConstant input
2509 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2510
2511 // Prepare a DataTagged output 2
2512 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataTagged output
2513 res.tag();
2514 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2515
2516 // Prepare offset into DataConstant
2517 int offset_1 = tmp_1->getPointOffset(0,0);
2518 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2519 // Get the views
2520 // DataArrayView view_0 = tmp_0->getDefaultValue();
2521 // DataArrayView view_2 = tmp_2->getDefaultValue();
2522 // // Get the pointers to the actual data
2523 // double *ptr_0 = &((view_0.getData())[0]);
2524 // double *ptr_2 = &((view_2.getData())[0]);
2525 // Get the pointers to the actual data
2526 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2527 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2528 // Compute a result for the default
2529 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2530 // Compute a result for each tag
2531 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2532 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2533 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2534 tmp_2->addTag(i->first);
2535 /* DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2536 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2537 double *ptr_0 = &view_0.getData(0);
2538 double *ptr_2 = &view_2.getData(0);*/
2539 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2540 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2541 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2542 }
2543
2544 }
2545 else if (arg_0_Z.isTagged() && arg_1_Z.isTagged()) {
2546
2547 // Borrow DataTagged input from Data object
2548 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2549
2550 // Borrow DataTagged input from Data object
2551 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2552
2553 // Prepare a DataTagged output 2
2554 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2555 res.tag(); // DataTagged output
2556 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2557
2558 // Get the views
2559 // DataArrayView view_0 = tmp_0->getDefaultValue();
2560 // DataArrayView view_1 = tmp_1->getDefaultValue();
2561 // DataArrayView view_2 = tmp_2->getDefaultValue();
2562 // // Get the pointers to the actual data
2563 // double *ptr_0 = &((view_0.getData())[0]);
2564 // double *ptr_1 = &((view_1.getData())[0]);
2565 // double *ptr_2 = &((view_2.getData())[0]);
2566
2567 // Get the pointers to the actual data
2568 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2569 double *ptr_1 = &(tmp_1->getDefaultValue(0));
2570 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2571
2572 // Compute a result for the default
2573 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2574 // Merge the tags
2575 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2576 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2577 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2578 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2579 tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2580 }
2581 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2582 tmp_2->addTag(i->first);
2583 }
2584 // Compute a result for each tag
2585 const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2586 for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2587 // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2588 // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2589 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2590 // double *ptr_0 = &view_0.getData(0);
2591 // double *ptr_1 = &view_1.getData(0);
2592 // double *ptr_2 = &view_2.getData(0);
2593
2594 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2595 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2596 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2597 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2598 }
2599
2600 }
2601 else if (arg_0_Z.isTagged() && arg_1_Z.isExpanded()) {
2602
2603 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2604 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2605 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2606 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2607 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2608
2609 int sampleNo_0,dataPointNo_0;
2610 int numSamples_0 = arg_0_Z.getNumSamples();
2611 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2612 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2613 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2614 int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2615 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2616 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2617 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2618 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2619 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2620 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2621 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2622 }
2623 }
2624
2625 }
2626 else if (arg_0_Z.isExpanded() && arg_1_Z.isConstant()) {
2627
2628 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2629 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2630 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2631 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2632
2633 int sampleNo_0,dataPointNo_0;
2634 int numSamples_0 = arg_0_Z.getNumSamples();
2635 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2636 int offset_1 = tmp_1->getPointOffset(0,0);
2637 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2638 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2639 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2640 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2641 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2642 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2643 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2644 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2645 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2646 }
2647 }
2648
2649
2650 }
2651 else if (arg_0_Z.isExpanded() && arg_1_Z.isTagged()) {
2652
2653 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2654 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2655 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2656 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2657 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2658
2659 int sampleNo_0,dataPointNo_0;
2660 int numSamples_0 = arg_0_Z.getNumSamples();
2661 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2662 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2663 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2664 int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2665 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2666 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2667 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2668 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2669 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2670 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2671 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2672 }
2673 }
2674
2675 }
2676 else if (arg_0_Z.isExpanded() && arg_1_Z.isExpanded()) {
2677
2678 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2679 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2680 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2681 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2682 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2683
2684 int sampleNo_0,dataPointNo_0;
2685 int numSamples_0 = arg_0_Z.getNumSamples();
2686 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2687 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2688 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2689 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2690 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2691 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2692 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2693 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2694 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2695 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2696 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2697 }
2698 }
2699
2700 }
2701 else {
2702 throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2703 }
2704
2705 } else {
2706 throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2707 }
2708
2709 return res;
2710 }
2711
2712 template <typename UnaryFunction>
2713 Data
2714 C_TensorUnaryOperation(Data const &arg_0,
2715 UnaryFunction operation)
2716 {
2717 if (arg_0.isEmpty()) // do this before we attempt to interpolate
2718 {
2719 throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2720 }
2721 if (arg_0.isLazy())
2722 {
2723 throw DataException("Error - Operations not permitted on lazy data.");
2724 }
2725 // Interpolate if necessary and find an appropriate function space
2726 Data arg_0_Z = Data(arg_0);
2727
2728 // Get rank and shape of inputs
2729 int rank0 = arg_0_Z.getDataPointRank();
2730 const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2731 int size0 = arg_0_Z.getDataPointSize();
2732
2733 // Declare output Data object
2734 Data res;
2735
2736 if (arg_0_Z.isConstant()) {
2737 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataConstant output
2738 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2739 // double *ptr_2 = &((res.getPointDataView().getData())[0]);
2740 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2741 double *ptr_2 = &(res.getDataAtOffset(0));
2742 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2743 }
2744 else if (arg_0_Z.isTagged()) {
2745
2746 // Borrow DataTagged input from Data object
2747 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2748
2749 // Prepare a DataTagged output 2
2750 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataTagged output
2751 res.tag();
2752 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2753
2754 // // Get the views
2755 // DataArrayView view_0 = tmp_0->getDefaultValue();
2756 // DataArrayView view_2 = tmp_2->getDefaultValue();
2757 // // Get the pointers to the actual data
2758 // double *ptr_0 = &((view_0.getData())[0]);
2759 // double *ptr_2 = &((view_2.getData())[0]);
2760 // Get the pointers to the actual data
2761 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2762 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2763 // Compute a result for the default
2764 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2765 // Compute a result for each tag
2766 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2767 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2768 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2769 tmp_2->addTag(i->first);
2770 // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2771 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2772 // double *ptr_0 = &view_0.getData(0);
2773 // double *ptr_2 = &view_2.getData(0);
2774 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2775 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2776 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2777 }
2778
2779 }
2780 else if (arg_0_Z.isExpanded()) {
2781
2782 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2783 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2784 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2785
2786 int sampleNo_0,dataPointNo_0;
2787 int numSamples_0 = arg_0_Z.getNumSamples();
2788 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2789 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2790 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2791 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2792 // int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2793 // int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2794 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2795 // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2796 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2797 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2798 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2799 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2800 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2801 }
2802 }
2803 }
2804 else {
2805 throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2806 }
2807
2808 return res;
2809 }
2810
2811 }
2812 #endif

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26