/[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 1899 - (show annotations)
Mon Oct 20 05:13:24 2008 UTC (10 years, 6 months ago) by jfenwick
File MIME type: text/plain
File size: 89875 byte(s)
Branch commit.
Added some doco to DataLazy.
Made Data::integrate aware of DataLazy.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26