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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1803 - (show annotations)
Wed Sep 24 06:20:29 2008 UTC (10 years, 11 months ago) by jfenwick
File MIME type: text/plain
File size: 87960 byte(s)
All about making DataEmpty instances throw.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Exposed getDim from AbstractDomain to python to fix bug.

Added isEmpty member to DataAbstract to allow it to throw is queries are 
made about a DataEmpty instance.


Added exceptions to DataAbstract, DataEmpty and Data to prevent calls 
being made against DataEmpty objects.
The following still work as expected on DataEmpty instances

copy, getDomain, getFunctionSpace, isEmpty, isExpanded, isProtected, 
isTagged, setprotection.

You can also call interpolate, however it should throw if you try to 
change FunctionSpaces.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26