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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2143 - (show annotations)
Tue Dec 9 06:28:10 2008 UTC (12 years, 4 months ago) by jfenwick
File MIME type: text/plain
File size: 94566 byte(s)
Branch commit.
Added scons option usenumarray (defaults to yes).
This controls the NONUMARRAY define which switches off all explicit 
references to boost::python::numeric::array

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26