/[escript]/trunk/escript/src/Data.h
ViewVC logotype

Diff of /trunk/escript/src/Data.h

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

revision 922 by gross, Fri Jan 5 04:23:05 2007 UTC revision 1811 by ksteube, Thu Sep 25 23:11:13 2008 UTC
# Line 1  Line 1 
1  // $Id$  
2  /*  /*******************************************************
3   ************************************************************  *
4   *          Copyright 2006 by ACcESS MNRF                   *  * Copyright (c) 2003-2008 by University of Queensland
5   *                                                          *  * Earth Systems Science Computational Center (ESSCC)
6   *              http://www.access.edu.au                    *  * http://www.uq.edu.au/esscc
7   *       Primary Business: Queensland, Australia            *  *
8   *  Licensed under the Open Software License version 3.0    *  * Primary Business: Queensland, Australia
9   *     http://www.opensource.org/licenses/osl-3.0.php       *  * Licensed under the Open Software License version 3.0
10   *                                                          *  * http://www.opensource.org/licenses/osl-3.0.php
11   ************************************************************  *
12  */  *******************************************************/
13    
14    
15  /** \file Data.h */  /** \file Data.h */
16    
# Line 23  Line 24 
24  #include "BinaryOp.h"  #include "BinaryOp.h"
25  #include "UnaryOp.h"  #include "UnaryOp.h"
26  #include "DataException.h"  #include "DataException.h"
27    #include "DataTypes.h"
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  #ifndef PASO_MPI  #include "esysmpi.h"
 #define MPI_Comm long  
 #endif  
   
