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

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

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

revision 782 by bcumming, Tue Jul 18 00:47:47 2006 UTC revision 1334 by matt, Thu Oct 25 05:08:54 2007 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 26  Line 28 
28    
29  extern "C" {  extern "C" {
30  #include "DataC.h"  #include "DataC.h"
31  #include "paso/Paso.h"  /* #include "paso/Paso.h" doesn't belong in this file...causes trouble for BruceFactory.cpp */
32  }  }
33    
34    #include "esysmpi.h"
35  #include <string>  #include <string>
36  #include <algorithm>  #include <algorithm>
37    
# Line 47  class DataExpanded; Line 50  class DataExpanded;
50    
51  /**  /**
52     \brief     \brief
53     Data creates the appropriate Data object for the given construction     Data creates the appropriate Data object for the given construction
54     arguments.     arguments.
55    
56     Description:     Description:
57     Data is essentially a factory class which creates the appropriate Data     Data is essentially a factory class which creates the appropriate Data
# Line 66  class Data { Line 69  class Data {
69    typedef double (*UnaryDFunPtr)(double);    typedef double (*UnaryDFunPtr)(double);
70    typedef double (*BinaryDFunPtr)(double,double);    typedef double (*BinaryDFunPtr)(double,double);
71    
72    
73    /**    /**
74       Constructors.       Constructors.
75    */    */
# Line 209  class Data { Line 213  class Data {
213       Constructor which creates a DataConstant of "shape" with constant value.       Constructor which creates a DataConstant of "shape" with constant value.
214    */    */
215    ESCRIPT_DLL_API    ESCRIPT_DLL_API
216    Data(double value,    Data(double value,
217         const boost::python::tuple& shape=boost::python::make_tuple(),         const boost::python::tuple& shape=boost::python::make_tuple(),
218         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
219         bool expanded=false);         bool expanded=false);
220    /**    /**
# Line 234  class Data { Line 238  class Data {
238    
239    /**    /**
240       \brief       \brief
241       Return the values of all data-points as a single python numarray object.       switches on update protection
242    
243    */    */
244    ESCRIPT_DLL_API    ESCRIPT_DLL_API
245    const boost::python::numeric::array    void
246    convertToNumArray();    setProtection();
247    
248    /**    /**
249       \brief       \brief
250       Return the values of all data-points for the given sample as a single python numarray object.       Returns trueif the data object is protected against update
251    
252    */    */
253    ESCRIPT_DLL_API    ESCRIPT_DLL_API
254    const boost::python::numeric::array    bool
255    convertToNumArrayFromSampleNo(int sampleNo);    isProtected() const;
256    
257    /**    /**
258       \brief       \brief
259       Return the value of the specified data-point as a single python numarray object.       Return the values of a data point on this process
260    */    */
261    ESCRIPT_DLL_API    ESCRIPT_DLL_API
262    const boost::python::numeric::array    const boost::python::numeric::array
263    convertToNumArrayFromDPNo(int sampleNo,    getValueOfDataPoint(int dataPointNo);
                             int dataPointNo);  
