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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1796 - (hide annotations)
Wed Sep 17 01:45:46 2008 UTC (11 years, 2 months ago) by jfenwick
Original Path: trunk/escript/src/Data.h
File MIME type: text/plain
File size: 87757 byte(s)
Merged noarrayview branch onto trunk.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26