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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26