/[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 1828 - (show annotations)
Thu Oct 2 04:52:11 2008 UTC (11 years, 1 month ago) by jfenwick
Original Path: branches/more_shared_ptrs_from_1812/escript/src/Data.h
File MIME type: text/plain
File size: 88237 byte(s)
Branch commit.
Added getPtr to DataAbstract.
Passes all unit tests.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26