264    
265    /**    /**
266       \brief       \brief
267       Fills the expanded Data object from values of a python numarray object.       sets the values of a data-point from a python object on this process
268    */    */
269    ESCRIPT_DLL_API    ESCRIPT_DLL_API
270    void    void
271    fillFromNumArray(const boost::python::numeric::array);    setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
272    
273      /**
274         \brief
275         sets the values of a data-point from a numarray object on this process
276      */
277      ESCRIPT_DLL_API
278      void
279      setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
280    
281      /**
282         \brief
283         sets the values of a data-point on this process
284      */
285      ESCRIPT_DLL_API
286      void
287      setValueOfDataPoint(int dataPointNo, const double);
288    
289      /**
290         \brief
291         Return the value of the specified data-point across all processors
292      */
293      ESCRIPT_DLL_API
294      const boost::python::numeric::array
295      getValueOfGlobalDataPoint(int procNo, int dataPointNo);
296    
297    /**    /**
298       \brief       \brief
# Line 423  class Data { Line 452  class Data {
452    
453    /**    /**
454       \brief       \brief
455         Return the number of data points
456      */
457      ESCRIPT_DLL_API
458      inline
459      int
460      getNumDataPoints() const
461      {
462        return getNumSamples() * getNumDataPointsPerSample();
463      }
464      /**
465         \brief
466       Return the number of samples.       Return the number of samples.
467    */    */
468    ESCRIPT_DLL_API    ESCRIPT_DLL_API
# Line 444  class Data { Line 484  class Data {
484    {    {
485      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
486    }    }
487      /**
488         \brief
489         dumps the object into a netCDF file
490      */
491      ESCRIPT_DLL_API
492      void
493      dump(const std::string fileName) const;
494    /**    /**
495       \brief       \brief
496       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 475  class Data { Line 521  class Data {
521    
522    /**    /**
523       \brief       \brief
      Assign the given value to the data-points referenced by the given  
      reference number.  
   
      The value supplied is a python numarray object.  The data from this numarray  
      is unpacked into a DataArray, and this is used to set the corresponding  
      data-points in the underlying Data object.  
   
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
   
      \param ref - Input - reference number.  
      \param value - Input - value to assign to data-points associated with  
                             the given reference number.  
   */  
   ESCRIPT_DLL_API  
   void  
   setRefValue(int ref,  
               const boost::python::numeric::array& value);  
   
   /**  
      \brief  
      Return the values associated with the data-points referenced by the given  
      reference number.  
   
      The value supplied is a python numarray object. The data from the corresponding  
      data-points in this Data object are packed into the given numarray object.  
   
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
   
      \param ref - Input - reference number.  
      \param value - Output - object to receive values from data-points  
                              associated with the given reference number.  
   */  
   ESCRIPT_DLL_API  
   void  
   getRefValue(int ref,  
               boost::python::numeric::array& value);  
   
   /**  
      \brief  
524       Return a view into the data for the data point specified.       Return a view into the data for the data point specified.
525       NOTE: Construction of the DataArrayView is a relatively expensive       NOTE: Construction of the DataArrayView is a relatively expensive
526       operation.       operation.
# Line 528  class Data { Line 533  class Data {
533    getDataPoint(int sampleNo,    getDataPoint(int sampleNo,
534                 int dataPointNo)                 int dataPointNo)
535    {    {
536      return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getDataPoint(sampleNo,dataPointNo);
537    }    }
538    
539    /**    /**
# Line 564  class Data { Line 569  class Data {
569    DataArrayView::ValueType::size_type    DataArrayView::ValueType::size_type
570    getLength() const;    getLength() const;
571    
572    
573    
574      /**
575         \brief
576         Assign the given value to the tag assocciated with name. Implicitly converts this
577         object to type DataTagged. Throws an exception if this object
578         cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
579         \param tagKey - Input - Integer key.
580         \param value - Input - Value to associate with given key.
581        ==>*
582      */
583      ESCRIPT_DLL_API
584      void
585      setTaggedValueByName(std::string name,
586                           const boost::python::object& value);
587    
588    /**    /**
589       \brief       \brief
590       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
# Line 607  class Data { Line 628  class Data {
628    
629    /**    /**
630       \brief       \brief
631         set all values to zero
632         *
633      */
634      ESCRIPT_DLL_API
635      void
636      setToZero();
637    
638      /**
639         \brief
640       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
641       the result as a Data object.       the result as a Data object.
642       *       *
# Line 614  class Data { Line 644  class Data {
644    ESCRIPT_DLL_API    ESCRIPT_DLL_API
645    Data    Data
646    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
647    /**    /**
648       \brief       \brief
649       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 640  class Data { Line 669  class Data {
669    
670    /**    /**
671       \brief       \brief
672         Returns 1./ Data object
673         *
674      */
675      ESCRIPT_DLL_API
676      Data
677      oneOver() const;
678      /**
679         \brief
680       Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.       Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.
681       *       *
682    */    */
# Line 703  class Data { Line 740  class Data {
740    
741    /**    /**
742       \brief       \brief
      Return the minimum absolute value of this Data object.  
      *  
   */  
   ESCRIPT_DLL_API  
   double  
   Linf() const;  
   
   /**  
      \brief  
743       Return the maximum value of this Data object.       Return the maximum value of this Data object.
744       *       *
745    */    */
# Line 762  class Data { Line 790  class Data {
790    */    */
791    ESCRIPT_DLL_API    ESCRIPT_DLL_API
792    const boost::python::tuple    const boost::python::tuple
793    mindp() const;    minGlobalDataPoint() const;
794    
795    ESCRIPT_DLL_API    ESCRIPT_DLL_API
796    void    void
797  #ifndef PASO_MPI    calc_minGlobalDataPoint(int& ProcNo,  int& DataPointNo) const;
   calc_mindp(int& SampleNo,  
              int& DataPointNo) const;  
 #else  
   calc_mindp(int& ProcNo,  
                         int& SampleNo,    
              int& DataPointNo) const;  
 #endif  
