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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26