/[escript]/branches/schroedinger/escript/src/Data.h
ViewVC logotype

Contents of /branches/schroedinger/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1822 - (show annotations)
Wed Oct 1 05:42:31 2008 UTC (11 years ago) by jfenwick
Original Path: branches/more_shared_ptrs_from_1812/escript/src/Data.h
File MIME type: text/plain
File size: 88207 byte(s)
Branch commit
Passes all unit tests.
Still resorting to special python versions of getDomain to get around type conversion.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26