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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.698  
changed lines
  Added in v.1802

  ViewVC Help
Powered by ViewVC 1.1.26