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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1889 - (hide annotations)
Thu Oct 16 05:57:09 2008 UTC (11 years ago) by jfenwick
File MIME type: text/plain
File size: 89743 byte(s)
Branch commit
Rewrote resolve to take into account Tagged and Constant Data.
Mixing expanded and Tagged does not work yet.

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26