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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26