/[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 1888 - (show annotations)
Wed Oct 15 04:00:21 2008 UTC (11 years, 10 months ago) by jfenwick
File MIME type: text/plain
File size: 89703 byte(s)
Branch commit.
Added more binary ops.

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 The method is not const because lazy data needs to be expanded before Lsup can be computed.
803 The _const form can be used when the Data object is const, however this will only work for
804 Data which is not Lazy.
805 *
806 */
807 ESCRIPT_DLL_API
808 double
809 Lsup();
810
811 ESCRIPT_DLL_API
812 double
813 Lsup_const() const;
814
815
816 /**
817 \brief
818 Return the maximum value of this Data object.
819 The method is not const because lazy data needs to be expanded before sup can be computed.
820 The _const form can be used when the Data object is const, however this will only work for
821 Data which is not Lazy.
822 *
823 */
824 ESCRIPT_DLL_API
825 double
826 sup();
827
828 ESCRIPT_DLL_API
829 double
830 sup_const() const;
831
832
833 /**
834 \brief
835 Return the minimum value of this Data object.
836 The method is not const because lazy data needs to be expanded before inf can be computed.
837 The _const form can be used when the Data object is const, however this will only work for
838 Data which is not Lazy.
839 *
840 */
841 ESCRIPT_DLL_API
842 double
843 inf();
844
845 ESCRIPT_DLL_API
846 double
847 inf_const() const;
848
849
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 ESCRIPT_DLL_API
1369 DataAbstract_ptr
1370 borrowDataPtr(void) const;
1371
1372 ESCRIPT_DLL_API
1373 DataReady_ptr
1374 borrowReadyPtr(void) const;
1375
1376
1377
1378 /**
1379 \brief
1380 Return a pointer to the beginning of the datapoint at the specified offset.
1381 TODO Eventually these should be inlined.
1382 \param i - position(offset) in the underlying datastructure
1383 */
1384 ESCRIPT_DLL_API
1385 DataTypes::ValueType::const_reference
1386 getDataAtOffset(DataTypes::ValueType::size_type i) const;
1387
1388
1389 ESCRIPT_DLL_API
1390 DataTypes::ValueType::reference
1391 getDataAtOffset(DataTypes::ValueType::size_type i);
1392
1393 protected:
1394
1395 private:
1396
1397 double
1398 LsupWorker() const;
1399
1400 double
1401 supWorker() const;
1402
1403 double
1404 infWorker() const;
1405
1406 /**
1407 \brief
1408 Check *this and the right operand are compatible. Throws
1409 an exception if they aren't.
1410 \param right - Input - The right hand side.
1411 */
1412 inline
1413 void
1414 operandCheck(const Data& right) const
1415 {
1416 return m_data->operandCheck(*(right.m_data.get()));
1417 }
1418
1419 /**
1420 \brief
1421 Perform the specified reduction algorithm on every element of every data point in
1422 this Data object according to the given function and return the single value result.
1423 */
1424 template <class BinaryFunction>
1425 inline
1426 double
1427 algorithm(BinaryFunction operation,
1428 double initial_value) const;
1429
1430 /**
1431 \brief
1432 Reduce each data-point in this Data object using the given operation. Return a Data
1433 object with the same number of data-points, but with each data-point containing only
1434 one value - the result of the reduction operation on the corresponding data-point in
1435 this Data object
1436 */
1437 template <class BinaryFunction>
1438 inline
1439 Data
1440 dp_algorithm(BinaryFunction operation,
1441 double initial_value) const;
1442
1443 /**
1444 \brief
1445 Perform the given binary operation on all of the data's elements.
1446 The underlying type of the right hand side (right) determines the final
1447 type of *this after the operation. For example if the right hand side
1448 is expanded *this will be expanded if necessary.
1449 RHS is a Data object.
1450 */
1451 template <class BinaryFunction>
1452 inline
1453 void
1454 binaryOp(const Data& right,
1455 BinaryFunction operation);
1456
1457 /**
1458 \brief
1459 Convert the data type of the RHS to match this.
1460 \param right - Input - data type to match.
1461 */
1462 void
1463 typeMatchLeft(Data& right) const;
1464
1465 /**
1466 \brief
1467 Convert the data type of this to match the RHS.
1468 \param right - Input - data type to match.
1469 */
1470 void
1471 typeMatchRight(const Data& right);
1472
1473 /**
1474 \brief
1475 Construct a Data object of the appropriate type.
1476 */
1477
1478 void
1479 initialise(const DataTypes::ValueType& value,
1480 const DataTypes::ShapeType& shape,
1481 const FunctionSpace& what,
1482 bool expanded);
1483
1484 void
1485 initialise(const boost::python::numeric::array& value,
1486 const FunctionSpace& what,
1487 bool expanded);
1488
1489 //
1490 // flag to protect the data object against any update
1491 bool m_protected;
1492
1493 //
1494 // pointer to the actual data object
1495 // boost::shared_ptr<DataAbstract> m_data;
1496 DataAbstract_ptr m_data;
1497
1498 const DataReady*
1499 getReady() const;
1500
1501 DataReady*
1502 getReady();
1503
1504 };
1505
1506 } // end namespace escript
1507
1508
1509 // No, this is not supposed to be at the top of the file
1510 // DataAbstact needs to be declared first, then DataReady needs to be fully declared
1511 // so that I can dynamic cast between them below.
1512 #include "DataReady.h"
1513
1514 namespace escript
1515 {
1516
1517 inline
1518 const DataReady*
1519 Data::getReady() const
1520 {
1521 const DataReady* dr=dynamic_cast<const DataReady*>(m_data.get());
1522 EsysAssert((dr!=0), "Error - casting to DataReady.");
1523 return dr;
1524 }
1525
1526 inline
1527 DataReady*
1528 Data::getReady()
1529 {
1530 DataReady* dr=dynamic_cast<DataReady*>(m_data.get());
1531 EsysAssert((dr!=0), "Error - casting to DataReady.");
1532 return dr;
1533 }
1534
1535 inline
1536 DataAbstract::ValueType::value_type*
1537 Data::getSampleData(DataAbstract::ValueType::size_type sampleNo)
1538 {
1539 return getReady()->getSampleData(sampleNo);
1540 }
1541
1542
1543 /**
1544 Modify a filename for MPI parallel output to multiple files
1545 */
1546 char *Escript_MPI_appendRankToFileName(const char *, int, int);
1547
1548 /**
1549 Binary Data object operators.
1550 */
1551 inline double rpow(double x,double y)
1552 {
1553 return pow(y,x);
1554 }
1555
1556 /**
1557 \brief
1558 Operator+
1559 Takes two Data objects.
1560 */
1561 ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1562
1563 /**
1564 \brief
1565 Operator-
1566 Takes two Data objects.
1567 */
1568 ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1569
1570 /**
1571 \brief
1572 Operator*
1573 Takes two Data objects.
1574 */
1575 ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1576
1577 /**
1578 \brief
1579 Operator/
1580 Takes two Data objects.
1581 */
1582 ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1583
1584 /**
1585 \brief
1586 Operator+
1587 Takes LHS Data object and RHS python::object.
1588 python::object must be convertable to Data type.
1589 */
1590 ESCRIPT_DLL_API Data operator+(const Data& left, const boost::python::object& right);
1591
1592 /**
1593 \brief
1594 Operator-
1595 Takes LHS Data object and RHS python::object.
1596 python::object must be convertable to Data type.
1597 */
1598 ESCRIPT_DLL_API Data operator-(const Data& left, const boost::python::object& right);
1599
1600 /**
1601 \brief
1602 Operator*
1603 Takes LHS Data object and RHS python::object.
1604 python::object must be convertable to Data type.
1605 */
1606 ESCRIPT_DLL_API Data operator*(const Data& left, const boost::python::object& right);
1607
1608 /**
1609 \brief
1610 Operator/
1611 Takes LHS Data object and RHS python::object.
1612 python::object must be convertable to Data type.
1613 */
1614 ESCRIPT_DLL_API Data operator/(const Data& left, const boost::python::object& right);
1615
1616 /**
1617 \brief
1618 Operator+
1619 Takes LHS python::object and RHS Data object.
1620 python::object must be convertable to Data type.
1621 */
1622 ESCRIPT_DLL_API Data operator+(const boost::python::object& left, const Data& right);
1623
1624 /**
1625 \brief
1626 Operator-
1627 Takes LHS python::object and RHS Data object.
1628 python::object must be convertable to Data type.
1629 */
1630 ESCRIPT_DLL_API Data operator-(const boost::python::object& left, const Data& right);
1631
1632 /**
1633 \brief
1634 Operator*
1635 Takes LHS python::object and RHS Data object.
1636 python::object must be convertable to Data type.
1637 */
1638 ESCRIPT_DLL_API Data operator*(const boost::python::object& left, const Data& right);
1639
1640 /**
1641 \brief
1642 Operator/
1643 Takes LHS python::object and RHS Data object.
1644 python::object must be convertable to Data type.
1645 */
1646 ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1647
1648
1649
1650 /**
1651 \brief
1652 Output operator
1653 */
1654 ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1655
1656 /**
1657 \brief
1658 Compute a tensor product of two Data objects
1659 \param arg0 - Input - Data object
1660 \param arg1 - Input - Data object
1661 \param axis_offset - Input - axis offset
1662 \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1663 */
1664 ESCRIPT_DLL_API
1665 Data
1666 C_GeneralTensorProduct(Data& arg0,
1667 Data& arg1,
1668 int axis_offset=0,
1669 int transpose=0);
1670
1671 /**
1672 \brief
1673 Perform the given binary operation with this and right as operands.
1674 Right is a Data object.
1675 */
1676 template <class BinaryFunction>
1677 inline
1678 void
1679 Data::binaryOp(const Data& right,
1680 BinaryFunction operation)
1681 {
1682 //
1683 // if this has a rank of zero promote it to the rank of the RHS
1684 if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1685 throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1686 }
1687
1688 if (isLazy() || right.isLazy())
1689 {
1690 throw DataException("Programmer error - attempt to call binaryOp with Lazy Data.");
1691 }
1692 //
1693 // initially make the temporary a shallow copy
1694 Data tempRight(right);
1695
1696 if (getFunctionSpace()!=right.getFunctionSpace()) {
1697 if (right.probeInterpolation(getFunctionSpace())) {
1698 //
1699 // an interpolation is required so create a new Data
1700 tempRight=Data(right,this->getFunctionSpace());
1701 } else if (probeInterpolation(right.getFunctionSpace())) {
1702 //
1703 // interpolate onto the RHS function space
1704 Data tempLeft(*this,right.getFunctionSpace());
1705 m_data=tempLeft.m_data;
1706 }
1707 }
1708 operandCheck(tempRight);
1709 //
1710 // ensure this has the right type for the RHS
1711 typeMatchRight(tempRight);
1712 //
1713 // Need to cast to the concrete types so that the correct binaryOp
1714 // is called.
1715 if (isExpanded()) {
1716 //
1717 // Expanded data will be done in parallel, the right hand side can be
1718 // of any data type
1719 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1720 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1721 escript::binaryOp(*leftC,*(tempRight.getReady()),operation);
1722 } else if (isTagged()) {
1723 //
1724 // Tagged data is operated on serially, the right hand side can be
1725 // either DataConstant or DataTagged
1726 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1727 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1728 if (right.isTagged()) {
1729 DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get());
1730 EsysAssert((rightC!=0), "Programming error - casting to DataTagged.");
1731 escript::binaryOp(*leftC,*rightC,operation);
1732 } else {
1733 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1734 EsysAssert((rightC!=0), "Programming error - casting to DataConstant.");
1735 escript::binaryOp(*leftC,*rightC,operation);
1736 }
1737 } else if (isConstant()) {
1738 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1739 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1740 EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1741 escript::binaryOp(*leftC,*rightC,operation);
1742 }
1743 }
1744
1745 /**
1746 \brief
1747 Perform the given Data object reduction algorithm on this and return the result.
1748 Given operation combines each element of each data point, thus argument
1749 object (*this) is a rank n Data object, and returned object is a scalar.
1750 Calls escript::algorithm.
1751 */
1752 template <class BinaryFunction>
1753 inline
1754 double
1755 Data::algorithm(BinaryFunction operation, double initial_value) const
1756 {
1757 if (isExpanded()) {
1758 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1759 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1760 return escript::algorithm(*leftC,operation,initial_value);
1761 } else if (isTagged()) {
1762 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1763 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1764 return escript::algorithm(*leftC,operation,initial_value);
1765 } else if (isConstant()) {
1766 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1767 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1768 return escript::algorithm(*leftC,operation,initial_value);
1769 } else if (isEmpty()) {
1770 throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1771 } else if (isLazy()) {
1772 throw DataException("Error - Operations not permitted on instances of DataLazy.");
1773 } else {
1774 throw DataException("Error - Data encapsulates an unknown type.");
1775 }
1776 }
1777
1778 /**
1779 \brief
1780 Perform the given data point reduction algorithm on data and return the result.
1781 Given operation combines each element within each data point into a scalar,
1782 thus argument object is a rank n Data object, and returned object is a
1783 rank 0 Data object.
1784 Calls escript::dp_algorithm.
1785 */
1786 template <class BinaryFunction>
1787 inline
1788 Data
1789 Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1790 {
1791 if (isEmpty()) {
1792 throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1793 }
1794 else if (isExpanded()) {
1795 Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1796 DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1797 DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1798 EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1799 EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1800 escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1801 return result;
1802 }
1803 else if (isTagged()) {
1804 DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
1805 EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1806 DataTypes::ValueType defval(1);
1807 defval[0]=0;
1808 DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1809 escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1810 return Data(resultT); // note: the Data object now owns the resultT pointer
1811 }
1812 else if (isConstant()) {
1813 Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1814 DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1815 DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1816 EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1817 EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1818 escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1819 return result;
1820 } else if (isLazy()) {
1821 throw DataException("Error - Operations not permitted on instances of DataLazy.");
1822 } else {
1823 throw DataException("Error - Data encapsulates an unknown type.");
1824 }
1825 }
1826
1827 /**
1828 \brief
1829 Compute a tensor operation with two Data objects
1830 \param arg0 - Input - Data object
1831 \param arg1 - Input - Data object
1832 \param operation - Input - Binary op functor
1833 */
1834 template <typename BinaryFunction>
1835 inline
1836 Data
1837 C_TensorBinaryOperation(Data const &arg_0,
1838 Data const &arg_1,
1839 BinaryFunction operation)
1840 {
1841 if (arg_0.isEmpty() || arg_1.isEmpty())
1842 {
1843 throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1844 }
1845 if (arg_0.isLazy() || arg_1.isLazy())
1846 {
1847 throw DataException("Error - Operations not permitted on lazy data.");
1848 }
1849 // Interpolate if necessary and find an appropriate function space
1850 Data arg_0_Z, arg_1_Z;
1851 if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1852 if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1853 arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1854 arg_1_Z = Data(arg_1);
1855 }
1856 else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1857 arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1858 arg_0_Z =Data(arg_0);
1859 }
1860 else {
1861 throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1862 }
1863 } else {
1864 arg_0_Z = Data(arg_0);
1865 arg_1_Z = Data(arg_1);
1866 }
1867 // Get rank and shape of inputs
1868 int rank0 = arg_0_Z.getDataPointRank();
1869 int rank1 = arg_1_Z.getDataPointRank();
1870 DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1871 DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1872 int size0 = arg_0_Z.getDataPointSize();
1873 int size1 = arg_1_Z.getDataPointSize();
1874
1875 // Declare output Data object
1876 Data res;
1877
1878 if (shape0 == shape1) {
1879
1880 if (arg_0_Z.isConstant() && arg_1_Z.isConstant()) {
1881 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataConstant output
1882 /* double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1883 double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1884 double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1885 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1886 double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1887 double *ptr_2 = &(res.getDataAtOffset(0));
1888
1889 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1890 }
1891 else if (arg_0_Z.isConstant() && arg_1_Z.isTagged()) {
1892
1893 // Prepare the DataConstant input
1894 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1895
1896 // Borrow DataTagged input from Data object
1897 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1898
1899 // Prepare a DataTagged output 2
1900 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataTagged output
1901 res.tag();
1902 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1903
1904 // Prepare offset into DataConstant
1905 int offset_0 = tmp_0->getPointOffset(0,0);
1906 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1907 // Get the views
1908 // DataArrayView view_1 = tmp_1->getDefaultValue();
1909 // DataArrayView view_2 = tmp_2->getDefaultValue();
1910 // // Get the pointers to the actual data
1911 // double *ptr_1 = &((view_1.getData())[0]);
1912 // double *ptr_2 = &((view_2.getData())[0]);
1913
1914 // Get the pointers to the actual data
1915 double *ptr_1 = &(tmp_1->getDefaultValue(0));
1916 double *ptr_2 = &(tmp_2->getDefaultValue(0));
1917
1918 // Compute a result for the default
1919 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1920 // Compute a result for each tag
1921 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1922 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1923 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1924 tmp_2->addTag(i->first);
1925 /* DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1926 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1927 double *ptr_1 = &view_1.getData(0);
1928 double *ptr_2 = &view_2.getData(0);*/
1929 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1930 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1931
1932 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1933 }
1934
1935 }
1936 else if (arg_0_Z.isConstant() && arg_1_Z.isExpanded()) {
1937
1938 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1939 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1940 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1941 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1942
1943 int sampleNo_1,dataPointNo_1;
1944 int numSamples_1 = arg_1_Z.getNumSamples();
1945 int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1946 int offset_0 = tmp_0->getPointOffset(0,0);
1947 #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1948 for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1949 for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1950 int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1951 int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1952 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1953 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1954 // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1955
1956 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1957 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1958 double *ptr_2 = &(res.getDataAtOffset(offset_2));
1959 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1960 }
1961 }
1962
1963 }
1964 else if (arg_0_Z.isTagged() && arg_1_Z.isConstant()) {
1965
1966 // Borrow DataTagged input from Data object
1967 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1968
1969 // Prepare the DataConstant input
1970 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1971
1972 // Prepare a DataTagged output 2
1973 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataTagged output
1974 res.tag();
1975 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1976
1977 // Prepare offset into DataConstant
1978 int offset_1 = tmp_1->getPointOffset(0,0);
1979 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1980 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1981 // Get the views
1982 // DataArrayView view_0 = tmp_0->getDefaultValue();
1983 // DataArrayView view_2 = tmp_2->getDefaultValue();
1984 // // Get the pointers to the actual data
1985 // double *ptr_0 = &((view_0.getData())[0]);
1986 // double *ptr_2 = &((view_2.getData())[0]);
1987 // Get the pointers to the actual data
1988 double *ptr_0 = &(tmp_0->getDefaultValue(0));
1989 double *ptr_2 = &(tmp_2->getDefaultValue(0));
1990 // Compute a result for the default
1991 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1992 // Compute a result for each tag
1993 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1994 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1995 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1996 tmp_2->addTag(i->first);
1997 // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1998 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1999 // double *ptr_0 = &view_0.getData(0);
2000 // double *ptr_2 = &view_2.getData(0);
2001 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2002 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2003 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2004 }
2005
2006 }
2007 else if (arg_0_Z.isTagged() && arg_1_Z.isTagged()) {
2008
2009 // Borrow DataTagged input from Data object
2010 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2011
2012 // Borrow DataTagged input from Data object
2013 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2014
2015 // Prepare a DataTagged output 2
2016 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2017 res.tag(); // DataTagged output
2018 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2019
2020 // // Get the views
2021 // DataArrayView view_0 = tmp_0->getDefaultValue();
2022 // DataArrayView view_1 = tmp_1->getDefaultValue();
2023 // DataArrayView view_2 = tmp_2->getDefaultValue();
2024 // // Get the pointers to the actual data
2025 // double *ptr_0 = &((view_0.getData())[0]);
2026 // double *ptr_1 = &((view_1.getData())[0]);
2027 // double *ptr_2 = &((view_2.getData())[0]);
2028
2029 // Get the pointers to the actual data
2030 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2031 double *ptr_1 = &(tmp_1->getDefaultValue(0));
2032 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2033
2034 // Compute a result for the default
2035 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2036 // Merge the tags
2037 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2038 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2039 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2040 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2041 tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2042 }
2043 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2044 tmp_2->addTag(i->first);
2045 }
2046 // Compute a result for each tag
2047 const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2048 for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2049
2050 // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2051 // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2052 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2053 // double *ptr_0 = &view_0.getData(0);
2054 // double *ptr_1 = &view_1.getData(0);
2055 // double *ptr_2 = &view_2.getData(0);
2056
2057 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2058 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2059 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2060
2061 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2062 }
2063
2064 }
2065 else if (arg_0_Z.isTagged() && arg_1_Z.isExpanded()) {
2066
2067 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2068 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2069 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2070 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2071 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2072
2073 int sampleNo_0,dataPointNo_0;
2074 int numSamples_0 = arg_0_Z.getNumSamples();
2075 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2076 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2077 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2078 int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2079 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2080 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2081 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2082 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2083
2084 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2085 // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2086 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2087 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2088
2089
2090 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2091 }
2092 }
2093
2094 }
2095 else if (arg_0_Z.isExpanded() && arg_1_Z.isConstant()) {
2096
2097 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2098 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2099 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2100 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2101
2102 int sampleNo_0,dataPointNo_0;
2103 int numSamples_0 = arg_0_Z.getNumSamples();
2104 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2105 int offset_1 = tmp_1->getPointOffset(0,0);
2106 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2107 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2108 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2109 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2110 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2111
2112 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2113 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2114 // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2115
2116 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2117 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2118 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2119
2120
2121 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2122 }
2123 }
2124
2125 }
2126 else if (arg_0_Z.isExpanded() && arg_1_Z.isTagged()) {
2127
2128 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2129 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2130 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2131 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2132 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2133
2134 int sampleNo_0,dataPointNo_0;
2135 int numSamples_0 = arg_0_Z.getNumSamples();
2136 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2137 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2138 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2139 int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2140 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2141 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2142 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2143 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2144 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2145 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2146 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2147 }
2148 }
2149
2150 }
2151 else if (arg_0_Z.isExpanded() && arg_1_Z.isExpanded()) {
2152
2153 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2154 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2155 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2156 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2157 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2158
2159 int sampleNo_0,dataPointNo_0;
2160 int numSamples_0 = arg_0_Z.getNumSamples();
2161 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2162 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2163 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2164 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2165 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2166 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2167 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2168 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2169 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2170 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2171 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2172 }
2173 }
2174
2175 }
2176 else {
2177 throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2178 }
2179
2180 } else if (0 == rank0) {
2181
2182 if (arg_0_Z.isConstant() && arg_1_Z.isConstant()) {
2183 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace()); // DataConstant output
2184 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2185 double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2186 double *ptr_2 = &(res.getDataAtOffset(0));
2187 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2188 }
2189 else if (arg_0_Z.isConstant() && arg_1_Z.isTagged()) {
2190
2191 // Prepare the DataConstant input
2192 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2193
2194 // Borrow DataTagged input from Data object
2195 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2196
2197 // Prepare a DataTagged output 2
2198 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace()); // DataTagged output
2199 res.tag();
2200 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2201
2202 // Prepare offset into DataConstant
2203 int offset_0 = tmp_0->getPointOffset(0,0);
2204 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2205 // Get the views
2206 // DataArrayView view_1 = tmp_1->getDefaultValue();
2207 // DataArrayView view_2 = tmp_2->getDefaultValue();
2208 // // Get the pointers to the actual data
2209 // double *ptr_1 = &((view_1.getData())[0]);
2210 // double *ptr_2 = &((view_2.getData())[0]);
2211 double *ptr_1 = &(tmp_1->getDefaultValue(0));
2212 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2213
2214 // Compute a result for the default
2215 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2216 // Compute a result for each tag
2217 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2218 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2219 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2220 tmp_2->addTag(i->first);
2221 // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2222 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2223 // double *ptr_1 = &view_1.getData(0);
2224 // double *ptr_2 = &view_2.getData(0);
2225 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2226 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2227 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2228 }
2229
2230 }
2231 else if (arg_0_Z.isConstant() && arg_1_Z.isExpanded()) {
2232
2233 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2234 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2235 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2236 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2237
2238 int sampleNo_1,dataPointNo_1;
2239 int numSamples_1 = arg_1_Z.getNumSamples();
2240 int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2241 int offset_0 = tmp_0->getPointOffset(0,0);
2242 #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2243 for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2244 for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2245 int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2246 int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2247 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2248 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2249 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2250 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2251
2252 }
2253 }
2254
2255 }
2256 else if (arg_0_Z.isTagged() && arg_1_Z.isConstant()) {
2257
2258 // Borrow DataTagged input from Data object
2259 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2260
2261 // Prepare the DataConstant input
2262 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2263
2264 // Prepare a DataTagged output 2
2265 res = Data(0.0, shape1, arg_0_Z.getFunctionSpace()); // DataTagged output
2266 res.tag();
2267 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2268
2269 // Prepare offset into DataConstant
2270 int offset_1 = tmp_1->getPointOffset(0,0);
2271 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2272 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2273 // Get the views
2274 /* DataArrayView view_0 = tmp_0->getDefaultValue();
2275 DataArrayView view_2 = tmp_2->getDefaultValue();
2276 // Get the pointers to the actual data
2277 double *ptr_0 = &((view_0.getData())[0]);
2278 double *ptr_2 = &((view_2.getData())[0]);*/
2279
2280 // Get the pointers to the actual data
2281 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2282 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2283
2284
2285 // Compute a result for the default
2286 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2287 // Compute a result for each tag
2288 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2289 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2290 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2291 tmp_2->addTag(i->first);
2292 /* DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2293 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2294 double *ptr_0 = &view_0.getData(0);
2295 double *ptr_2 = &view_2.getData(0);*/
2296 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2297 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2298
2299 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2300 }
2301
2302 }
2303 else if (arg_0_Z.isTagged() && arg_1_Z.isTagged()) {
2304
2305 // Borrow DataTagged input from Data object
2306 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2307
2308 // Borrow DataTagged input from Data object
2309 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2310
2311 // Prepare a DataTagged output 2
2312 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2313 res.tag(); // DataTagged output
2314 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2315
2316 // Get the views
2317 /* DataArrayView view_0 = tmp_0->getDefaultValue();
2318 DataArrayView view_1 = tmp_1->getDefaultValue();
2319 DataArrayView view_2 = tmp_2->getDefaultValue();
2320 // Get the pointers to the actual data
2321 double *ptr_0 = &((view_0.getData())[0]);
2322 double *ptr_1 = &((view_1.getData())[0]);
2323 double *ptr_2 = &((view_2.getData())[0]);*/
2324
2325 // Get the pointers to the actual data
2326 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2327 double *ptr_1 = &(tmp_1->getDefaultValue(0));
2328 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2329
2330
2331 // Compute a result for the default
2332 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2333 // Merge the tags
2334 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2335 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2336 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2337 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2338 tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2339 }
2340 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2341 tmp_2->addTag(i->first);
2342 }
2343 // Compute a result for each tag
2344 const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2345 for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2346
2347 /* DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2348 DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2349 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2350 double *ptr_0 = &view_0.getData(0);
2351 double *ptr_1 = &view_1.getData(0);
2352 double *ptr_2 = &view_2.getData(0);*/
2353
2354 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2355 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2356 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2357
2358 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2359 }
2360
2361 }
2362 else if (arg_0_Z.isTagged() && arg_1_Z.isExpanded()) {
2363
2364 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2365 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2366 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2367 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2368 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2369
2370 int sampleNo_0,dataPointNo_0;
2371 int numSamples_0 = arg_0_Z.getNumSamples();
2372 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2373 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2374 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2375 int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2376 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2377 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2378 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2379 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2380 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2381 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2382 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2383 }
2384 }
2385
2386 }
2387 else if (arg_0_Z.isExpanded() && arg_1_Z.isConstant()) {
2388
2389 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2390 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2391 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2392 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2393
2394 int sampleNo_0,dataPointNo_0;
2395 int numSamples_0 = arg_0_Z.getNumSamples();
2396 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2397 int offset_1 = tmp_1->getPointOffset(0,0);
2398 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2399 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2400 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2401 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2402 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2403 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2404 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2405 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2406 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2407 }
2408 }
2409
2410
2411 }
2412 else if (arg_0_Z.isExpanded() && arg_1_Z.isTagged()) {
2413
2414 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2415 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2416 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2417 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2418 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2419
2420 int sampleNo_0,dataPointNo_0;
2421 int numSamples_0 = arg_0_Z.getNumSamples();
2422 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2423 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2424 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2425 int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2426 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2427 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2428 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2429 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2430 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2431 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2432 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2433 }
2434 }
2435
2436 }
2437 else if (arg_0_Z.isExpanded() && arg_1_Z.isExpanded()) {
2438
2439 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2440 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2441 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2442 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2443 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2444
2445 int sampleNo_0,dataPointNo_0;
2446 int numSamples_0 = arg_0_Z.getNumSamples();
2447 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2448 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2449 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2450 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2451 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2452 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2453 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2454 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2455 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2456 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2457 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2458 }
2459 }
2460
2461 }
2462 else {
2463 throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2464 }
2465
2466 } else if (0 == rank1) {
2467
2468 if (arg_0_Z.isConstant() && arg_1_Z.isConstant()) {
2469 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataConstant output
2470 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2471 double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2472 double *ptr_2 = &(res.getDataAtOffset(0));
2473 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2474 }
2475 else if (arg_0_Z.isConstant() && arg_1_Z.isTagged()) {
2476
2477 // Prepare the DataConstant input
2478 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2479
2480 // Borrow DataTagged input from Data object
2481 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2482
2483 // Prepare a DataTagged output 2
2484 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataTagged output
2485 res.tag();
2486 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2487
2488 // Prepare offset into DataConstant
2489 int offset_0 = tmp_0->getPointOffset(0,0);
2490 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2491 // Get the views
2492 /* DataArrayView view_1 = tmp_1->getDefaultValue();
2493 DataArrayView view_2 = tmp_2->getDefaultValue();
2494 // Get the pointers to the actual data
2495 double *ptr_1 = &((view_1.getData())[0]);
2496 double *ptr_2 = &((view_2.getData())[0]);*/
2497 //Get the pointers to the actual data
2498 double *ptr_1 = &(tmp_1->getDefaultValue(0));
2499 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2500
2501 // Compute a result for the default
2502 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2503 // Compute a result for each tag
2504 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2505 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2506 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2507 tmp_2->addTag(i->first);
2508 // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2509 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2510 // double *ptr_1 = &view_1.getData(0);
2511 // double *ptr_2 = &view_2.getData(0);
2512 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2513 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2514
2515
2516 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2517 }
2518
2519 }
2520 else if (arg_0_Z.isConstant() && arg_1_Z.isExpanded()) {
2521
2522 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2523 DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2524 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2525 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2526
2527 int sampleNo_1,dataPointNo_1;
2528 int numSamples_1 = arg_1_Z.getNumSamples();
2529 int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2530 int offset_0 = tmp_0->getPointOffset(0,0);
2531 #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2532 for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2533 for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2534 int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2535 int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2536 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2537 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2538 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2539 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2540 }
2541 }
2542
2543 }
2544 else if (arg_0_Z.isTagged() && arg_1_Z.isConstant()) {
2545
2546 // Borrow DataTagged input from Data object
2547 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2548
2549 // Prepare the DataConstant input
2550 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2551
2552 // Prepare a DataTagged output 2
2553 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataTagged output
2554 res.tag();
2555 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2556
2557 // Prepare offset into DataConstant
2558 int offset_1 = tmp_1->getPointOffset(0,0);
2559 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2560 // Get the views
2561 // DataArrayView view_0 = tmp_0->getDefaultValue();
2562 // DataArrayView view_2 = tmp_2->getDefaultValue();
2563 // // Get the pointers to the actual data
2564 // double *ptr_0 = &((view_0.getData())[0]);
2565 // double *ptr_2 = &((view_2.getData())[0]);
2566 // Get the pointers to the actual data
2567 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2568 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2569 // Compute a result for the default
2570 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2571 // Compute a result for each tag
2572 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2573 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2574 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2575 tmp_2->addTag(i->first);
2576 /* DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2577 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2578 double *ptr_0 = &view_0.getData(0);
2579 double *ptr_2 = &view_2.getData(0);*/
2580 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2581 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2582 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2583 }
2584
2585 }
2586 else if (arg_0_Z.isTagged() && arg_1_Z.isTagged()) {
2587
2588 // Borrow DataTagged input from Data object
2589 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2590
2591 // Borrow DataTagged input from Data object
2592 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2593
2594 // Prepare a DataTagged output 2
2595 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2596 res.tag(); // DataTagged output
2597 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2598
2599 // Get the views
2600 // DataArrayView view_0 = tmp_0->getDefaultValue();
2601 // DataArrayView view_1 = tmp_1->getDefaultValue();
2602 // DataArrayView view_2 = tmp_2->getDefaultValue();
2603 // // Get the pointers to the actual data
2604 // double *ptr_0 = &((view_0.getData())[0]);
2605 // double *ptr_1 = &((view_1.getData())[0]);
2606 // double *ptr_2 = &((view_2.getData())[0]);
2607
2608 // Get the pointers to the actual data
2609 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2610 double *ptr_1 = &(tmp_1->getDefaultValue(0));
2611 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2612
2613 // Compute a result for the default
2614 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2615 // Merge the tags
2616 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2617 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2618 const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2619 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2620 tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2621 }
2622 for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2623 tmp_2->addTag(i->first);
2624 }
2625 // Compute a result for each tag
2626 const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2627 for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2628 // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2629 // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2630 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2631 // double *ptr_0 = &view_0.getData(0);
2632 // double *ptr_1 = &view_1.getData(0);
2633 // double *ptr_2 = &view_2.getData(0);
2634
2635 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2636 double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2637 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2638 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2639 }
2640
2641 }
2642 else if (arg_0_Z.isTagged() && arg_1_Z.isExpanded()) {
2643
2644 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2645 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2646 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2647 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2648 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2649
2650 int sampleNo_0,dataPointNo_0;
2651 int numSamples_0 = arg_0_Z.getNumSamples();
2652 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2653 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2654 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2655 int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2656 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2657 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2658 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2659 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2660 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2661 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2662 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2663 }
2664 }
2665
2666 }
2667 else if (arg_0_Z.isExpanded() && arg_1_Z.isConstant()) {
2668
2669 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2670 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2671 DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2672 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2673
2674 int sampleNo_0,dataPointNo_0;
2675 int numSamples_0 = arg_0_Z.getNumSamples();
2676 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2677 int offset_1 = tmp_1->getPointOffset(0,0);
2678 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2679 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2680 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2681 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2682 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2683 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2684 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2685 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2686 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2687 }
2688 }
2689
2690
2691 }
2692 else if (arg_0_Z.isExpanded() && arg_1_Z.isTagged()) {
2693
2694 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2695 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2696 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2697 DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2698 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2699
2700 int sampleNo_0,dataPointNo_0;
2701 int numSamples_0 = arg_0_Z.getNumSamples();
2702 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2703 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2704 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2705 int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2706 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2707 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2708 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2709 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2710 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2711 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2712 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2713 }
2714 }
2715
2716 }
2717 else if (arg_0_Z.isExpanded() && arg_1_Z.isExpanded()) {
2718
2719 // After finding a common function space above the two inputs have the same numSamples and num DPPS
2720 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2721 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2722 DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2723 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2724
2725 int sampleNo_0,dataPointNo_0;
2726 int numSamples_0 = arg_0_Z.getNumSamples();
2727 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2728 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2729 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2730 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2731 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2732 int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2733 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2734 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2735 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2736 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2737 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2738 }
2739 }
2740
2741 }
2742 else {
2743 throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2744 }
2745
2746 } else {
2747 throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2748 }
2749
2750 return res;
2751 }
2752
2753 template <typename UnaryFunction>
2754 Data
2755 C_TensorUnaryOperation(Data const &arg_0,
2756 UnaryFunction operation)
2757 {
2758 if (arg_0.isEmpty()) // do this before we attempt to interpolate
2759 {
2760 throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2761 }
2762 if (arg_0.isLazy())
2763 {
2764 throw DataException("Error - Operations not permitted on lazy data.");
2765 }
2766 // Interpolate if necessary and find an appropriate function space
2767 Data arg_0_Z = Data(arg_0);
2768
2769 // Get rank and shape of inputs
2770 int rank0 = arg_0_Z.getDataPointRank();
2771 const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2772 int size0 = arg_0_Z.getDataPointSize();
2773
2774 // Declare output Data object
2775 Data res;
2776
2777 if (arg_0_Z.isConstant()) {
2778 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataConstant output
2779 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2780 // double *ptr_2 = &((res.getPointDataView().getData())[0]);
2781 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2782 double *ptr_2 = &(res.getDataAtOffset(0));
2783 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2784 }
2785 else if (arg_0_Z.isTagged()) {
2786
2787 // Borrow DataTagged input from Data object
2788 DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2789
2790 // Prepare a DataTagged output 2
2791 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataTagged output
2792 res.tag();
2793 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2794
2795 // // Get the views
2796 // DataArrayView view_0 = tmp_0->getDefaultValue();
2797 // DataArrayView view_2 = tmp_2->getDefaultValue();
2798 // // Get the pointers to the actual data
2799 // double *ptr_0 = &((view_0.getData())[0]);
2800 // double *ptr_2 = &((view_2.getData())[0]);
2801 // Get the pointers to the actual data
2802 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2803 double *ptr_2 = &(tmp_2->getDefaultValue(0));
2804 // Compute a result for the default
2805 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2806 // Compute a result for each tag
2807 const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2808 DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2809 for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2810 tmp_2->addTag(i->first);
2811 // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2812 // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2813 // double *ptr_0 = &view_0.getData(0);
2814 // double *ptr_2 = &view_2.getData(0);
2815 double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2816 double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2817 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2818 }
2819
2820 }
2821 else if (arg_0_Z.isExpanded()) {
2822
2823 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2824 DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2825 DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2826
2827 int sampleNo_0,dataPointNo_0;
2828 int numSamples_0 = arg_0_Z.getNumSamples();
2829 int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2830 #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2831 for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2832 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2833 // int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2834 // int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2835 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2836 // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2837 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2838 int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2839 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2840 double *ptr_2 = &(res.getDataAtOffset(offset_2));
2841 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2842 }
2843 }
2844 }
2845 else {
2846 throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2847 }
2848
2849 return res;
2850 }
2851
2852 }
2853 #endif

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26