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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2212 - (show annotations)
Wed Jan 14 00:15:00 2009 UTC (10 years, 3 months ago) by jfenwick
File MIME type: text/plain
File size: 94043 byte(s)
Executive summary:

This commit adds copy on write checks to operations involving shared data. 

Changes:

new #defines:
~~~~~~~~~~~~~
Data.cpp has ASSIGNMENT_MEANS_DEEPCOPY (defaults to undefined).
Defining this will put the data = operator back to making deep copies instead
of sharing data (now the default.)

Data:
~~~~~
. Added exclusiveWrite method to copy the underlying data if it is shared.
. Some operators which took python objects now call the c++ versions intead of duplicating code.

DataAbstract and offspring:
~~~~~~~~~~~~~~~~~~~~~~~~~~~
. Added method to determine whether the data is currently shared.
. Added getVectorRO to children of DataReady.
. Added getTagRO.

. Operations which modify values in place (or return modifiable pointers) now use
a macro to check for sharing. In the case where a modification attempt is detected, it throws an exception. In the future, I will enable this only for debugging.

. This shold not really have been required but the compiler was not choosing the use the const version as I would have liked. Besides, this makes things explict.

. Moved (and de-inlined) getVector in DataConstant (It was virtual in a parent class).

Unit tests:
~~~~~~~~~~~
Added both python and c++ unit tests to check known cases of sharing and "inplace"
modification operations.

General:
~~~~~~~~
Removed some commented out code.

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26