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

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

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

revision 1092 by gross, Fri Apr 13 03:39:49 2007 UTC revision 1799 by jfenwick, Wed Sep 17 06:33:18 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    
# Line 23  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"  /* #include "paso/Paso.h" doesn't belong in this file...causes trouble for BruceFactory.cpp */
33  }  }
34    
35  #ifndef PASO_MPI  #include "esysmpi.h"
 #define MPI_Comm long  
 #endif  
   
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 51  class DataExpanded; Line 53  class DataExpanded;
53    
54  /**  /**
55     \brief     \brief
56     Data creates the appropriate Data object for the given construction     Data creates the appropriate Data object for the given construction
57     arguments.     arguments.
58    
59     Description:     Description:
60     Data is essentially a factory class which creates the appropriate Data     Data is essentially a factory class which creates the appropriate Data
# Line 102  class Data { Line 104  class Data {
104         const FunctionSpace& what);         const FunctionSpace& what);
105    
106    /**    /**
107       \brief      \brief Copy Data from an existing vector
108       Constructor which copies data from a DataArrayView.    */
109    
      \param value - Input - Data value for a single point.  
      \param what - Input - A description of what this data represents.  
      \param expanded - Input - Flag, if true fill the entire container with  
                        the value. Otherwise a more efficient storage  
                        mechanism will be used.  
   */  
