/[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 1820 - (show annotations)
Wed Oct 1 03:48:18 2008 UTC (11 years ago) by jfenwick
Original Path: branches/more_shared_ptrs_from_1812/escript/src/Data.h
File MIME type: text/plain
File size: 88078 byte(s)
Branch commit.

First experiments with shared_ptr.
There is a crash on exit due to deallocating the NullDomain object twice.
(One from shared_ptr and once in global destructors)


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26