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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26