35  #include <string>  #include <string>
36  #include <algorithm>  #include <algorithm>
37    #include <sstream>
38    
39    
40  #include <boost/shared_ptr.hpp>  #include <boost/shared_ptr.hpp>
41  #include <boost/python/object.hpp>  #include <boost/python/object.hpp>
# Line 51  class DataExpanded; Line 52  class DataExpanded;
52    
53  /**  /**
54     \brief     \brief
55     Data creates the appropriate Data object for the given construction     Data represents a collection of datapoints.
    arguments.  
56    
57     Description:     Description:
58     Data is essentially a factory class which creates the appropriate Data     Internally, the datapoints are actually stored by a DataAbstract object.
59     object for the given construction arguments. It retains control over     The specific instance of DataAbstract used may vary over the lifetime
60     the object created for the lifetime of the object.     of the Data object.
61     The type of Data object referred to may change during the lifetime of     Some methods on this class return references (eg getShape()).
62     the Data object.     These references should not be used after an operation which changes the underlying DataAbstract object.
63       Doing so will lead to invalid memory access.
64       This should not affect any methods exposed via boost::python.
65  */  */
66  class Data {  class Data {
67    
# 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 254  class Data { Line 250  class Data {
250    ESCRIPT_DLL_API    ESCRIPT_DLL_API
251    bool    bool
252    isProtected() const;    isProtected() const;
253    
254    /**    /**
255       \brief       \brief
256       Return the values of all data-points as a single python numarray object.       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
260    convertToNumArray();    getValueOfDataPoint(int dataPointNo);
261    
262    /**    /**
263       \brief       \brief
264       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
265    */    */
266    ESCRIPT_DLL_API    ESCRIPT_DLL_API
267    void    void
268    fillFromNumArray(const boost::python::numeric::array);    setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
   
   /**  
      \brief  
      Return the values of a data point on this process  
   */  
   ESCRIPT_DLL_API  
   const boost::python::numeric::array  
   getValueOfDataPoint(int dataPointNo);  
269    
270    /**    /**
271       \brief       \brief
272       sets the values of a data-point on this process       sets the values of a data-point from a numarray object on this process
273    */    */
274    ESCRIPT_DLL_API    ESCRIPT_DLL_API
275    void    void
276    setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array);    setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
277    
278    /**    /**
279       \brief       \brief
# Line 306  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 321  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 331  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 400  class Data { Line 395  class Data {
395    
396    /**    /**
397       \brief       \brief
398       Return true if this Data is empty.       Return true if this Data holds an instance of DataEmpty. This is _not_ the same as asking if the object
399    contains datapoints.
400    */    */
401    ESCRIPT_DLL_API    ESCRIPT_DLL_API
402    bool    bool
# Line 455  class Data { Line 451  class Data {
451    int    int
452    getDataPointRank() const    getDataPointRank() const
453    {    {
454      return m_data->getPointDataView().getRank();  //    return m_data->getPointDataView().getRank();
455        return m_data->getRank();
456    }    }
457    
458    /**    /**
# Line 493  class Data { Line 490  class Data {
490      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
491    }    }
492    
493    
494      /**
495        \brief
496        Return the number of values in the shape for this object.
497      */
498      ESCRIPT_DLL_API
499      int
500      getNoValues() const
501      {
502        return m_data->getNoValues();
503      }
504    
505    
506      /**
507         \brief
508         dumps the object into a netCDF file
509      */
510      ESCRIPT_DLL_API
511      void
512      dump(const std::string fileName) const;
513    /**    /**
514       \brief       \brief
515       Return the sample data for the given sample no. This is not the       Return the sample data for the given sample no. This is not the
# Line 521  class Data { Line 538  class Data {
538      return m_data->getSampleDataByTag(tag);      return m_data->getSampleDataByTag(tag);
539    }    }
540    
541    /**  //  /**
542       \brief  /*     \brief
543       Assign the given value to the data-points referenced by the given       Return a view into the data for the data point specified.
544       reference number.       NOTE: Construction of the DataArrayView is a relatively expensive
545         operation.
546       The value supplied is a python numarray object.  The data from this numarray       \param sampleNo - Input -
547       is unpacked into a DataArray, and this is used to set the corresponding       \param dataPointNo - Input -*/
548       data-points in the underlying Data object.  //  */
549    //   ESCRIPT_DLL_API
550    //   inline
551    //   DataArrayView
552    //   getDataPoint(int sampleNo,
553    //                int dataPointNo)
554    //   {
555    //                 return m_data->getDataPoint(sampleNo,dataPointNo);
556    //   }
557    
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
558    
559       \param ref - Input - reference number.    /**
560       \param value - Input - value to assign to data-points associated with       \brief
561                              the given reference number.       Return a view into the data for the data point specified.
562         NOTE: Construction of the DataArrayView is a relatively expensive
563         operation.
564         \param sampleNo - Input -
565         \param dataPointNo - Input -
566    */    */
567    ESCRIPT_DLL_API    ESCRIPT_DLL_API
568    void    DataTypes::ValueType::const_reference
569    setRefValue(int ref,    getDataPoint(int sampleNo, int dataPointNo) const;
               const boost::python::numeric::array& value);  
570    
   /**  
      \brief  
      Return the values associated with the data-points referenced by the given  
      reference number.  
571    
572       The value supplied is a python numarray object. The data from the corresponding    ESCRIPT_DLL_API
573       data-points in this Data object are packed into the given numarray object.    DataTypes::ValueType::reference
574      getDataPoint(int sampleNo, int dataPointNo);
575    
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
576    
      \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);  
577    
578    /**    /**
579       \brief       \brief
580       Return a view into the data for the data point specified.       Return the offset for the given sample and point within the sample
      NOTE: Construction of the DataArrayView is a relatively expensive  
      operation.  
      \param sampleNo - Input -  
      \param dataPointNo - Input -  
581    */    */
582    ESCRIPT_DLL_API    ESCRIPT_DLL_API
583    inline    inline
584    DataArrayView    DataTypes::ValueType::size_type
585    getDataPoint(int sampleNo,    getDataOffset(int sampleNo,
586                 int dataPointNo)                 int dataPointNo)
587    {    {
588          return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getPointOffset(sampleNo,dataPointNo);
589    }    }
590    
591    /**    /**
# Line 584  class Data { Line 593  class Data {
593       Return a reference to the data point shape.       Return a reference to the data point shape.
594    */    */
595    ESCRIPT_DLL_API    ESCRIPT_DLL_API
596    const DataArrayView::ShapeType&    inline
597    getDataPointShape() const;    const DataTypes::ShapeType&
598      getDataPointShape() const
599      {
600        return m_data->getShape();
601      }
602    
603    /**    /**
604       \brief       \brief
# Line 609  class Data { Line 622  class Data {
622       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
623    */    */
624    ESCRIPT_DLL_API    ESCRIPT_DLL_API
625    DataArrayView::ValueType::size_type    DataTypes::ValueType::size_type
626    getLength() const;    getLength() const;
627    
628    
629    
630    /**    /**
631       \brief       \brief
632       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag assocciated with name. Implicitly converts this
633       object to type DataTagged. Throws an exception if this object       object to type DataTagged. Throws an exception if this object
634       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
635         \param tagKey - Input - Integer key.
636         \param value - Input - Value to associate with given key.
637        ==>*
638      */
639      ESCRIPT_DLL_API
640      void
641      setTaggedValueByName(std::string name,
642                           const boost::python::object& value);
643    
644      /**
645         \brief
646         Assign the given value to the tag. Implicitly converts this
647         object to type DataTagged if it is constant.
648    
649       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
650       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
651      ==>*      ==>*
# Line 626  class Data { Line 655  class Data {
655    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
656                   const boost::python::object& value);                   const boost::python::object& value);
657    
658    
659    //  /**
660    //     \brief
661    //     Assign the given value to the tag. Implicitly converts this
662    //     object to type DataTagged if it is constant.
663    //
664    //     \param tagKey - Input - Integer key.
665    //     \param value - Input - Value to associate with given key.
666    //    ==>*
667    //  */
668    //   ESCRIPT_DLL_API
669    //   void
670    //   setTaggedValueFromCPP(int tagKey,
671    //                         const DataArrayView& value);
672    
673    /**    /**
674       \brief       \brief
675       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
676       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
677       cannot be converted to a DataTagged object.  
678       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
679         \param pointshape - Input - The shape of the value parameter
680       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
681      ==>*       \param dataOffset - Input - Offset of the begining of the point within the value parameter
682    */    */
683    ESCRIPT_DLL_API    ESCRIPT_DLL_API
684    void    void
685    setTaggedValueFromCPP(int tagKey,    setTaggedValueFromCPP(int tagKey,
686                          const DataArrayView& value);              const DataTypes::ShapeType& pointshape,
687                            const DataTypes::ValueType& value,
688                int dataOffset=0);
689    
690    
691    
692    /**    /**
693      \brief      \brief
# Line 655  class Data { Line 704  class Data {
704    
705    /**    /**
706       \brief       \brief
707         set all values to zero
708         *
709      */
710      ESCRIPT_DLL_API
711      void
712      setToZero();
713    
714      /**
715         \brief
716       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
717       the result as a Data object.       the result as a Data object.
718       *       *
# Line 662  class Data { Line 720  class Data {
720    ESCRIPT_DLL_API    ESCRIPT_DLL_API
721    Data    Data
722    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
723    /**    /**
724       \brief       \brief
725       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
# Line 759  class Data { Line 816  class Data {
816    
817    /**    /**
818       \brief       \brief
      Return the minimum absolute value of this Data object.  
      *  
   */  
   ESCRIPT_DLL_API  
   double  
   Linf() const;  
   
   /**  
      \brief  
819       Return the maximum value of this Data object.       Return the maximum value of this Data object.
820       *       *
821    */    */
# Line 882  class Data { Line 930  class Data {
930    /**    /**
931       \brief       \brief
932       Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.       Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.
933       the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than       the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than
934       tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the       tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the
935       first non-zero entry is positive.       first non-zero entry is positive.
936       Currently this function is restricted to rank 2, square shape, and dimension 3       Currently this function is restricted to rank 2, square shape, and dimension 3
937       *       *
# Line 1087  class Data { Line 1135  class Data {
1135    /**    /**
1136       \brief       \brief
1137       Return the given power of each data point of this boost python object.       Return the given power of each data point of this boost python object.
1138        
1139       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1140       *       *
1141     */     */
# Line 1098  class Data { Line 1146  class Data {
1146    /**    /**
1147       \brief       \brief
1148       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.
1149        
1150       \param left Input - the bases       \param left Input - the bases
1151       *       *
1152     */     */
# Line 1134  class Data { Line 1182  class Data {
1182    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1183    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1184    
1185      ESCRIPT_DLL_API
1186      Data& operator=(const Data& other);
1187    
1188    /**    /**
1189       \brief       \brief
1190       Overloaded operator -=       Overloaded operator -=
# Line 1226  class Data { Line 1277  class Data {
1277    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1278    inline    inline
1279    void    void
1280    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1281    
1282    /**    /**
1283       \brief       \brief
# Line 1237  class Data { Line 1288  class Data {
1288    */    */
1289    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1290    Data    Data
1291    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataTypes::RegionType& region) const;
1292    
1293    /**    /**
1294       \brief       \brief
# Line 1250  class Data { Line 1301  class Data {
1301    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1302    void    void
1303    setSlice(const Data& value,    setSlice(const Data& value,
1304             const DataArrayView::RegionType& region);             const DataTypes::RegionType& region);
1305    
1306    /**    /**
1307       \brief       \brief
1308       Archive the current Data object to the given file.       print the data values to stdout. Used for debugging
      \param fileName - Input - file to archive to.  
1309    */    */
1310    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1311    void    void
1312    archiveData(const std::string fileName);          print(void);
1313    
1314    /**    /**
1315       \brief       \brief
1316       Extract the Data object archived in the given file, overwriting       return the MPI rank number of the local data
1317       the current Data object.                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1318       Note - the current object must be of type DataEmpty.                   is returned
      \param fileName - Input - file to extract from.  
      \param fspace - Input - a suitable FunctionSpace descibing the data.  
1319    */    */
1320    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1321    void          int
1322    extractData(const std::string fileName,          get_MPIRank(void) const;
               const FunctionSpace& fspace);  
   
