/[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 1802 - (show annotations)
Tue Sep 23 01:03:29 2008 UTC (11 years, 1 month ago) by jfenwick
Original Path: trunk/escript/src/Data.h
File MIME type: text/plain
File size: 88014 byte(s)
Added canTag methods to FunctionSpace and AbstractDomain (and its 
offspring).
This checks to see if the domain supports tags for the given type of 
function space.

Constructors for DataTagged now throw exceptions if you attempt to make 
a DataTagged with a FunctionSpace which does not support tags.
To allow the default constructor to work, NullDomain has a single 
functioncode which "supports" tagging.

Fixed a bug in DataTagged::toString and DataTypes::pointToString.

Added FunctionSpace::getListOfTagsSTL.

algorithm(DataTagged, BinaryFunction) in DataAlgorithm now only 
processes tags known to be in use.
This fixes mantis issue #0000186.

Added comment to Data.h intro warning about holding references if the 
underlying DataAbstract changes.

_python_ unit tests have been updated to test TaggedData with invalid 
FunctionSpaces and to give the correct answers to Lsup etc.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26