110    ESCRIPT_DLL_API    ESCRIPT_DLL_API
111    Data(const DataArrayView& value,    Data(const DataTypes::ValueType& value,
112         const FunctionSpace& what=FunctionSpace(),           const DataTypes::ShapeType& shape,
113         bool expanded=false);                   const FunctionSpace& what=FunctionSpace(),
114                     bool expanded=false);
115    
116    /**    /**
117       \brief       \brief
# Line 129  class Data { Line 126  class Data {
126    */    */
127    ESCRIPT_DLL_API    ESCRIPT_DLL_API
128    Data(double value,    Data(double value,
129         const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(),         const DataTypes::ShapeType& dataPointShape=DataTypes::ShapeType(),
130         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
131         bool expanded=false);         bool expanded=false);
132    
# Line 142  class Data { Line 139  class Data {
139    */    */
140    ESCRIPT_DLL_API    ESCRIPT_DLL_API
141    Data(const Data& inData,    Data(const Data& inData,
142         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.  
     ==>*  
   */  
   ESCRIPT_DLL_API  
   Data(const DataTagged::TagListType& tagKeys,  
        const DataTagged::ValueListType& values,  
        const DataArrayView& defaultValue,  
        const FunctionSpace& what=FunctionSpace(),  
        bool expanded=false);  
143    
144    /**    /**
145       \brief       \brief
# Line 214  class Data { Line 190  class Data {
190       Constructor which creates a DataConstant of "shape" with constant value.       Constructor which creates a DataConstant of "shape" with constant value.
191    */    */
192    ESCRIPT_DLL_API    ESCRIPT_DLL_API
193    Data(double value,    Data(double value,
194         const boost::python::tuple& shape=boost::python::make_tuple(),         const boost::python::tuple& shape=boost::python::make_tuple(),
195         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
196         bool expanded=false);         bool expanded=false);
197    
198    
199    
200      /**
201        \brief Create a Data using an existing DataAbstract. Warning: The new object assumes ownership of the pointer!
202        Once you have passed the pointer, do not delete it.
203      */
204      ESCRIPT_DLL_API
205      Data(DataAbstract* underlyingdata);
206    
207    
208    /**    /**
209       \brief       \brief
210       Destructor       Destructor
# Line 226  class Data { Line 213  class Data {
213    ~Data();    ~Data();
214    
215    /**    /**
216       \brief       \brief Make this object a deep copy of "other".
      Perform a deep copy.  
217    */    */
218    ESCRIPT_DLL_API    ESCRIPT_DLL_API
219    void    void
220    copy(const Data& other);    copy(const Data& other);
221    
222    /**    /**
223         \brief Return a pointer to a deep copy of this object.
224      */
225      ESCRIPT_DLL_API
226      Data*
227      copySelf();
228    
229    
230    
231    
232      /**
233       Member access methods.       Member access methods.
234    */    */
235    
236    /**    /**
237       \brief       \brief
238       switches on update protection       switches on update protection
239    
240    */    */
241    ESCRIPT_DLL_API    ESCRIPT_DLL_API
# Line 257  class Data { Line 253  class Data {
253    
254    /**    /**
255       \brief       \brief
256       Return the values of a data point on this process       Return the values of a data point on this process
257    */    */
258    ESCRIPT_DLL_API    ESCRIPT_DLL_API
259    const boost::python::numeric::array    const boost::python::numeric::array
# Line 299  class Data { Line 295  class Data {
295       \brief       \brief
296       Return the tag number associated with the given data-point.       Return the tag number associated with the given data-point.
297    
      The data-point number here corresponds to the data-point number in the  
      numarray returned by convertToNumArray.  
298    */    */
299    ESCRIPT_DLL_API    ESCRIPT_DLL_API
300    int    int
# Line 314  class Data { Line 308  class Data {
308    escriptDataC    escriptDataC
309    getDataC();    getDataC();
310    
311    
312    
313    
314    
315    
316    // REMOVE ME
317    // ESCRIPT_DLL_API
318    // void
319    // CompareDebug(const Data& rd);
320    
321    
322    /**    /**
323       \brief       \brief
324       Return the C wrapper for the Data object - const version.       Return the C wrapper for the Data object - const version.
# Line 324  class Data { Line 329  class Data {
329    
330    /**    /**
331       \brief       \brief
332       Write the data as a string.       Write the data as a string. For large amounts of data, a summary is printed.
333    */    */
334    ESCRIPT_DLL_API    ESCRIPT_DLL_API
   inline  
335    std::string    std::string
336    toString() const    toString() const;
   {  
     return m_data->toString();  
   }  
337    
338    /**  
339       \brief  //  /**
340    /*     \brief
341       Return the DataArrayView of the point data. This essentially contains       Return the DataArrayView of the point data. This essentially contains
342       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
343       to manipulate the point data.       to manipulate the point data.*/
344    */  //  */
345    ESCRIPT_DLL_API  //   ESCRIPT_DLL_API
346    inline  //   inline
347    const DataArrayView&  //   const DataArrayView&
348    getPointDataView() const  //   getPointDataView() const
349    {  //   {
350       return m_data->getPointDataView();  //      return m_data->getPointDataView();
351    }  //   }
352    
353    /**    /**
354       \brief       \brief
# Line 448  class Data { Line 450  class Data {
450    int    int
451    getDataPointRank() const    getDataPointRank() const
452    {    {
453      return m_data->getPointDataView().getRank();  //    return m_data->getPointDataView().getRank();
454        return m_data->getRank();
455    }    }
456    
457    /**    /**
# Line 485  class Data { Line 488  class Data {
488    {    {
489      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
490    }    }
491    
492    
493    /**    /**
494       \brief      \brief
495       dumps the object into a netCDF file      Return the number of values in the shape for this object.
496    */    */
497    ESCRIPT_DLL_API    ESCRIPT_DLL_API
498    inline    int
499    void    getNoValues() const
   dump(const std::string fileName) const  
500    {    {
501      return m_data->dump(fileName);      return m_data->getNoValues();
502    }    }
503    
504    
505      /**
506         \brief
507         dumps the object into a netCDF file
508      */
509      ESCRIPT_DLL_API
510      void
511      dump(const std::string fileName) const;
512    /**    /**
513       \brief       \brief
514       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
# Line 525  class Data { Line 537  class Data {
537      return m_data->getSampleDataByTag(tag);      return m_data->getSampleDataByTag(tag);
538    }    }
539    
540    //  /**
541    /*     \brief
542         Return a view into the data for the data point specified.
543         NOTE: Construction of the DataArrayView is a relatively expensive
544         operation.
545         \param sampleNo - Input -
546         \param dataPointNo - Input -*/
547    //  */
548    //   ESCRIPT_DLL_API
549    //   inline
550    //   DataArrayView
551    //   getDataPoint(int sampleNo,
552    //                int dataPointNo)
553    //   {
554    //                 return m_data->getDataPoint(sampleNo,dataPointNo);
555    //   }
556    
557    
558    /**    /**
559       \brief       \brief
560       Return a view into the data for the data point specified.       Return a view into the data for the data point specified.
# Line 534  class Data { Line 564  class Data {
564       \param dataPointNo - Input -       \param dataPointNo - Input -
565    */    */
566    ESCRIPT_DLL_API    ESCRIPT_DLL_API
567      DataTypes::ValueType::const_reference
568      getDataPoint(int sampleNo, int dataPointNo) const;
569    
570    
571      ESCRIPT_DLL_API
572      DataTypes::ValueType::reference
573      getDataPoint(int sampleNo, int dataPointNo);
574    
575    
576    
577      /**
578         \brief
579         Return the offset for the given sample and point within the sample
580      */
581      ESCRIPT_DLL_API
582    inline    inline
583    DataArrayView    DataTypes::ValueType::size_type
584    getDataPoint(int sampleNo,    getDataOffset(int sampleNo,
585                 int dataPointNo)                 int dataPointNo)
586    {    {
587          return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getPointOffset(sampleNo,dataPointNo);
588    }    }
589    
590    /**    /**
# Line 547  class Data { Line 592  class Data {
592       Return a reference to the data point shape.       Return a reference to the data point shape.
593    */    */
594    ESCRIPT_DLL_API    ESCRIPT_DLL_API
595    const DataArrayView::ShapeType&    inline
596    getDataPointShape() const;    const DataTypes::ShapeType&
597      getDataPointShape() const
598      {
599        return m_data->getShape();
600      }
601    
602    /**    /**
603       \brief       \brief
# Line 572  class Data { Line 621  class Data {
621       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
622    */    */
623    ESCRIPT_DLL_API    ESCRIPT_DLL_API
624    DataArrayView::ValueType::size_type    DataTypes::ValueType::size_type
625    getLength() const;    getLength() const;
626    
627    
# Line 594  class Data { Line 643  class Data {
643    /**    /**
644       \brief       \brief
645       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
646       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
647       cannot be converted to a DataTagged object.  
648       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
649       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
650      ==>*      ==>*
# Line 605  class Data { Line 654  class Data {
654    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
655                   const boost::python::object& value);                   const boost::python::object& value);
656    
657    
658    //  /**
659    //     \brief
660    //     Assign the given value to the tag. Implicitly converts this
661    //     object to type DataTagged if it is constant.
662    //
663    //     \param tagKey - Input - Integer key.
664    //     \param value - Input - Value to associate with given key.
665    //    ==>*
666    //  */
667    //   ESCRIPT_DLL_API
668    //   void
669    //   setTaggedValueFromCPP(int tagKey,
670    //                         const DataArrayView& value);
671    
672    /**    /**
673       \brief       \brief
674       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
675       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
676       cannot be converted to a DataTagged object.  
677       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
678         \param pointshape - Input - The shape of the value parameter
679       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
680      ==>*       \param dataOffset - Input - Offset of the begining of the point within the value parameter
681    */    */
682    ESCRIPT_DLL_API    ESCRIPT_DLL_API
683    void    void
684    setTaggedValueFromCPP(int tagKey,    setTaggedValueFromCPP(int tagKey,
685                          const DataArrayView& value);              const DataTypes::ShapeType& pointshape,
686                            const DataTypes::ValueType& value,
687                int dataOffset=0);
688    
689    
690    
691    /**    /**
692      \brief      \brief
# Line 634  class Data { Line 703  class Data {
703    
704    /**    /**
705       \brief       \brief
706         set all values to zero
707         *
708      */
709      ESCRIPT_DLL_API
710      void
711      setToZero();
712    
713      /**
714         \brief
715       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
716       the result as a Data object.       the result as a Data object.
717       *       *
# Line 641  class Data { Line 719  class Data {
719    ESCRIPT_DLL_API    ESCRIPT_DLL_API
720    Data    Data
721    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
722    /**    /**
723       \brief       \brief
724       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
# Line 738  class Data { Line 815  class Data {
815    
816    /**    /**
817       \brief       \brief
      Return the minimum absolute value of this Data object.  
      *  
   */  
   ESCRIPT_DLL_API  
   double  
   Linf() const;  
   
   /**  
      \brief  
818       Return the maximum value of this Data object.       Return the maximum value of this Data object.
819       *       *
820    */    */
# Line 861  class Data { Line 929  class Data {
929    /**    /**
930       \brief       \brief
931       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.
932       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
933       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
934       first non-zero entry is positive.       first non-zero entry is positive.
935       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
936       *       *
# Line 1066  class Data { Line 1134  class Data {
1134    /**    /**
1135       \brief       \brief
1136       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.
1137        
1138       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1139       *       *
1140     */     */
# Line 1077  class Data { Line 1145  class Data {
1145    /**    /**
1146       \brief       \brief
1147       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.
1148        
1149       \param left Input - the bases       \param left Input - the bases
1150       *       *
1151     */     */
# Line 1113  class Data { Line 1181  class Data {
1181    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1182    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1183    
1184      ESCRIPT_DLL_API
1185      Data& operator=(const Data& other);
1186    
1187    /**    /**
1188       \brief       \brief
1189       Overloaded operator -=       Overloaded operator -=
# Line 1205  class Data { Line 1276  class Data {
1276    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1277    inline    inline
1278    void    void
1279    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1280    
1281    /**    /**
1282       \brief       \brief
# Line 1216  class Data { Line 1287  class Data {
1287    */    */
1288    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1289    Data    Data
1290    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataTypes::RegionType& region) const;
1291    
1292    /**    /**
1293       \brief       \brief
# Line 1229  class Data { Line 1300  class Data {
1300    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1301    void    void
1302    setSlice(const Data& value,    setSlice(const Data& value,
1303             const DataArrayView::RegionType& region);             const DataTypes::RegionType& region);
1304    
1305    /**    /**
1306       \brief       \brief
1307       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.  
1308    */    */
1309    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1310    void    void
1311    archiveData(const std::string fileName);          print(void);
1312    
1313    /**    /**
1314       \brief       \brief
1315       Extract the Data object archived in the given file, overwriting       return the MPI rank number of the local data
1316       the current Data object.                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1317       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.  
1318    */    */
1319    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1320    void          int
1321    extractData(const std::string fileName,          get_MPIRank(void) const;
               const FunctionSpace& fspace);  
   
1322    
1323    /**    /**
1324       \brief       \brief
1325       print the data values to stdout. Used for debugging       return the MPI rank number of the local data
1326                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1327                     is returned
1328    */    */
1329    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1330    void          int
1331      print(void);          get_MPISize(void) const;
1332    
1333    /**    /**
1334       \brief       \brief
1335       return the MPI rank number of the local data       return the MPI rank number of the local data
1336           MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()                   MPI_COMM_WORLD is assumed and returned.
          is returned  
1337    */    */
1338    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1339      int          MPI_Comm
1340      get_MPIRank(void) const;          get_MPIComm(void) const;
1341    
1342    /**    /**
1343       \brief       \brief
1344       return the MPI rank number of the local data       return the object produced by the factory, which is a DataConstant or DataExpanded
1345           MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()      TODO Ownership of this object should be explained in doco.
          is returned  
1346    */    */
1347    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1348      int          DataAbstract*
1349      get_MPISize(void) const;          borrowData(void) const;
1350    
1351    
1352    /**    /**
1353       \brief       \brief
1354       return the MPI rank number of the local data       Return a pointer to the beginning of the datapoint at the specified offset.
1355           MPI_COMM_WORLD is assumed and returned.       TODO Eventually these should be inlined.
1356         \param i - position(offset) in the underlying datastructure
1357    */    */
1358    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1359      MPI_Comm          DataTypes::ValueType::const_reference
1360      get_MPIComm(void) const;          getDataAtOffset(DataTypes::ValueType::size_type i) const;
1361    
1362    
   /**  
      \brief  
      return the object produced by the factory, which is a DataConstant or DataExpanded  
   */  
1363    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1364      DataAbstract*          DataTypes::ValueType::reference
1365      borrowData(void) const;          getDataAtOffset(DataTypes::ValueType::size_type i);
1366    
1367   protected:   protected:
1368    
# Line 1374  class Data { Line 1439  class Data {
1439       \brief       \brief
1440       Construct a Data object of the appropriate type.       Construct a Data object of the appropriate type.
1441    */    */
1442    template <class IValueType>  
1443    void    void
1444    initialise(const IValueType& value,    initialise(const DataTypes::ValueType& value,
1445             const DataTypes::ShapeType& shape,
1446               const FunctionSpace& what,               const FunctionSpace& what,
1447               bool expanded);               bool expanded);
1448    
1449      void
1450      initialise(const boost::python::numeric::array& value,
1451                     const FunctionSpace& what,
1452                     bool expanded);
1453    
1454    //    //
1455    // flag to protect the data object against any update    // flag to protect the data object against any update
1456    bool m_protected;    bool m_protected;
# Line 1390  class Data { Line 1461  class Data {
1461    
1462  };  };
1463    
1464  template <class IValueType>  
1465  void  
1466  Data::initialise(const IValueType& value,  /**
1467                   const FunctionSpace& what,     Modify a filename for MPI parallel output to multiple files
1468                   bool expanded)  */
1469  {  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;  
   }  
 }  