1323    
1324    /**    /**
1325       \brief       \brief
1326       print the data values to stdout. Used for debugging       return the MPI rank number of the local data
1327                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1328                     is returned
1329    */    */
1330    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1331    void          int
1332      print(void);          get_MPISize(void) const;
1333    
1334    /**    /**
1335       \brief       \brief
1336       return the MPI rank number of the local data       return the MPI rank number of the local data
1337           MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()                   MPI_COMM_WORLD is assumed and returned.
          is returned  
1338    */    */
1339    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1340      int          MPI_Comm
1341      get_MPIRank(void) const;          get_MPIComm(void) const;
1342    
1343    /**    /**
1344       \brief       \brief
1345       return the MPI rank number of the local data       return the object produced by the factory, which is a DataConstant or DataExpanded
1346           MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()      TODO Ownership of this object should be explained in doco.
          is returned  
1347    */    */
1348    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1349      int          DataAbstract*
1350      get_MPISize(void) const;          borrowData(void) const;
1351    
1352    
1353    /**    /**
1354       \brief       \brief
1355       return the MPI rank number of the local data       Return a pointer to the beginning of the datapoint at the specified offset.
1356           MPI_COMM_WORLD is assumed and returned.       TODO Eventually these should be inlined.
1357         \param i - position(offset) in the underlying datastructure
1358    */    */
1359    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1360      MPI_Comm          DataTypes::ValueType::const_reference
1361      get_MPIComm(void) const;          getDataAtOffset(DataTypes::ValueType::size_type i) const;
1362    
1363    
   /**  
      \brief  
      return the object produced by the factory, which is a DataConstant or DataExpanded  
   */  
