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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1889 - (show annotations)
Thu Oct 16 05:57:09 2008 UTC (10 years, 11 months ago) by jfenwick
File MIME type: text/plain
File size: 89743 byte(s)
Branch commit
Rewrote resolve to take into account Tagged and Constant Data.
Mixing expanded and Tagged does not work yet.

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26