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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26