1364    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1365      DataAbstract*          DataTypes::ValueType::reference
1366      borrowData(void) const;          getDataAtOffset(DataTypes::ValueType::size_type i);
1367    
1368   protected:   protected:
1369    
# Line 1395  class Data { Line 1440  class Data {
1440       \brief       \brief
1441       Construct a Data object of the appropriate type.       Construct a Data object of the appropriate type.
1442    */    */
1443    template <class IValueType>  
1444    void    void
1445    initialise(const IValueType& value,    initialise(const DataTypes::ValueType& value,
1446             const DataTypes::ShapeType& shape,
1447               const FunctionSpace& what,               const FunctionSpace& what,
1448               bool expanded);               bool expanded);
1449    
1450      void
1451      initialise(const boost::python::numeric::array& value,
1452                     const FunctionSpace& what,
1453                     bool expanded);
1454    
1455    //    //
1456    // flag to protect the data object against any update    // flag to protect the data object against any update
1457    bool m_protected;    bool m_protected;
# Line 1409  class Data { Line 1460  class Data {
1460    // pointer to the actual data object    // pointer to the actual data object
1461    boost::shared_ptr<DataAbstract> m_data;    boost::shared_ptr<DataAbstract> m_data;
1462    
   //  
   // pointer to the internal profiling data  
   struct profDataEntry *profData;  
   
