/[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 1901 - (show annotations)
Wed Oct 22 02:44:34 2008 UTC (11 years, 9 months ago) by jfenwick
File MIME type: text/plain
File size: 90033 byte(s)
Improved the api_doxygen target a bit.
Added some documentation.
Added FORCERESOLVE macro to a number of operations.

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26