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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1752 - (show annotations)
Fri Sep 5 06:26:29 2008 UTC (10 years, 8 months ago) by jfenwick
File MIME type: text/plain
File size: 89765 byte(s)
Branch commit

Now passes all c++ unit tests but fails some python ones.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26