/[escript]/trunk/escript/src/Data.h
ViewVC logotype

Contents of /trunk/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3259 - (show annotations)
Mon Oct 11 01:48:14 2010 UTC (8 years, 10 months ago) by jfenwick
File MIME type: text/plain
File size: 92595 byte(s)
Merging dudley and scons updates from branches

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26