798    /**    /**
799       \brief       \brief
800       Return the sign of each data point of this Data object.       Return the sign of each data point of this Data object.
# Line 809  class Data { Line 830  class Data {
830    */    */
831    ESCRIPT_DLL_API    ESCRIPT_DLL_API
832    Data    Data
833    matrixtrace(int axis_offset) const;    trace(int axis_offset) const;
834    
835    /**    /**
836       \brief       \brief
# Line 833  class Data { Line 854  class Data {
854    /**    /**
855       \brief       \brief
856       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.
857       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
858       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
859       first non-zero entry is positive.       first non-zero entry is positive.
860       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
861       *       *
# Line 845  class Data { Line 866  class Data {
866    
867    /**    /**
868       \brief       \brief
869       Calculate the trace of each data point of this Data object.       swaps the components axis0 and axis1
870         *
871      */
872      ESCRIPT_DLL_API
873      Data
874      swapaxes(const int axis0, const int axis1) const;
875    
876      /**
877         \brief
878         Return the error function erf of each data point of this Data object.
879       *       *
880    */    */
881    ESCRIPT_DLL_API    ESCRIPT_DLL_API
882    Data    Data
883    trace() const;    erf() const;
884    
885    /**    /**
886       \brief       \brief
# Line 1029  class Data { Line 1059  class Data {
1059    /**    /**
1060       \brief       \brief
1061       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.
1062        
1063       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1064       *       *
1065     */     */
# Line 1040  class Data { Line 1070  class Data {
1070    /**    /**
1071       \brief       \brief
1072       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.
1073        
1074       \param left Input - the bases       \param left Input - the bases
1075       *       *
1076     */     */
# Line 1076  class Data { Line 1106  class Data {
1106    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1107    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1108    
1109      ESCRIPT_DLL_API
1110      Data& operator=(const Data& other);
1111    
1112    /**    /**
1113       \brief       \brief
1114       Overloaded operator -=       Overloaded operator -=
# Line 1168  class Data { Line 1201  class Data {
1201    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1202    inline    inline
1203    void    void
1204    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1205    
1206    /**    /**
1207       \brief       \brief
# Line 1217  class Data { Line 1250  class Data {
1250                const FunctionSpace& fspace);                const FunctionSpace& fspace);
1251    
1252    
 #ifdef PASO_MPI  
1253    /**    /**
1254       \brief       \brief
1255       print the data values to stdout. Used for debugging       print the data values to stdout. Used for debugging
1256    */    */
1257    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1258    void    void
1259      print(void);          print(void);
1260    
1261    /**    /**
1262       \brief       \brief
1263       return the MPI rank number of the local data       return the MPI rank number of the local data
1264           MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1265           is returned                   is returned
1266    */    */
1267    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1268      int          int
1269      get_MPIRank(void) const;          get_MPIRank(void) const;
1270    
1271    /**    /**
1272       \brief       \brief
1273       return the MPI rank number of the local data       return the MPI rank number of the local data
1274           MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1275           is returned                   is returned
1276    */    */
1277    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1278      int          int
1279      get_MPISize(void) const;          get_MPISize(void) const;
1280    
1281    /**    /**
1282       \brief       \brief
1283       return the MPI rank number of the local data       return the MPI rank number of the local data
1284           MPI_COMM_WORLD is assumed and returned.                   MPI_COMM_WORLD is assumed and returned.
1285      */
1286      ESCRIPT_DLL_API
1287            MPI_Comm
1288            get_MPIComm(void) const;
1289    
1290      /**
1291         \brief
1292         return the object produced by the factory, which is a DataConstant or DataExpanded
1293    */    */
1294    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1295      MPI_Comm          DataAbstract*
1296      get_MPIComm(void) const;          borrowData(void) const;
1297  #endif  
       
1298   protected:   protected:
1299    
1300   private:   private:
# Line 1313  class Data { Line 1352  class Data {
1352    
1353    /**    /**
1354       \brief       \brief
      Perform the given binary operation on all of the data's elements.  
      RHS is a boost::python object.  
   */  
   template <class BinaryFunction>  
   inline  
   void  
   binaryOp(const boost::python::object& right,  
            BinaryFunction operation);  
   
   /**  
      \brief  
1355       Convert the data type of the RHS to match this.       Convert the data type of the RHS to match this.
1356       \param right - Input - data type to match.       \param right - Input - data type to match.
1357    */    */
# Line 1348  class Data { Line 1376  class Data {
1376               const FunctionSpace& what,               const FunctionSpace& what,
1377               bool expanded);               bool expanded);
1378    
1379    /**    //
1380       \brief    // flag to protect the data object against any update
1381       Reshape the data point if the data point is currently rank 0.    bool m_protected;
      Will throw an exception if the data points are not rank 0.  
      The original data point value is used for all values of the new  
      data point.  
   */  
   void  
   reshapeDataPoint(const DataArrayView::ShapeType& shape);  
1382    
1383    //    //
1384    // pointer to the actual data object    // pointer to the actual data object
1385    boost::shared_ptr<DataAbstract> m_data;    boost::shared_ptr<DataAbstract> m_data;
1386    
   //  
   // pointer to the internal profiling data  
   struct profDataEntry *profData;  
   
