/[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 1868 - (show annotations)
Thu Oct 9 06:30:49 2008 UTC (10 years, 6 months ago) by jfenwick
File MIME type: text/plain
File size: 88676 byte(s)
Branch commit.
Bulk resolve for + - * /

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26