/[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 1879 - (show annotations)
Tue Oct 14 03:54:42 2008 UTC (10 years, 6 months ago) by jfenwick
File MIME type: text/plain
File size: 88811 byte(s)
Branch commit.
About to make some changes.

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26