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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1952 - (show annotations)
Thu Oct 30 06:16:00 2008 UTC (11 years, 3 months ago) by jfenwick
File MIME type: text/plain
File size: 88577 byte(s)
Fixed /* in a comment.
The rank of a datapoint is now an unsigned int.

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26