1387  };  };
1388    
1389  template <class IValueType>  template <class IValueType>
# Line 1393  Data::initialise(const IValueType& value Line 1411  Data::initialise(const IValueType& value
1411  /**  /**
1412     Binary Data object operators.     Binary Data object operators.
1413  */  */
1414    inline double rpow(double x,double y)
1415    {
1416        return pow(y,x);
1417    }
1418    
1419  /**  /**
1420    \brief    \brief
# Line 1486  ESCRIPT_DLL_API Data operator*(const boo Line 1508  ESCRIPT_DLL_API Data operator*(const boo
1508  */  */
1509  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);
1510    
1511    
1512    
1513  /**  /**
1514    \brief    \brief
1515    Output operator    Output operator
# Line 1494  ESCRIPT_DLL_API std::ostream& operator<< Line 1518  ESCRIPT_DLL_API std::ostream& operator<<
1518    
1519  /**  /**
1520    \brief    \brief
1521      Compute a tensor product of two Data objects
1522      \param arg0 - Input - Data object
1523      \param arg1 - Input - Data object
1524      \param axis_offset - Input - axis offset
1525      \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1526    */
1527    ESCRIPT_DLL_API
1528    Data
1529    C_GeneralTensorProduct(Data& arg0,
1530                         Data& arg1,
1531                         int axis_offset=0,
1532                         int transpose=0);
1533    
1534    
1535    /**
1536      \brief
1537      Compute a tensor operation with two Data objects
1538      \param arg0 - Input - Data object
1539      \param arg1 - Input - Data object
1540      \param operation - Input - Binary op functor
1541    */
1542    template <typename BinaryFunction>
1543    ESCRIPT_DLL_API
1544    Data
1545    C_TensorBinaryOperation(Data const &arg0,
1546                            Data const &arg1,
1547                            BinaryFunction operation);
1548    
1549    /**
1550      \brief
1551    Return true if operands are equivalent, else return false.    Return true if operands are equivalent, else return false.
1552    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
1553    be relied on. Requires further implementation.    be relied on. Requires further implementation.
1554  */  */
1555  //ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);  // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1556    
1557  /**  /**
1558    \brief    \brief
# Line 1514  Data::binaryOp(const Data& right, Line 1568  Data::binaryOp(const Data& right,
1568     //     //
1569     // 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
1570     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {
1571       reshapeDataPoint(right.getPointDataView().getShape());       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1572     }     }
1573     //     //
1574     // initially make the temporary a shallow copy     // initially make the temporary a shallow copy
# Line 1522  Data::binaryOp(const Data& right, Line 1576  Data::binaryOp(const Data& right,
1576     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1577       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1578         //         //
1579         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1580         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1581       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1582         //         //
# Line 1570  Data::binaryOp(const Data& right, Line 1624  Data::binaryOp(const Data& right,
1624    
1625  /**  /**
1626    \brief    \brief
   Perform the given binary operation with this and right as operands.  
   Right is a boost::python object.  
 */  
 template <class BinaryFunction>  
 inline  
 void  
 Data::binaryOp(const boost::python::object& right,  
                BinaryFunction operation)  
 {  
    DataArray temp(right);  
    //  
    // if this has a rank of zero promote it to the rank of the RHS.  
    if (getPointDataView().getRank()==0 && temp.getView().getRank()!=0) {  
       reshapeDataPoint(temp.getView().getShape());  
    }  
    //  
    // Always allow scalar values for the RHS but check other shapes  
    if (temp.getView().getRank()!=0) {  
      if (!getPointDataView().checkShape(temp.getView().getShape())) {  
        throw DataException(getPointDataView().createShapeErrorMessage(  
                   "Error - RHS shape doesn't match LHS shape.",temp.getView().getShape()));  
      }  
    }  
    if (isExpanded()) {  
      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());  
      EsysAssert((leftC!=0),"Programming error - casting to DataExpanded.");  
      escript::binaryOp(*leftC,temp.getView(),operation);  
    } else if (isTagged()) {  
      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());  
      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");  
      escript::binaryOp(*leftC,temp.getView(),operation);  
    } else if (isConstant()) {  
      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());  
      EsysAssert((leftC!=0),"Programming error - casting to DataConstant.");  
      escript::binaryOp(*leftC,temp.getView(),operation);  
    }  
 }  
   
 /**  
   \brief  
   Perform the given unary operation on other and return the result.  
   Given operation is performed on each element of each data point, thus  
   argument object is a rank n Data object, and returned object is a rank n  
   Data object.  
   Calls Data::unaryOp.  
 */  
 template <class UnaryFunction>  
 inline  
 Data  
 unaryOp(const Data& other,  
         UnaryFunction operation)  
 {  
   Data result;  
   result.copy(other);  
   result.unaryOp(operation);  
   return result;  
 }  
   
 /**  
   \brief  
   Perform the given unary operation on this.  
   Given operation is performed on each element of each data point.  
   Calls escript::unaryOp.  
 */  
 template <class UnaryFunction>  
 inline  
 void  
 Data::unaryOp(UnaryFunction operation)  
 {  
   if (isExpanded()) {  
     DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());  
     EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");  
     escript::unaryOp(*leftC,operation);  
   } else if (isTagged()) {  
     DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());  
     EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");  
     escript::unaryOp(*leftC,operation);  
   } else if (isConstant()) {  
     DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());  
     EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");  
     escript::unaryOp(*leftC,operation);  
   }  
 }  
   
 /**  
   \brief  
1627    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.
1628    Given operation combines each element of each data point, thus argument    Given operation combines each element of each data point, thus argument
1629    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 1686  Data::algorithm(BinaryFunction operation Line 1654  Data::algorithm(BinaryFunction operation
1654    \brief    \brief
1655    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.
1656    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1657    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
1658    rank 0 Data object.    rank 0 Data object.
1659    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1660  */  */
# Line 1735  Data::dp_algorithm(BinaryFunction operat Line 1703  Data::dp_algorithm(BinaryFunction operat
1703    return falseRetVal;    return falseRetVal;
1704  }  }
1705    
1706    template <typename BinaryFunction>
1707    Data
1708    C_TensorBinaryOperation(Data const &arg_0,
1709                            Data const &arg_1,
1710                            BinaryFunction operation)
1711    {
1712      // Interpolate if necessary and find an appropriate function space
1713      Data arg_0_Z, arg_1_Z;
1714      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1715        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1716          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1717          arg_1_Z = Data(arg_1);
1718        }
1719        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1720          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1721          arg_0_Z =Data(arg_0);
1722        }
1723        else {
1724          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1725        }
1726      } else {
1727          arg_0_Z = Data(arg_0);
1728          arg_1_Z = Data(arg_1);
1729      }
1730      // Get rank and shape of inputs
1731      int rank0 = arg_0_Z.getDataPointRank();
1732      int rank1 = arg_1_Z.getDataPointRank();
1733      DataArrayView::ShapeType shape0 = arg_0_Z.getDataPointShape();
1734      DataArrayView::ShapeType shape1 = arg_1_Z.getDataPointShape();
1735      int size0 = arg_0_Z.getDataPointSize();
1736      int size1 = arg_1_Z.getDataPointSize();
1737    
1738      // Declare output Data object
1739      Data res;
1740    
1741      if (shape0 == shape1) {
1742    
1743        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1744          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1745          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1746          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1747          double *ptr_2 = &((res.getPointDataView().getData())[0]);
1748          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1749        }
1750        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1751    
1752          // Prepare the DataConstant input
1753          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1754    
1755          // Borrow DataTagged input from Data object
1756          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1757    
1758          // Prepare a DataTagged output 2
1759          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1760          res.tag();
1761          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1762    
1763          // Prepare offset into DataConstant
1764          int offset_0 = tmp_0->getPointOffset(0,0);
1765          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1766          // Get the views
1767          DataArrayView view_1 = tmp_1->getDefaultValue();
1768          DataArrayView view_2 = tmp_2->getDefaultValue();
1769          // Get the pointers to the actual data
1770          double *ptr_1 = &((view_1.getData())[0]);
1771          double *ptr_2 = &((view_2.getData())[0]);
1772          // Compute a result for the default
1773          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1774          // Compute a result for each tag
1775          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1776          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1777          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1778            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
1779            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1780            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1781            double *ptr_1 = &view_1.getData(0);
1782            double *ptr_2 = &view_2.getData(0);
1783            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1784          }
1785    
1786        }
1787        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1788    
1789          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1790          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1791          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1792          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1793    
1794          int sampleNo_1,dataPointNo_1;
1795          int numSamples_1 = arg_1_Z.getNumSamples();
1796          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1797          int offset_0 = tmp_0->getPointOffset(0,0);
1798          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1799          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1800            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1801              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1802              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1803              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1804              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1805              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1806              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1807            }
1808          }
1809    
1810        }
1811        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1812    
1813          // Borrow DataTagged input from Data object
1814          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1815    
1816          // Prepare the DataConstant input
1817          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1818    
1819          // Prepare a DataTagged output 2
1820          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1821          res.tag();
1822          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1823    
1824          // Prepare offset into DataConstant
1825          int offset_1 = tmp_1->getPointOffset(0,0);
1826          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1827          // Get the views
1828          DataArrayView view_0 = tmp_0->getDefaultValue();
1829          DataArrayView view_2 = tmp_2->getDefaultValue();
1830          // Get the pointers to the actual data
1831          double *ptr_0 = &((view_0.getData())[0]);
1832          double *ptr_2 = &((view_2.getData())[0]);
1833          // Compute a result for the default
1834          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1835          // Compute a result for each tag
1836          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1837          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1838          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1839            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
1840            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1841            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1842            double *ptr_0 = &view_0.getData(0);
1843            double *ptr_2 = &view_2.getData(0);
1844            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1845          }
1846    
1847        }
1848        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1849    
1850          // Borrow DataTagged input from Data object
1851          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1852    
1853          // Borrow DataTagged input from Data object
1854          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1855    
1856          // Prepare a DataTagged output 2
1857          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1858          res.tag();        // DataTagged output
1859          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1860    
1861          // Get the views
1862          DataArrayView view_0 = tmp_0->getDefaultValue();
1863          DataArrayView view_1 = tmp_1->getDefaultValue();
1864          DataArrayView view_2 = tmp_2->getDefaultValue();
1865          // Get the pointers to the actual data
1866          double *ptr_0 = &((view_0.getData())[0]);
1867          double *ptr_1 = &((view_1.getData())[0]);
1868          double *ptr_2 = &((view_2.getData())[0]);
1869          // Compute a result for the default
1870          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1871          // Merge the tags
1872          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1873          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1874          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1875          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1876            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue()); // use tmp_2 to get correct shape
1877          }
1878          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1879            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
1880          }
1881          // Compute a result for each tag
1882          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1883          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1884            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1885            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1886            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1887            double *ptr_0 = &view_0.getData(0);
1888            double *ptr_1 = &view_1.getData(0);
1889            double *ptr_2 = &view_2.getData(0);
1890            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1891          }
1892    
1893        }
1894        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
1895    
1896          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1897          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1898          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1899          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1900          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1901    
1902          int sampleNo_0,dataPointNo_0;
1903          int numSamples_0 = arg_0_Z.getNumSamples();
1904          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1905          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1906          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1907            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
1908            double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1909            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1910              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
1911              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1912              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1913              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1914              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1915            }
1916          }
1917    
1918        }
1919        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
1920    
1921          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1922          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
1923          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1924          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1925    
1926          int sampleNo_0,dataPointNo_0;
1927          int numSamples_0 = arg_0_Z.getNumSamples();
1928          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1929          int offset_1 = tmp_1->getPointOffset(0,0);
1930          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1931          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1932            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1933              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
1934              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1935              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1936              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1937              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1938              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1939            }
1940          }
1941    
1942        }
1943        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
1944    
1945          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1946          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1947          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
1948          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1949          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1950    
1951          int sampleNo_0,dataPointNo_0;
1952          int numSamples_0 = arg_0_Z.getNumSamples();
1953          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1954          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1955          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1956            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
1957            double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1958            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1959              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
1960              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1961              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1962              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1963              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1964            }
1965          }
1966    
1967        }
1968        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
1969    
1970          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1971          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1972          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
1973          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1974          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1975    
1976          int sampleNo_0,dataPointNo_0;
1977          int numSamples_0 = arg_0_Z.getNumSamples();
1978          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1979          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1980          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1981            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1982              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
1983              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
1984              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1985              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1986              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1987              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1988              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1989            }
1990          }
1991    
1992        }
1993        else {
1994          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
1995        }
1996    
1997      } else if (0 == rank0) {
1998    
1999        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2000          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2001          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2002          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
2003          double *ptr_2 = &((res.getPointDataView().getData())[0]);
2004          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2005        }
2006        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2007    
2008          // Prepare the DataConstant input
2009          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2010    
2011          // Borrow DataTagged input from Data object
2012          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2013    
2014          // Prepare a DataTagged output 2
2015          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2016          res.tag();
2017          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2018    
2019          // Prepare offset into DataConstant
2020          int offset_0 = tmp_0->getPointOffset(0,0);
2021          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2022          // Get the views
2023          DataArrayView view_1 = tmp_1->getDefaultValue();
2024          DataArrayView view_2 = tmp_2->getDefaultValue();
2025          // Get the pointers to the actual data
2026          double *ptr_1 = &((view_1.getData())[0]);
2027          double *ptr_2 = &((view_2.getData())[0]);
2028          // Compute a result for the default
2029          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2030          // Compute a result for each tag
2031          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2032          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2033          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2034            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2035            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2036            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2037            double *ptr_1 = &view_1.getData(0);
2038            double *ptr_2 = &view_2.getData(0);
2039            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2040          }
2041    
2042        }
2043        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2044    
2045          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2046          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2047          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2048          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2049    
2050          int sampleNo_1,dataPointNo_1;
2051          int numSamples_1 = arg_1_Z.getNumSamples();
2052          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2053          int offset_0 = tmp_0->getPointOffset(0,0);
2054          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2055          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2056            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2057              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2058              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2059              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2060              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2061              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2062              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2063    
2064            }
2065          }
2066    
2067        }
2068        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2069    
2070          // Borrow DataTagged input from Data object
2071          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2072    
2073          // Prepare the DataConstant input
2074          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2075    
2076          // Prepare a DataTagged output 2
2077          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2078          res.tag();
2079          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2080    
2081          // Prepare offset into DataConstant
2082          int offset_1 = tmp_1->getPointOffset(0,0);
2083          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2084          // Get the views
2085          DataArrayView view_0 = tmp_0->getDefaultValue();
2086          DataArrayView view_2 = tmp_2->getDefaultValue();
2087          // Get the pointers to the actual data
2088          double *ptr_0 = &((view_0.getData())[0]);
2089          double *ptr_2 = &((view_2.getData())[0]);
2090          // Compute a result for the default
2091          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2092          // Compute a result for each tag
2093          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2094          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2095          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2096            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2097            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2098            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2099            double *ptr_0 = &view_0.getData(0);
2100            double *ptr_2 = &view_2.getData(0);
2101            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2102          }
2103    
2104        }
2105        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2106    
2107          // Borrow DataTagged input from Data object
2108          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2109    
2110          // Borrow DataTagged input from Data object
2111          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2112    
2113          // Prepare a DataTagged output 2
2114          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2115          res.tag();        // DataTagged output
2116          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2117    
2118          // Get the views
2119          DataArrayView view_0 = tmp_0->getDefaultValue();
2120          DataArrayView view_1 = tmp_1->getDefaultValue();
2121          DataArrayView view_2 = tmp_2->getDefaultValue();
2122          // Get the pointers to the actual data
2123          double *ptr_0 = &((view_0.getData())[0]);
2124          double *ptr_1 = &((view_1.getData())[0]);
2125          double *ptr_2 = &((view_2.getData())[0]);
2126          // Compute a result for the default
2127          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2128          // Merge the tags
2129          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2130          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2131          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2132          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2133            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue()); // use tmp_2 to get correct shape
2134          }
2135          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2136            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2137          }
2138          // Compute a result for each tag
2139          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2140          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2141            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2142            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2143            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2144            double *ptr_0 = &view_0.getData(0);
2145            double *ptr_1 = &view_1.getData(0);
2146            double *ptr_2 = &view_2.getData(0);
2147            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2148          }
2149    
2150        }
2151        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2152    
2153          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2154          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2155          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2156          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2157          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2158    
2159          int sampleNo_0,dataPointNo_0;
2160          int numSamples_0 = arg_0_Z.getNumSamples();
2161          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2162          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2163          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2164            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2165            double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2166            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2167              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2168              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2169              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2170              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2171              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2172            }
2173          }
2174    
2175        }
2176        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2177    
2178          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2179          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2180          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2181          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2182    
2183          int sampleNo_0,dataPointNo_0;
2184          int numSamples_0 = arg_0_Z.getNumSamples();
2185          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2186          int offset_1 = tmp_1->getPointOffset(0,0);
2187          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2188          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2189            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2190              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2191              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2192              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2193              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2194              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2195              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2196            }
2197          }
2198    
2199    
2200        }
2201        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2202    
2203          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2204          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2205          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2206          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2207          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2208    
2209          int sampleNo_0,dataPointNo_0;
2210          int numSamples_0 = arg_0_Z.getNumSamples();
2211          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2212          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2213          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2214            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2215            double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2216            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2217              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2218              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2219              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2220              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2221              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2222            }
2223          }
2224    
2225        }
2226        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2227    
2228          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2229          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2230          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2231          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2232          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2233    
2234          int sampleNo_0,dataPointNo_0;
2235          int numSamples_0 = arg_0_Z.getNumSamples();
2236          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2237          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2238          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2239            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2240              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2241              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2242              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2243              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2244              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2245              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2246              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2247            }
2248          }
2249    
2250        }
2251        else {
2252          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2253        }
2254    
2255      } else if (0 == rank1) {
2256    
2257        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2258          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2259          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2260          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
2261          double *ptr_2 = &((res.getPointDataView().getData())[0]);
2262          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2263        }
2264        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2265    
2266          // Prepare the DataConstant input
2267          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2268    
2269          // Borrow DataTagged input from Data object
2270          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2271    
2272          // Prepare a DataTagged output 2
2273          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2274          res.tag();
2275          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2276    
2277          // Prepare offset into DataConstant
2278          int offset_0 = tmp_0->getPointOffset(0,0);
2279          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2280          // Get the views
2281          DataArrayView view_1 = tmp_1->getDefaultValue();
2282          DataArrayView view_2 = tmp_2->getDefaultValue();
2283          // Get the pointers to the actual data
2284          double *ptr_1 = &((view_1.getData())[0]);
2285          double *ptr_2 = &((view_2.getData())[0]);
2286          // Compute a result for the default
2287          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2288          // Compute a result for each tag
2289          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2290          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2291          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2292            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2293            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2294            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2295            double *ptr_1 = &view_1.getData(0);
2296            double *ptr_2 = &view_2.getData(0);
2297            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2298          }
2299    
2300        }
2301        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2302    
2303          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2304          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2305          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2306          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2307    
2308          int sampleNo_1,dataPointNo_1;
2309          int numSamples_1 = arg_1_Z.getNumSamples();
2310          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2311          int offset_0 = tmp_0->getPointOffset(0,0);
2312          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2313          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2314            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2315              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2316              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2317              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2318              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2319              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2320              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2321            }
2322          }
2323    
2324        }
2325        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2326    
2327          // Borrow DataTagged input from Data object
2328          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2329    
2330          // Prepare the DataConstant input
2331          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2332    
2333          // Prepare a DataTagged output 2
2334          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2335          res.tag();
2336          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2337    
2338          // Prepare offset into DataConstant
2339          int offset_1 = tmp_1->getPointOffset(0,0);
2340          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2341          // Get the views
2342          DataArrayView view_0 = tmp_0->getDefaultValue();
2343          DataArrayView view_2 = tmp_2->getDefaultValue();
2344          // Get the pointers to the actual data
2345          double *ptr_0 = &((view_0.getData())[0]);
2346          double *ptr_2 = &((view_2.getData())[0]);
2347          // Compute a result for the default
2348          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2349          // Compute a result for each tag
2350          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2351          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2352          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2353            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2354            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2355            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2356            double *ptr_0 = &view_0.getData(0);
2357            double *ptr_2 = &view_2.getData(0);
2358            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2359          }
2360    
2361        }
2362        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2363    
2364          // Borrow DataTagged input from Data object
2365          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2366    
2367          // Borrow DataTagged input from Data object
2368          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2369    
2370          // Prepare a DataTagged output 2
2371          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2372          res.tag();        // DataTagged output
2373          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2374    
2375          // Get the views
2376          DataArrayView view_0 = tmp_0->getDefaultValue();
2377          DataArrayView view_1 = tmp_1->getDefaultValue();
2378          DataArrayView view_2 = tmp_2->getDefaultValue();
2379          // Get the pointers to the actual data
2380          double *ptr_0 = &((view_0.getData())[0]);
2381          double *ptr_1 = &((view_1.getData())[0]);
2382          double *ptr_2 = &((view_2.getData())[0]);
2383          // Compute a result for the default
2384          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2385          // Merge the tags
2386          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2387          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2388          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2389          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2390            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue()); // use tmp_2 to get correct shape
2391          }
2392          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2393            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2394          }
2395          // Compute a result for each tag
2396          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2397          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2398            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2399            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2400            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2401            double *ptr_0 = &view_0.getData(0);
2402            double *ptr_1 = &view_1.getData(0);
2403            double *ptr_2 = &view_2.getData(0);
2404            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2405          }
2406    
2407        }
2408        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2409    
2410          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2411          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2412          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2413          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2414          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2415    
2416          int sampleNo_0,dataPointNo_0;
2417          int numSamples_0 = arg_0_Z.getNumSamples();
2418          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2419          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2420          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2421            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2422            double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2423            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2424              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2425              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2426              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2427              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2428              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2429            }
2430          }
2431    
2432        }
2433        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2434    
2435          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2436          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2437          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2438          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2439    
2440          int sampleNo_0,dataPointNo_0;
2441          int numSamples_0 = arg_0_Z.getNumSamples();
2442          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2443          int offset_1 = tmp_1->getPointOffset(0,0);
2444          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2445          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2446            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2447              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2448              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2449              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2450              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2451              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2452              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2453            }
2454          }
2455    
2456    
2457        }
2458        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2459    
2460          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2461          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2462          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2463          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2464          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2465    
2466          int sampleNo_0,dataPointNo_0;
2467          int numSamples_0 = arg_0_Z.getNumSamples();
2468          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2469          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2470          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2471            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2472            double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2473            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2474              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2475              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2476              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2477              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2478              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2479            }
2480          }
2481    
2482        }
2483        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2484    
2485          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2486          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2487          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2488          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2489          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2490    
2491          int sampleNo_0,dataPointNo_0;
2492          int numSamples_0 = arg_0_Z.getNumSamples();
2493          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2494          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2495          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2496            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2497              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2498              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2499              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2500              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2501              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2502              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2503              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2504            }
2505          }
2506    
2507        }
2508        else {
2509          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2510        }
2511    
2512      } else {
2513        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2514      }
2515    
2516      return res;
2517    }
2518    
2519    template <typename UnaryFunction>
2520    Data
2521    C_TensorUnaryOperation(Data const &arg_0,
2522                           UnaryFunction operation)
2523    {
2524      // Interpolate if necessary and find an appropriate function space
2525      Data arg_0_Z = Data(arg_0);
2526    
2527      // Get rank and shape of inputs
2528      int rank0 = arg_0_Z.getDataPointRank();
2529      DataArrayView::ShapeType shape0 = arg_0_Z.getDataPointShape();
2530      int size0 = arg_0_Z.getDataPointSize();
2531    
2532      // Declare output Data object
2533      Data res;
2534    
2535      if (arg_0_Z.isConstant()) {
2536        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2537        double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2538        double *ptr_2 = &((res.getPointDataView().getData())[0]);
2539        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2540      }
2541      else if (arg_0_Z.isTagged()) {
2542    
2543        // Borrow DataTagged input from Data object
2544        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2545    
2546        // Prepare a DataTagged output 2
2547        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2548        res.tag();
2549        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2550    
2551        // Get the views
2552        DataArrayView view_0 = tmp_0->getDefaultValue();
2553        DataArrayView view_2 = tmp_2->getDefaultValue();
2554        // Get the pointers to the actual data
2555        double *ptr_0 = &((view_0.getData())[0]);
2556        double *ptr_2 = &((view_2.getData())[0]);
2557        // Compute a result for the default
2558        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2559        // Compute a result for each tag
2560        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2561        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2562        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2563          tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2564          DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2565          DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2566          double *ptr_0 = &view_0.getData(0);
2567          double *ptr_2 = &view_2.getData(0);
2568          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2569        }
2570    
2571      }
2572      else if (arg_0_Z.isExpanded()) {
2573    
2574        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2575        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2576        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2577    
2578        int sampleNo_0,dataPointNo_0;
2579        int numSamples_0 = arg_0_Z.getNumSamples();
2580        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2581        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2582        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2583          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2584            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2585            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2586            double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2587            double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2588            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2589          }
2590        }
2591    
2592      }
2593      else {
2594        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2595      }
2596    
2597      return res;
2598    }
2599    
2600  }  }
2601  #endif  #endif

Legend:
Removed from v.782  
changed lines
  Added in v.1334

  ViewVC Help
Powered by ViewVC 1.1.26