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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26