1470    
1471  /**  /**
1472     Binary Data object operators.     Binary Data object operators.
1473  */  */
1474  inline double rpow(double x,double y)  inline double rpow(double x,double y)
1475  {  {
1476      return pow(y,x);      return pow(y,x);
1477  }  }
# Line 1512  ESCRIPT_DLL_API Data operator*(const boo Line 1568  ESCRIPT_DLL_API Data operator*(const boo
1568  */  */
1569  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1570    
1571    
1572    
1573  /**  /**
1574    \brief    \brief
1575    Output operator    Output operator
# Line 1533  C_GeneralTensorProduct(Data& arg0, Line 1591  C_GeneralTensorProduct(Data& arg0,
1591                       int axis_offset=0,                       int axis_offset=0,
1592                       int transpose=0);                       int transpose=0);
1593    
1594  /**  
1595    \brief  
1596    // /**
1597    /*  \brief
1598    Return true if operands are equivalent, else return false.    Return true if operands are equivalent, else return false.
1599    NB: this operator does very little at this point, and isn't to    NB: this operator does very little at this point, and isn't to
1600    be relied on. Requires further implementation.    be relied on. Requires further implementation.*/
1601  */  //*/
1602  //ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);  // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1603    
1604  /**  /**
1605    \brief    \brief
# Line 1554  Data::binaryOp(const Data& right, Line 1614  Data::binaryOp(const Data& right,
1614  {  {
1615     //     //
1616     // 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
1617     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1618       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1619     }     }
1620     //     //
# Line 1563  Data::binaryOp(const Data& right, Line 1623  Data::binaryOp(const Data& right,
1623     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1624       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1625         //         //
1626         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1627         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1628       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1629         //         //
# Line 1611  Data::binaryOp(const Data& right, Line 1671  Data::binaryOp(const Data& right,
1671    
1672  /**  /**
1673    \brief    \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  
1674    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.
1675    Given operation combines each element of each data point, thus argument    Given operation combines each element of each data point, thus argument
1676    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 1687  Data::algorithm(BinaryFunction operation Line 1701  Data::algorithm(BinaryFunction operation
1701    \brief    \brief
1702    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.
1703    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1704    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
1705    rank 0 Data object.    rank 0 Data object.
1706    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1707  */  */
# Line 1697  Data Line 1711  Data
1711  Data::dp_algorithm(BinaryFunction operation, double initial_value) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1712  {  {
1713    if (isExpanded()) {    if (isExpanded()) {
1714      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());      Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1715      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1716      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1717      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
# Line 1706  Data::dp_algorithm(BinaryFunction operat Line 1720  Data::dp_algorithm(BinaryFunction operat
1720      return result;      return result;
1721    } else if (isTagged()) {    } else if (isTagged()) {
1722      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());  
1723      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1724      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");  
1725    //     DataTypes::ShapeType viewShape;
1726    //     DataTypes::ValueType viewData(1);
1727    //     viewData[0]=0;
1728    //     DataArrayView defaultValue(viewData,viewShape);
1729    //     DataTagged::TagListType keys;
1730    //     DataTagged::ValueListType values;
1731    //     DataTagged::DataMapType::const_iterator i;
1732    //     for (i=dataT->getTagLookup().begin();i!=dataT->getTagLookup().end();i++) {
1733    //       keys.push_back(i->first);
1734    //       values.push_back(defaultValue);
1735    //     }
1736    //     Data result(keys,values,defaultValue,getFunctionSpace());
1737    //     DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());
1738    //     EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");
1739    
1740    
1741    
1742    
1743        DataTypes::ValueType defval(1);
1744        defval[0]=0;
1745        DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1746      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1747      return result;      return Data(resultT);   // note: the Data object now owns the resultT pointer
1748    
1749    } else if (isConstant()) {    } else if (isConstant()) {
1750      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());      Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1751      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1752      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1753      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
# Line 1736  Data::dp_algorithm(BinaryFunction operat Line 1759  Data::dp_algorithm(BinaryFunction operat
1759    return falseRetVal;    return falseRetVal;
1760  }  }
1761    
1762    /**
1763      \brief
1764      Compute a tensor operation with two Data objects
1765      \param arg0 - Input - Data object
1766      \param arg1 - Input - Data object
1767      \param operation - Input - Binary op functor
1768    */
1769    template <typename BinaryFunction>
1770    inline
1771    Data
1772    C_TensorBinaryOperation(Data const &arg_0,
1773                            Data const &arg_1,
1774                            BinaryFunction operation)
1775    {
1776      // Interpolate if necessary and find an appropriate function space
1777      Data arg_0_Z, arg_1_Z;
1778      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1779        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1780          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1781          arg_1_Z = Data(arg_1);
1782        }
1783        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1784          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1785          arg_0_Z =Data(arg_0);
1786        }
1787        else {
1788          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1789        }
1790      } else {
1791          arg_0_Z = Data(arg_0);
1792          arg_1_Z = Data(arg_1);
1793      }
1794      // Get rank and shape of inputs
1795      int rank0 = arg_0_Z.getDataPointRank();
1796      int rank1 = arg_1_Z.getDataPointRank();
1797      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1798      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1799      int size0 = arg_0_Z.getDataPointSize();
1800      int size1 = arg_1_Z.getDataPointSize();
1801    
1802      // Declare output Data object
1803      Data res;
1804    
1805      if (shape0 == shape1) {
1806    
1807        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1808          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1809    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1810          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1811          double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1812          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1813          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1814          double *ptr_2 = &(res.getDataAtOffset(0));
1815    
1816          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1817        }
1818        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1819    
1820          // Prepare the DataConstant input
1821          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1822    
1823          // Borrow DataTagged input from Data object
1824          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1825    
1826          // Prepare a DataTagged output 2
1827          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1828          res.tag();
1829          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1830    
1831          // Prepare offset into DataConstant
1832          int offset_0 = tmp_0->getPointOffset(0,0);
1833          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1834          // Get the views
1835    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1836    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1837    //       // Get the pointers to the actual data
1838    //       double *ptr_1 = &((view_1.getData())[0]);
1839    //       double *ptr_2 = &((view_2.getData())[0]);
1840    
1841          // Get the pointers to the actual data
1842          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1843          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1844    
1845          // Compute a result for the default
1846          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1847          // Compute a result for each tag
1848          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1849          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1850          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1851            tmp_2->addTag(i->first);
1852    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1853            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1854            double *ptr_1 = &view_1.getData(0);
1855            double *ptr_2 = &view_2.getData(0);*/
1856            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1857            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1858    
1859            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1860          }
1861    
1862        }
1863        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1864    
1865          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1866          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1867          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1868          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1869    
1870          int sampleNo_1,dataPointNo_1;
1871          int numSamples_1 = arg_1_Z.getNumSamples();
1872          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1873          int offset_0 = tmp_0->getPointOffset(0,0);
1874          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1875          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1876            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1877              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1878              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1879    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1880    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1881    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1882    
1883              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1884              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1885              double *ptr_2 = &(res.getDataAtOffset(offset_2));
1886              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1887            }
1888          }
1889    
1890        }
1891        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1892    
1893          // Borrow DataTagged input from Data object
1894          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1895    
1896          // Prepare the DataConstant input
1897          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1898    
1899          // Prepare a DataTagged output 2
1900          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1901          res.tag();
1902          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1903    
1904          // Prepare offset into DataConstant
1905          int offset_1 = tmp_1->getPointOffset(0,0);
1906    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1907          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1908          // Get the views
1909    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1910    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1911    //       // Get the pointers to the actual data
1912    //       double *ptr_0 = &((view_0.getData())[0]);
1913    //       double *ptr_2 = &((view_2.getData())[0]);
1914          // Get the pointers to the actual data
1915          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1916          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1917          // Compute a result for the default
1918          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1919          // Compute a result for each tag
1920          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1921          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1922          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1923            tmp_2->addTag(i->first);
1924    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1925    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1926    //         double *ptr_0 = &view_0.getData(0);
1927    //         double *ptr_2 = &view_2.getData(0);
1928            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1929            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1930            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1931          }
1932    
1933        }
1934        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1935    
1936          // Borrow DataTagged input from Data object
1937          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1938    
1939          // Borrow DataTagged input from Data object
1940          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1941    
1942          // Prepare a DataTagged output 2
1943          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1944          res.tag();        // DataTagged output
1945          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1946    
1947    //       // Get the views
1948    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1949    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1950    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1951    //       // Get the pointers to the actual data
1952    //       double *ptr_0 = &((view_0.getData())[0]);
1953    //       double *ptr_1 = &((view_1.getData())[0]);
1954    //       double *ptr_2 = &((view_2.getData())[0]);
1955    
1956          // Get the pointers to the actual data
1957          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1958          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1959          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1960    
1961          // Compute a result for the default
1962          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1963          // Merge the tags
1964          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1965          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1966          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1967          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1968            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
1969          }
1970          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1971            tmp_2->addTag(i->first);
1972          }
1973          // Compute a result for each tag
1974          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1975          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1976    
1977    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1978    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1979    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1980    //         double *ptr_0 = &view_0.getData(0);
1981    //         double *ptr_1 = &view_1.getData(0);
1982    //         double *ptr_2 = &view_2.getData(0);
1983    
1984            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1985            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1986            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1987    
1988            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1989          }
1990    
1991        }
1992        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
1993    
1994          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1995          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1996          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1997          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1998          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1999    
2000          int sampleNo_0,dataPointNo_0;
2001          int numSamples_0 = arg_0_Z.getNumSamples();
2002          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2003          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2004          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2005            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2006            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2007            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2008              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2009              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2010    
2011    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2012    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2013              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2014              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2015    
2016    
2017              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2018            }
2019          }
2020    
2021        }
2022        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2023    
2024          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2025          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2026          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2027          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2028    
2029          int sampleNo_0,dataPointNo_0;
2030          int numSamples_0 = arg_0_Z.getNumSamples();
2031          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2032          int offset_1 = tmp_1->getPointOffset(0,0);
2033          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2034          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2035            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2036              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2037              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2038    
2039    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2040    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2041    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2042    
2043              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2044              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2045              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2046    
2047    
2048              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2049            }
2050          }
2051    
2052        }
2053        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2054    
2055          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2056          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2057          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2058          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2059          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2060    
2061          int sampleNo_0,dataPointNo_0;
2062          int numSamples_0 = arg_0_Z.getNumSamples();
2063          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2064          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2065          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2066            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2067            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2068            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2069              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2070              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2071              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2072              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2073              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2074            }
2075          }
2076    
2077        }
2078        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2079    
2080          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2081          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2082          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2083          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2084          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2085    
2086          int sampleNo_0,dataPointNo_0;
2087          int numSamples_0 = arg_0_Z.getNumSamples();
2088          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2089          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2090          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2091            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2092              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2093              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2094              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2095              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2096              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2097              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2098              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2099            }
2100          }
2101    
2102        }
2103        else {
2104          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2105        }
2106    
2107      } else if (0 == rank0) {
2108    
2109        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2110          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2111          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2112          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2113          double *ptr_2 = &(res.getDataAtOffset(0));
2114          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2115        }
2116        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2117    
2118          // Prepare the DataConstant input
2119          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2120    
2121          // Borrow DataTagged input from Data object
2122          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2123    
2124          // Prepare a DataTagged output 2
2125          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2126          res.tag();
2127          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2128    
2129          // Prepare offset into DataConstant
2130          int offset_0 = tmp_0->getPointOffset(0,0);
2131          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2132          // Get the views
2133    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2134    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2135    //       // Get the pointers to the actual data
2136    //       double *ptr_1 = &((view_1.getData())[0]);
2137    //       double *ptr_2 = &((view_2.getData())[0]);
2138           double *ptr_1 = &(tmp_1->getDefaultValue(0));
2139           double *ptr_2 = &(tmp_2->getDefaultValue(0));
2140    
2141          // Compute a result for the default
2142          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2143          // Compute a result for each tag
2144          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2145          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2146          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2147            tmp_2->addTag(i->first);
2148    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2149    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2150    //         double *ptr_1 = &view_1.getData(0);
2151    //         double *ptr_2 = &view_2.getData(0);
2152            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2153            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2154            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2155          }
2156    
2157        }
2158        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2159    
2160          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2161          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2162          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2163          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2164    
2165          int sampleNo_1,dataPointNo_1;
2166          int numSamples_1 = arg_1_Z.getNumSamples();
2167          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2168          int offset_0 = tmp_0->getPointOffset(0,0);
2169          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2170          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2171            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2172              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2173              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2174              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2175              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2176              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2177              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2178    
2179            }
2180          }
2181    
2182        }
2183        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2184    
2185          // Borrow DataTagged input from Data object
2186          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2187    
2188          // Prepare the DataConstant input
2189          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2190    
2191          // Prepare a DataTagged output 2
2192          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2193          res.tag();
2194          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2195    
2196          // Prepare offset into DataConstant
2197          int offset_1 = tmp_1->getPointOffset(0,0);
2198    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2199          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2200          // Get the views
2201    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2202          DataArrayView view_2 = tmp_2->getDefaultValue();
2203          // Get the pointers to the actual data
2204          double *ptr_0 = &((view_0.getData())[0]);
2205          double *ptr_2 = &((view_2.getData())[0]);*/
2206    
2207          // Get the pointers to the actual data
2208          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2209          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2210    
2211    
2212          // Compute a result for the default
2213          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2214          // Compute a result for each tag
2215          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2216          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2217          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2218            tmp_2->addTag(i->first);
2219    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2220            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2221            double *ptr_0 = &view_0.getData(0);
2222            double *ptr_2 = &view_2.getData(0);*/
2223            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2224            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2225    
2226            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2227          }
2228    
2229        }
2230        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2231    
2232          // Borrow DataTagged input from Data object
2233          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2234    
2235          // Borrow DataTagged input from Data object
2236          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2237    
2238          // Prepare a DataTagged output 2
2239          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2240          res.tag();        // DataTagged output
2241          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2242    
2243          // Get the views
2244    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2245          DataArrayView view_1 = tmp_1->getDefaultValue();
2246          DataArrayView view_2 = tmp_2->getDefaultValue();
2247          // Get the pointers to the actual data
2248          double *ptr_0 = &((view_0.getData())[0]);
2249          double *ptr_1 = &((view_1.getData())[0]);
2250          double *ptr_2 = &((view_2.getData())[0]);*/
2251    
2252          // Get the pointers to the actual data
2253          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2254          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2255          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2256    
2257    
2258          // Compute a result for the default
2259          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2260          // Merge the tags
2261          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2262          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2263          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2264          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2265            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2266          }
2267          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2268            tmp_2->addTag(i->first);
2269          }
2270          // Compute a result for each tag
2271          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2272          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2273    
2274    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2275            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2276            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2277            double *ptr_0 = &view_0.getData(0);
2278            double *ptr_1 = &view_1.getData(0);
2279            double *ptr_2 = &view_2.getData(0);*/
2280    
2281            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2282            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2283            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2284    
2285            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2286          }
2287    
2288        }
2289        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2290    
2291          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2292          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2293          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2294          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2295          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2296    
2297          int sampleNo_0,dataPointNo_0;
2298          int numSamples_0 = arg_0_Z.getNumSamples();
2299          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2300          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2301          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2302            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2303            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2304            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2305              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2306              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2307              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2308              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2309              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2310            }
2311          }
2312    
2313        }
2314        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2315    
2316          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2317          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2318          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2319          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2320    
2321          int sampleNo_0,dataPointNo_0;
2322          int numSamples_0 = arg_0_Z.getNumSamples();
2323          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2324          int offset_1 = tmp_1->getPointOffset(0,0);
2325          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2326          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2327            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2328              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2329              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2330              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2331              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2332              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2333              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2334            }
2335          }
2336    
2337    
2338        }
2339        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2340    
2341          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2342          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2343          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2344          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2345          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2346    
2347          int sampleNo_0,dataPointNo_0;
2348          int numSamples_0 = arg_0_Z.getNumSamples();
2349          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2350          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2351          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2352            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2353            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2354            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2355              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2356              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2357              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2358              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2359              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2360            }
2361          }
2362    
2363        }
2364        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2365    
2366          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2367          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2368          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2369          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2370          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2371    
2372          int sampleNo_0,dataPointNo_0;
2373          int numSamples_0 = arg_0_Z.getNumSamples();
2374          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2375          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2376          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2377            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2378              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2379              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2380              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2381              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2382              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2383              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2384              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2385            }
2386          }
2387    
2388        }
2389        else {
2390          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2391        }
2392    
2393      } else if (0 == rank1) {
2394    
2395        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2396          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2397          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2398          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2399          double *ptr_2 = &(res.getDataAtOffset(0));
2400          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2401        }
2402        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2403    
2404          // Prepare the DataConstant input
2405          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2406    
2407          // Borrow DataTagged input from Data object
2408          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2409    
2410          // Prepare a DataTagged output 2
2411          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2412          res.tag();
2413          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2414    
2415          // Prepare offset into DataConstant
2416          int offset_0 = tmp_0->getPointOffset(0,0);
2417          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2418          // Get the views
2419    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2420          DataArrayView view_2 = tmp_2->getDefaultValue();
2421          // Get the pointers to the actual data
2422          double *ptr_1 = &((view_1.getData())[0]);
2423          double *ptr_2 = &((view_2.getData())[0]);*/
2424          //Get the pointers to the actual data
2425          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2426          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2427    
2428          // Compute a result for the default
2429          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2430          // Compute a result for each tag
2431          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2432          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2433          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2434            tmp_2->addTag(i->first);
2435    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2436    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2437    //         double *ptr_1 = &view_1.getData(0);
2438    //         double *ptr_2 = &view_2.getData(0);
2439            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2440            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2441    
2442    
2443            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2444          }
2445    
2446        }
2447        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2448    
2449          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2450          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2451          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2452          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2453    
2454          int sampleNo_1,dataPointNo_1;
2455          int numSamples_1 = arg_1_Z.getNumSamples();
2456          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2457          int offset_0 = tmp_0->getPointOffset(0,0);
2458          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2459          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2460            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2461              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2462              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2463              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2464              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2465              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2466              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2467            }
2468          }
2469    
2470        }
2471        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2472    
2473          // Borrow DataTagged input from Data object
2474          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2475    
2476          // Prepare the DataConstant input
2477          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2478    
2479          // Prepare a DataTagged output 2
2480          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2481          res.tag();
2482          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2483    
2484          // Prepare offset into DataConstant
2485          int offset_1 = tmp_1->getPointOffset(0,0);
2486          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2487          // Get the views
2488    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2489    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2490    //       // Get the pointers to the actual data
2491    //       double *ptr_0 = &((view_0.getData())[0]);
2492    //       double *ptr_2 = &((view_2.getData())[0]);
2493          // Get the pointers to the actual data
2494          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2495          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2496          // Compute a result for the default
2497          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2498          // Compute a result for each tag
2499          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2500          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2501          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2502            tmp_2->addTag(i->first);
2503    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2504            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2505            double *ptr_0 = &view_0.getData(0);
2506            double *ptr_2 = &view_2.getData(0);*/
2507            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2508            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2509            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2510          }
2511    
2512        }
2513        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2514    
2515          // Borrow DataTagged input from Data object
2516          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2517    
2518          // Borrow DataTagged input from Data object
2519          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2520    
2521          // Prepare a DataTagged output 2
2522          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2523          res.tag();        // DataTagged output
2524          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2525    
2526          // Get the views
2527    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2528    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2529    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2530    //       // Get the pointers to the actual data
2531    //       double *ptr_0 = &((view_0.getData())[0]);
2532    //       double *ptr_1 = &((view_1.getData())[0]);
2533    //       double *ptr_2 = &((view_2.getData())[0]);
2534    
2535          // Get the pointers to the actual data
2536          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2537          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2538          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2539    
2540          // Compute a result for the default
2541          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2542          // Merge the tags
2543          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2544          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2545          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2546          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2547            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2548          }
2549          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2550            tmp_2->addTag(i->first);
2551          }
2552          // Compute a result for each tag
2553          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2554          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2555    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2556    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2557    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2558    //         double *ptr_0 = &view_0.getData(0);
2559    //         double *ptr_1 = &view_1.getData(0);
2560    //         double *ptr_2 = &view_2.getData(0);
2561    
2562            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2563            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2564            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2565            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2566          }
2567    
2568        }
2569        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2570    
2571          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2572          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2573          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2574          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2575          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2576    
2577          int sampleNo_0,dataPointNo_0;
2578          int numSamples_0 = arg_0_Z.getNumSamples();
2579          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2580          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2581          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2582            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2583            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2584            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2585              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2586              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2587              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2588              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2589              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2590            }
2591          }
2592    
2593        }
2594        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2595    
2596          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2597          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2598          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2599          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2600    
2601          int sampleNo_0,dataPointNo_0;
2602          int numSamples_0 = arg_0_Z.getNumSamples();
2603          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2604          int offset_1 = tmp_1->getPointOffset(0,0);
2605          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2606          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2607            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2608              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2609              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2610              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2611              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2612              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2613              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2614            }
2615          }
2616    
2617    
2618        }
2619        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2620    
2621          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2622          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2623          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2624          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2625          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2626    
2627          int sampleNo_0,dataPointNo_0;
2628          int numSamples_0 = arg_0_Z.getNumSamples();
2629          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2630          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2631          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2632            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2633            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2634            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2635              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2636              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2637              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2638              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2639              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2640            }
2641          }
2642    
2643        }
2644        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2645    
2646          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2647          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2648          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2649          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2650          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2651    
2652          int sampleNo_0,dataPointNo_0;
2653          int numSamples_0 = arg_0_Z.getNumSamples();
2654          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2655          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2656          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2657            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2658              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2659              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2660              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2661              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2662              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2663              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2664              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2665            }
2666          }
2667    
2668        }
2669        else {
2670          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2671        }
2672    
2673      } else {
2674        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2675      }
2676    
2677      return res;
2678    }
2679    
2680    template <typename UnaryFunction>
2681    Data
2682    C_TensorUnaryOperation(Data const &arg_0,
2683                           UnaryFunction operation)
2684    {
2685      // Interpolate if necessary and find an appropriate function space
2686      Data arg_0_Z = Data(arg_0);
2687    
2688      // Get rank and shape of inputs
2689      int rank0 = arg_0_Z.getDataPointRank();
2690      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2691      int size0 = arg_0_Z.getDataPointSize();
2692    
2693      // Declare output Data object
2694      Data res;
2695    
2696      if (arg_0_Z.isConstant()) {
2697        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2698    //     double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2699    //     double *ptr_2 = &((res.getPointDataView().getData())[0]);
2700        double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2701        double *ptr_2 = &(res.getDataAtOffset(0));
2702        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2703      }
2704      else if (arg_0_Z.isTagged()) {
2705    
2706        // Borrow DataTagged input from Data object
2707        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2708    
2709        // Prepare a DataTagged output 2
2710        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2711        res.tag();
2712        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2713    
2714    //     // Get the views
2715    //     DataArrayView view_0 = tmp_0->getDefaultValue();
2716    //     DataArrayView view_2 = tmp_2->getDefaultValue();
2717    //     // Get the pointers to the actual data
2718    //     double *ptr_0 = &((view_0.getData())[0]);
2719    //     double *ptr_2 = &((view_2.getData())[0]);
2720        // Get the pointers to the actual data
2721        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2722        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2723        // Compute a result for the default
2724        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2725        // Compute a result for each tag
2726        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2727        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2728        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2729          tmp_2->addTag(i->first);
2730    //       DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2731    //       DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2732    //       double *ptr_0 = &view_0.getData(0);
2733    //       double *ptr_2 = &view_2.getData(0);
2734          double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2735          double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2736          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2737        }
2738    
2739      }
2740      else if (arg_0_Z.isExpanded()) {
2741    
2742        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2743        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2744        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2745    
2746        int sampleNo_0,dataPointNo_0;
2747        int numSamples_0 = arg_0_Z.getNumSamples();
2748        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2749        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2750        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2751          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2752    //         int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2753    //         int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2754    //         double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2755    //         double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2756            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2757            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2758            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2759            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2760            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2761          }
2762        }
2763    
2764      }
2765      else {
2766        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2767      }
2768    
2769      return res;
2770    }
2771    
2772  }  }
2773  #endif  #endif

Legend:
Removed from v.1092  
changed lines
  Added in v.1799

  ViewVC Help
Powered by ViewVC 1.1.26