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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2221 - (show annotations)
Mon Jan 19 06:11:25 2009 UTC (10 years, 6 months ago) by jfenwick
File MIME type: text/plain
File size: 95833 byte(s)
A second attempt at a thread-safe COW

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26