/[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 1864 - (show annotations)
Thu Oct 9 03:09:30 2008 UTC (11 years ago) by jfenwick
File MIME type: text/plain
File size: 88392 byte(s)
Branch commit
It compiles but doesn't do much.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26