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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26