/[escript]/trunk/escript/src/Data.h
ViewVC logotype

Contents of /trunk/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1857 - (show annotations)
Tue Oct 7 23:58:44 2008 UTC (12 years, 9 months ago) by jfenwick
File MIME type: text/plain
File size: 88305 byte(s)
Updated doco to describe the behaviour of inf, sup and Lsup for cases 
where none of the tags in use in the domain have values.

It confused me when I was testing.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26