1463  };  };
1464    
1465  template <class IValueType>  
1466  void  
1467  Data::initialise(const IValueType& value,  /**
1468                   const FunctionSpace& what,     Modify a filename for MPI parallel output to multiple files
1469                   bool expanded)  */
1470  {  char *Escript_MPI_appendRankToFileName(const char *, int, int);
   //  
   // Construct a Data object of the appropriate type.  
   // Construct the object first as there seems to be a bug which causes  
   // undefined behaviour if an exception is thrown during construction  
   // within the shared_ptr constructor.  
   if (expanded) {  
     DataAbstract* temp=new DataExpanded(value,what);  
     boost::shared_ptr<DataAbstract> temp_data(temp);  
     m_data=temp_data;  
   } else {  
     DataAbstract* temp=new DataConstant(value,what);  
     boost::shared_ptr<DataAbstract> temp_data(temp);  
     m_data=temp_data;  
   }  
 }  
1471    
1472  /**  /**
1473     Binary Data object operators.     Binary Data object operators.
1474  */  */
1475  inline double rpow(double x,double y)  inline double rpow(double x,double y)
1476  {  {
1477      return pow(y,x);      return pow(y,x);
1478  };  }
1479    
1480  /**  /**
1481    \brief    \brief
# Line 1537  ESCRIPT_DLL_API Data operator*(const boo Line 1569  ESCRIPT_DLL_API Data operator*(const boo
1569  */  */
1570  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);
1571    
1572    
1573    
1574  /**  /**
1575    \brief    \brief
1576    Output operator    Output operator
# Line 1558  C_GeneralTensorProduct(Data& arg0, Line 1592  C_GeneralTensorProduct(Data& arg0,
1592                       int axis_offset=0,                       int axis_offset=0,
1593                       int transpose=0);                       int transpose=0);
1594    
1595  /**  
1596    \brief  
1597    // /**
1598    /*  \brief
1599    Return true if operands are equivalent, else return false.    Return true if operands are equivalent, else return false.
1600    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
1601    be relied on. Requires further implementation.    be relied on. Requires further implementation.*/
1602  */  //*/
1603  //ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);  // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1604    
1605  /**  /**
1606    \brief    \brief
# Line 1579  Data::binaryOp(const Data& right, Line 1615  Data::binaryOp(const Data& right,
1615  {  {
1616     //     //
1617     // if this has a rank of zero promote it to the rank of the RHS     // if this has a rank of zero promote it to the rank of the RHS
1618     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1619       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.");
1620     }     }
1621     //     //
# Line 1588  Data::binaryOp(const Data& right, Line 1624  Data::binaryOp(const Data& right,
1624     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1625       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1626         //         //
1627         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1628         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1629       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1630         //         //
# Line 1632  Data::binaryOp(const Data& right, Line 1668  Data::binaryOp(const Data& right,
1668       EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");       EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1669       escript::binaryOp(*leftC,*rightC,operation);       escript::binaryOp(*leftC,*rightC,operation);
1670     }     }
    #if defined DOPROF  
    profData->binary++;  
    #endif  
 }  
   
 /**  
   \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);  
   }  
1671  }  }
1672    
1673  /**  /**
# Line 1707  Data::algorithm(BinaryFunction operation Line 1694  Data::algorithm(BinaryFunction operation
1694      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1695      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1696      return escript::algorithm(*leftC,operation,initial_value);      return escript::algorithm(*leftC,operation,initial_value);
1697      } else if (isEmpty()) {
1698        throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1699    }    }
1700    return 0;    return 0;
1701  }  }
# Line 1715  Data::algorithm(BinaryFunction operation Line 1704  Data::algorithm(BinaryFunction operation
1704    \brief    \brief
1705    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.
1706    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1707    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
1708    rank 0 Data object.    rank 0 Data object.
1709    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1710  */  */
# Line 1724  inline Line 1713  inline
1713  Data  Data
1714  Data::dp_algorithm(BinaryFunction operation, double initial_value) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1715  {  {
1716    if (isExpanded()) {    if (isEmpty()) {
1717      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1718      }
1719      else if (isExpanded()) {
1720        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1721      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1722      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1723      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1724      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1725      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1726      return result;      return result;
1727    } else if (isTagged()) {    }
1728      else if (isTagged()) {
1729      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());  
1730      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1731      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      DataTypes::ValueType defval(1);
1732        defval[0]=0;
1733        DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1734      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1735      return result;      return Data(resultT);   // note: the Data object now owns the resultT pointer
1736    } else if (isConstant()) {    }
1737      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());    else if (isConstant()) {
1738        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1739      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1740      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1741      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
# Line 1764  Data::dp_algorithm(BinaryFunction operat Line 1747  Data::dp_algorithm(BinaryFunction operat
1747    return falseRetVal;    return falseRetVal;
1748  }  }
1749    
1750    /**
1751      \brief
1752      Compute a tensor operation with two Data objects
1753      \param arg0 - Input - Data object
1754      \param arg1 - Input - Data object
1755      \param operation - Input - Binary op functor
1756    */
1757    template <typename BinaryFunction>
1758    inline
1759    Data
1760    C_TensorBinaryOperation(Data const &arg_0,
1761                            Data const &arg_1,
1762                            BinaryFunction operation)
1763    {
1764      if (arg_0.isEmpty() || arg_1.isEmpty())
1765      {
1766         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1767      }
1768      // Interpolate if necessary and find an appropriate function space
1769      Data arg_0_Z, arg_1_Z;
1770      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1771        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1772          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1773          arg_1_Z = Data(arg_1);
1774        }
1775        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1776          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1777          arg_0_Z =Data(arg_0);
1778        }
1779        else {
1780          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1781        }
1782      } else {
1783          arg_0_Z = Data(arg_0);
1784          arg_1_Z = Data(arg_1);
1785      }
1786      // Get rank and shape of inputs
1787      int rank0 = arg_0_Z.getDataPointRank();
1788      int rank1 = arg_1_Z.getDataPointRank();
1789      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1790      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1791      int size0 = arg_0_Z.getDataPointSize();
1792      int size1 = arg_1_Z.getDataPointSize();
1793    
1794      // Declare output Data object
1795      Data res;
1796    
1797      if (shape0 == shape1) {
1798    
1799        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1800          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1801    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1802          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1803          double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1804          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1805          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1806          double *ptr_2 = &(res.getDataAtOffset(0));
1807    
1808          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1809        }
1810        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1811    
1812          // Prepare the DataConstant input
1813          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1814    
1815          // Borrow DataTagged input from Data object
1816          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1817    
1818          // Prepare a DataTagged output 2
1819          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1820          res.tag();
1821          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1822    
1823          // Prepare offset into DataConstant
1824          int offset_0 = tmp_0->getPointOffset(0,0);
1825          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1826          // Get the views
1827    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1828    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1829    //       // Get the pointers to the actual data
1830    //       double *ptr_1 = &((view_1.getData())[0]);
1831    //       double *ptr_2 = &((view_2.getData())[0]);
1832    
1833          // Get the pointers to the actual data
1834          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1835          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1836    
1837          // Compute a result for the default
1838          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1839          // Compute a result for each tag
1840          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1841          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1842          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1843            tmp_2->addTag(i->first);
1844    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1845            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1846            double *ptr_1 = &view_1.getData(0);
1847            double *ptr_2 = &view_2.getData(0);*/
1848            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1849            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1850    
1851            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1852          }
1853    
1854        }
1855        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1856    
1857          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1858          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1859          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1860          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1861    
1862          int sampleNo_1,dataPointNo_1;
1863          int numSamples_1 = arg_1_Z.getNumSamples();
1864          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1865          int offset_0 = tmp_0->getPointOffset(0,0);
1866          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1867          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1868            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1869              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1870              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1871    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1872    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1873    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1874    
1875              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1876              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1877              double *ptr_2 = &(res.getDataAtOffset(offset_2));
1878              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1879            }
1880          }
1881    
1882        }
1883        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1884    
1885          // Borrow DataTagged input from Data object
1886          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1887    
1888          // Prepare the DataConstant input
1889          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1890    
1891          // Prepare a DataTagged output 2
1892          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1893          res.tag();
1894          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1895    
1896          // Prepare offset into DataConstant
1897          int offset_1 = tmp_1->getPointOffset(0,0);
1898    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1899          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1900          // Get the views
1901    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1902    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1903    //       // Get the pointers to the actual data
1904    //       double *ptr_0 = &((view_0.getData())[0]);
1905    //       double *ptr_2 = &((view_2.getData())[0]);
1906          // Get the pointers to the actual data
1907          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1908          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1909          // Compute a result for the default
1910          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1911          // Compute a result for each tag
1912          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1913          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1914          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1915            tmp_2->addTag(i->first);
1916    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1917    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1918    //         double *ptr_0 = &view_0.getData(0);
1919    //         double *ptr_2 = &view_2.getData(0);
1920            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1921            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1922            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1923          }
1924    
1925        }
1926        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1927    
1928          // Borrow DataTagged input from Data object
1929          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1930    
1931          // Borrow DataTagged input from Data object
1932          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1933    
1934          // Prepare a DataTagged output 2
1935          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1936          res.tag();        // DataTagged output
1937          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1938    
1939    //       // Get the views
1940    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1941    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1942    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1943    //       // Get the pointers to the actual data
1944    //       double *ptr_0 = &((view_0.getData())[0]);
1945    //       double *ptr_1 = &((view_1.getData())[0]);
1946    //       double *ptr_2 = &((view_2.getData())[0]);
1947    
1948          // Get the pointers to the actual data
1949          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1950          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1951          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1952    
1953          // Compute a result for the default
1954          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1955          // Merge the tags
1956          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1957          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1958          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1959          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1960            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
1961          }
1962          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1963            tmp_2->addTag(i->first);
1964          }
1965          // Compute a result for each tag
1966          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1967          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1968    
1969    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1970    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1971    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1972    //         double *ptr_0 = &view_0.getData(0);
1973    //         double *ptr_1 = &view_1.getData(0);
1974    //         double *ptr_2 = &view_2.getData(0);
1975    
1976            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1977            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1978            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1979    
1980            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1981          }
1982    
1983        }
1984        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
1985    
1986          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1987          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1988          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1989          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1990          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1991    
1992          int sampleNo_0,dataPointNo_0;
1993          int numSamples_0 = arg_0_Z.getNumSamples();
1994          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1995          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1996          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1997            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
1998            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1999            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2000              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2001              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2002    
2003    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2004    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2005              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2006              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2007    
2008    
2009              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2010            }
2011          }
2012    
2013        }
2014        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2015    
2016          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2017          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2018          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2019          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2020    
2021          int sampleNo_0,dataPointNo_0;
2022          int numSamples_0 = arg_0_Z.getNumSamples();
2023          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2024          int offset_1 = tmp_1->getPointOffset(0,0);
2025          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2026          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2027            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2028              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2029              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2030    
2031    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2032    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2033    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2034    
2035              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2036              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2037              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2038    
2039    
2040              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2041            }
2042          }
2043    
2044        }
2045        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2046    
2047          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2048          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2049          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2050          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2051          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2052    
2053          int sampleNo_0,dataPointNo_0;
2054          int numSamples_0 = arg_0_Z.getNumSamples();
2055          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2056          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2057          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2058            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2059            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2060            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2061              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2062              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2063              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2064              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2065              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2066            }
2067          }
2068    
2069        }
2070        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2071    
2072          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2073          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2074          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2075          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2076          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2077    
2078          int sampleNo_0,dataPointNo_0;
2079          int numSamples_0 = arg_0_Z.getNumSamples();
2080          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2081          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2082          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2083            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2084              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2085              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2086              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2087              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2088              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2089              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2090              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2091            }
2092          }
2093    
2094        }
2095        else {
2096          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2097        }
2098    
2099      } else if (0 == rank0) {
2100    
2101        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2102          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2103          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2104          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2105          double *ptr_2 = &(res.getDataAtOffset(0));
2106          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2107        }
2108        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2109    
2110          // Prepare the DataConstant input
2111          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2112    
2113          // Borrow DataTagged input from Data object
2114          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2115    
2116          // Prepare a DataTagged output 2
2117          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2118          res.tag();
2119          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2120    
2121          // Prepare offset into DataConstant
2122          int offset_0 = tmp_0->getPointOffset(0,0);
2123          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2124          // Get the views
2125    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2126    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2127    //       // Get the pointers to the actual data
2128    //       double *ptr_1 = &((view_1.getData())[0]);
2129    //       double *ptr_2 = &((view_2.getData())[0]);
2130           double *ptr_1 = &(tmp_1->getDefaultValue(0));
2131           double *ptr_2 = &(tmp_2->getDefaultValue(0));
2132    
2133          // Compute a result for the default
2134          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2135          // Compute a result for each tag
2136          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2137          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2138          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2139            tmp_2->addTag(i->first);
2140    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2141    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2142    //         double *ptr_1 = &view_1.getData(0);
2143    //         double *ptr_2 = &view_2.getData(0);
2144            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2145            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2146            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2147          }
2148    
2149        }
2150        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2151    
2152          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2153          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2154          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2155          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2156    
2157          int sampleNo_1,dataPointNo_1;
2158          int numSamples_1 = arg_1_Z.getNumSamples();
2159          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2160          int offset_0 = tmp_0->getPointOffset(0,0);
2161          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2162          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2163            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2164              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2165              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2166              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2167              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2168              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2169              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2170    
2171            }
2172          }
2173    
2174        }
2175        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2176    
2177          // Borrow DataTagged input from Data object
2178          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2179    
2180          // Prepare the DataConstant input
2181          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2182    
2183          // Prepare a DataTagged output 2
2184          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2185          res.tag();
2186          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2187    
2188          // Prepare offset into DataConstant
2189          int offset_1 = tmp_1->getPointOffset(0,0);
2190    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2191          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2192          // Get the views
2193    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2194          DataArrayView view_2 = tmp_2->getDefaultValue();
2195          // Get the pointers to the actual data
2196          double *ptr_0 = &((view_0.getData())[0]);
2197          double *ptr_2 = &((view_2.getData())[0]);*/
2198    
2199          // Get the pointers to the actual data
2200          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2201          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2202    
2203    
2204          // Compute a result for the default
2205          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2206          // Compute a result for each tag
2207          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2208          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2209          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2210            tmp_2->addTag(i->first);
2211    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2212            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2213            double *ptr_0 = &view_0.getData(0);
2214            double *ptr_2 = &view_2.getData(0);*/
2215            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2216            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2217    
2218            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2219          }
2220    
2221        }
2222        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2223    
2224          // Borrow DataTagged input from Data object
2225          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2226    
2227          // Borrow DataTagged input from Data object
2228          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2229    
2230          // Prepare a DataTagged output 2
2231          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2232          res.tag();        // DataTagged output
2233          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2234    
2235          // Get the views
2236    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2237          DataArrayView view_1 = tmp_1->getDefaultValue();
2238          DataArrayView view_2 = tmp_2->getDefaultValue();
2239          // Get the pointers to the actual data
2240          double *ptr_0 = &((view_0.getData())[0]);
2241          double *ptr_1 = &((view_1.getData())[0]);
2242          double *ptr_2 = &((view_2.getData())[0]);*/
2243    
2244          // Get the pointers to the actual data
2245          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2246          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2247          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2248    
2249    
2250          // Compute a result for the default
2251          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2252          // Merge the tags
2253          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2254          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2255          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2256          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2257            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2258          }
2259          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2260            tmp_2->addTag(i->first);
2261          }
2262          // Compute a result for each tag
2263          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2264          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2265    
2266    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2267            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2268            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2269            double *ptr_0 = &view_0.getData(0);
2270            double *ptr_1 = &view_1.getData(0);
2271            double *ptr_2 = &view_2.getData(0);*/
2272    
2273            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2274            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2275            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2276    
2277            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2278          }
2279    
2280        }
2281        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2282    
2283          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2284          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2285          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2286          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2287          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2288    
2289          int sampleNo_0,dataPointNo_0;
2290          int numSamples_0 = arg_0_Z.getNumSamples();
2291          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2292          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2293          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2294            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2295            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2296            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2297              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2298              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2299              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2300              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2301              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2302            }
2303          }
2304    
2305        }
2306        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2307    
2308          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2309          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2310          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2311          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2312    
2313          int sampleNo_0,dataPointNo_0;
2314          int numSamples_0 = arg_0_Z.getNumSamples();
2315          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2316          int offset_1 = tmp_1->getPointOffset(0,0);
2317          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2318          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2319            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2320              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2321              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2322              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2323              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2324              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2325              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2326            }
2327          }
2328    
2329    
2330        }
2331        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2332    
2333          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2334          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2335          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2336          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2337          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2338    
2339          int sampleNo_0,dataPointNo_0;
2340          int numSamples_0 = arg_0_Z.getNumSamples();
2341          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2342          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2343          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2344            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2345            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2346            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2347              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2348              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2349              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2350              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2351              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2352            }
2353          }
2354    
2355        }
2356        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2357    
2358          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2359          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2360          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2361          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2362          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2363    
2364          int sampleNo_0,dataPointNo_0;
2365          int numSamples_0 = arg_0_Z.getNumSamples();
2366          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2367          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2368          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2369            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2370              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2371              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2372              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2373              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2374              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2375              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2376              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2377            }
2378          }
2379    
2380        }
2381        else {
2382          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2383        }
2384    
2385      } else if (0 == rank1) {
2386    
2387        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2388          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2389          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2390          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2391          double *ptr_2 = &(res.getDataAtOffset(0));
2392          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2393        }
2394        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2395    
2396          // Prepare the DataConstant input
2397          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2398    
2399          // Borrow DataTagged input from Data object
2400          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2401    
2402          // Prepare a DataTagged output 2
2403          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2404          res.tag();
2405          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2406    
2407          // Prepare offset into DataConstant
2408          int offset_0 = tmp_0->getPointOffset(0,0);
2409          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2410          // Get the views
2411    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2412          DataArrayView view_2 = tmp_2->getDefaultValue();
2413          // Get the pointers to the actual data
2414          double *ptr_1 = &((view_1.getData())[0]);
2415          double *ptr_2 = &((view_2.getData())[0]);*/
2416          //Get the pointers to the actual data
2417          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2418          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2419    
2420          // Compute a result for the default
2421          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2422          // Compute a result for each tag
2423          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2424          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2425          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2426            tmp_2->addTag(i->first);
2427    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2428    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2429    //         double *ptr_1 = &view_1.getData(0);
2430    //         double *ptr_2 = &view_2.getData(0);
2431            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2432            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2433    
2434    
2435            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2436          }
2437    
2438        }
2439        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2440    
2441          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2442          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2443          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2444          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2445    
2446          int sampleNo_1,dataPointNo_1;
2447          int numSamples_1 = arg_1_Z.getNumSamples();
2448          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2449          int offset_0 = tmp_0->getPointOffset(0,0);
2450          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2451          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2452            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2453              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2454              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2455              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2456              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2457              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2458              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2459            }
2460          }
2461    
2462        }
2463        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2464    
2465          // Borrow DataTagged input from Data object
2466          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2467    
2468          // Prepare the DataConstant input
2469          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2470    
2471          // Prepare a DataTagged output 2
2472          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2473          res.tag();
2474          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2475    
2476          // Prepare offset into DataConstant
2477          int offset_1 = tmp_1->getPointOffset(0,0);
2478          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2479          // Get the views
2480    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2481    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2482    //       // Get the pointers to the actual data
2483    //       double *ptr_0 = &((view_0.getData())[0]);
2484    //       double *ptr_2 = &((view_2.getData())[0]);
2485          // Get the pointers to the actual data
2486          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2487          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2488          // Compute a result for the default
2489          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2490          // Compute a result for each tag
2491          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2492          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2493          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2494            tmp_2->addTag(i->first);
2495    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2496            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2497            double *ptr_0 = &view_0.getData(0);
2498            double *ptr_2 = &view_2.getData(0);*/
2499            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2500            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2501            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2502          }
2503    
2504        }
2505        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2506    
2507          // Borrow DataTagged input from Data object
2508          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2509    
2510          // Borrow DataTagged input from Data object
2511          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2512    
2513          // Prepare a DataTagged output 2
2514          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2515          res.tag();        // DataTagged output
2516          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2517    
2518          // Get the views
2519    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2520    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2521    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2522    //       // Get the pointers to the actual data
2523    //       double *ptr_0 = &((view_0.getData())[0]);
2524    //       double *ptr_1 = &((view_1.getData())[0]);
2525    //       double *ptr_2 = &((view_2.getData())[0]);
2526    
2527          // Get the pointers to the actual data
2528          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2529          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2530          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2531    
2532          // Compute a result for the default
2533          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2534          // Merge the tags
2535          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2536          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2537          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2538          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2539            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2540          }
2541          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2542            tmp_2->addTag(i->first);
2543          }
2544          // Compute a result for each tag
2545          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2546          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2547    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2548    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2549    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2550    //         double *ptr_0 = &view_0.getData(0);
2551    //         double *ptr_1 = &view_1.getData(0);
2552    //         double *ptr_2 = &view_2.getData(0);
2553    
2554            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2555            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2556            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2557            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2558          }
2559    
2560        }
2561        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2562    
2563          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2564          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2565          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2566          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2567          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2568    
2569          int sampleNo_0,dataPointNo_0;
2570          int numSamples_0 = arg_0_Z.getNumSamples();
2571          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2572          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2573          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2574            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2575            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2576            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2577              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2578              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2579              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2580              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2581              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2582            }
2583          }
2584    
2585        }
2586        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2587    
2588          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2589          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2590          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2591          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2592    
2593          int sampleNo_0,dataPointNo_0;
2594          int numSamples_0 = arg_0_Z.getNumSamples();
2595          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2596          int offset_1 = tmp_1->getPointOffset(0,0);
2597          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2598          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2599            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2600              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2601              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2602              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2603              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2604              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2605              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2606            }
2607          }
2608    
2609    
2610        }
2611        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2612    
2613          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2614          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2615          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2616          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2617          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2618    
2619          int sampleNo_0,dataPointNo_0;
2620          int numSamples_0 = arg_0_Z.getNumSamples();
2621          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2622          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2623          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2624            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2625            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2626            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2627              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2628              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2629              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2630              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2631              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2632            }
2633          }
2634    
2635        }
2636        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2637    
2638          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2639          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2640          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2641          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2642          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2643    
2644          int sampleNo_0,dataPointNo_0;
2645          int numSamples_0 = arg_0_Z.getNumSamples();
2646          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2647          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2648          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2649            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2650              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2651              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2652              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2653              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2654              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2655              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2656              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2657            }
2658          }
2659    
2660        }
2661        else {
2662          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2663        }
2664    
2665      } else {
2666        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2667      }
2668    
2669      return res;
2670    }
2671    
2672    template <typename UnaryFunction>
2673    Data
2674    C_TensorUnaryOperation(Data const &arg_0,
2675                           UnaryFunction operation)
2676    {
2677      if (arg_0.isEmpty())  // do this before we attempt to interpolate
2678      {
2679         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2680      }
2681    
2682      // Interpolate if necessary and find an appropriate function space
2683      Data arg_0_Z = Data(arg_0);
2684    
2685      // Get rank and shape of inputs
2686      int rank0 = arg_0_Z.getDataPointRank();
2687      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2688      int size0 = arg_0_Z.getDataPointSize();
2689    
2690      // Declare output Data object
2691      Data res;
2692    
2693      if (arg_0_Z.isConstant()) {
2694        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2695    //     double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2696    //     double *ptr_2 = &((res.getPointDataView().getData())[0]);
2697        double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2698        double *ptr_2 = &(res.getDataAtOffset(0));
2699        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2700      }
2701      else if (arg_0_Z.isTagged()) {
2702    
2703        // Borrow DataTagged input from Data object
2704        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2705    
2706        // Prepare a DataTagged output 2
2707        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2708        res.tag();
2709        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2710    
2711    //     // Get the views
2712    //     DataArrayView view_0 = tmp_0->getDefaultValue();
2713    //     DataArrayView view_2 = tmp_2->getDefaultValue();
2714    //     // Get the pointers to the actual data
2715    //     double *ptr_0 = &((view_0.getData())[0]);
2716    //     double *ptr_2 = &((view_2.getData())[0]);
2717        // Get the pointers to the actual data
2718        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2719        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2720        // Compute a result for the default
2721        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2722        // Compute a result for each tag
2723        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2724        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2725        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2726          tmp_2->addTag(i->first);
2727    //       DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2728    //       DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2729    //       double *ptr_0 = &view_0.getData(0);
2730    //       double *ptr_2 = &view_2.getData(0);
2731          double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2732          double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2733          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2734        }
2735    
2736      }
2737      else if (arg_0_Z.isExpanded()) {
2738    
2739        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2740        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2741        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2742    
2743        int sampleNo_0,dataPointNo_0;
2744        int numSamples_0 = arg_0_Z.getNumSamples();
2745        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2746        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2747        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2748          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2749    //         int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2750    //         int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2751    //         double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2752    //         double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2753            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2754            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2755            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2756            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2757            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2758          }
2759        }
2760      }
2761      else {
2762        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2763      }
2764    
2765      return res;
2766    }
2767    
2768  }  }
2769  #endif  #endif

Legend:
Removed from v.922  
changed lines
  Added in v.1811

  ViewVC Help
Powered by ViewVC 1.1.26