/[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 1952 by jfenwick, Thu Oct 30 06:16:00 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);
269    
270    /**    /**
271       \brief       \brief
272       Return the values of a data point on this process       sets the values of a data-point from a numarray object on this process
   */  
   ESCRIPT_DLL_API  
   const boost::python::numeric::array  
   getValueOfDataPoint(int dataPointNo);  
   
   /**  
      \brief  
      sets the values of a data-point 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 432  class Data { Line 428  class Data {
428    */    */
429    ESCRIPT_DLL_API    ESCRIPT_DLL_API
430    inline    inline
431    const AbstractDomain&  //   const AbstractDomain&
432      const_Domain_ptr
433    getDomain() const    getDomain() const
434    {    {
435       return getFunctionSpace().getDomain();       return getFunctionSpace().getDomain();
436    }    }
437    
438    
439      /**
440         \brief
441         Return the domain.
442         TODO: For internal use only.   This should be removed.
443      */
444      ESCRIPT_DLL_API
445      inline
446    //   const AbstractDomain&
447      Domain_ptr
448      getDomainPython() const
449      {
450         return getFunctionSpace().getDomainPython();
451      }
452    
453    /**    /**
454       \brief       \brief
455       Return a copy of the domain.       Return a copy of the domain.
# Line 452  class Data { Line 464  class Data {
464    */    */
465    ESCRIPT_DLL_API    ESCRIPT_DLL_API
466    inline    inline
467    int    unsigned int
468    getDataPointRank() const    getDataPointRank() const
469    {    {
470      return m_data->getPointDataView().getRank();      return m_data->getRank();
471    }    }
472    
473    /**    /**
# Line 493  class Data { Line 505  class Data {
505      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
506    }    }
507    
508    
509      /**
510        \brief
511        Return the number of values in the shape for this object.
512      */
513      ESCRIPT_DLL_API
514      int
515      getNoValues() const
516      {
517        return m_data->getNoValues();
518      }
519    
520    
521      /**
522         \brief
523         dumps the object into a netCDF file
524      */
525      ESCRIPT_DLL_API
526      void
527      dump(const std::string fileName) const;
528    /**    /**
529       \brief       \brief
530       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 553  class Data {
553      return m_data->getSampleDataByTag(tag);      return m_data->getSampleDataByTag(tag);
554    }    }
555    
556    /**  //  /**
557       \brief  /*     \brief
558       Assign the given value to the data-points referenced by the given       Return a view into the data for the data point specified.
559       reference number.       NOTE: Construction of the DataArrayView is a relatively expensive
560         operation.
561       The value supplied is a python numarray object.  The data from this numarray       \param sampleNo - Input -
562       is unpacked into a DataArray, and this is used to set the corresponding       \param dataPointNo - Input -*/
563       data-points in the underlying Data object.  //  */
564    //   ESCRIPT_DLL_API
565    //   inline
566    //   DataArrayView
567    //   getDataPoint(int sampleNo,
568    //                int dataPointNo)
569    //   {
570    //                 return m_data->getDataPoint(sampleNo,dataPointNo);
571    //   }
572    
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
573    
574       \param ref - Input - reference number.    /**
575       \param value - Input - value to assign to data-points associated with       \brief
576                              the given reference number.       Return a view into the data for the data point specified.
577         NOTE: Construction of the DataArrayView is a relatively expensive
578         operation.
579         \param sampleNo - Input -
580         \param dataPointNo - Input -
581    */    */
582    ESCRIPT_DLL_API    ESCRIPT_DLL_API
583    void    DataTypes::ValueType::const_reference
584    setRefValue(int ref,    getDataPoint(int sampleNo, int dataPointNo) const;
               const boost::python::numeric::array& value);  
585    
   /**  
      \brief  
      Return the values associated with the data-points referenced by the given  
      reference number.  
586    
587       The value supplied is a python numarray object. The data from the corresponding    ESCRIPT_DLL_API
588       data-points in this Data object are packed into the given numarray object.    DataTypes::ValueType::reference
589      getDataPoint(int sampleNo, int dataPointNo);
590    
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
591    
      \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);  
592    
593    /**    /**
594       \brief       \brief
595       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 -  
596    */    */
597    ESCRIPT_DLL_API    ESCRIPT_DLL_API
598    inline    inline
599    DataArrayView    DataTypes::ValueType::size_type
600    getDataPoint(int sampleNo,    getDataOffset(int sampleNo,
601                 int dataPointNo)                 int dataPointNo)
602    {    {
603          return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getPointOffset(sampleNo,dataPointNo);
604    }    }
605    
606    /**    /**
# Line 584  class Data { Line 608  class Data {
608       Return a reference to the data point shape.       Return a reference to the data point shape.
609    */    */
610    ESCRIPT_DLL_API    ESCRIPT_DLL_API
611    const DataArrayView::ShapeType&    inline
612    getDataPointShape() const;    const DataTypes::ShapeType&
613      getDataPointShape() const
614      {
615        return m_data->getShape();
616      }
617    
618    /**    /**
619       \brief       \brief
# Line 609  class Data { Line 637  class Data {
637       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
638    */    */
639    ESCRIPT_DLL_API    ESCRIPT_DLL_API
640    DataArrayView::ValueType::size_type    DataTypes::ValueType::size_type
641    getLength() const;    getLength() const;
642    
643    
644    
645    /**    /**
646       \brief       \brief
647       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag assocciated with name. Implicitly converts this
648       object to type DataTagged. Throws an exception if this object       object to type DataTagged. Throws an exception if this object
649       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
650         \param tagKey - Input - Integer key.
651         \param value - Input - Value to associate with given key.
652        ==>*
653      */
654      ESCRIPT_DLL_API
655      void
656      setTaggedValueByName(std::string name,
657                           const boost::python::object& value);
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.       \param tagKey - Input - Integer key.
665       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
666      ==>*      ==>*
# Line 626  class Data { Line 670  class Data {
670    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
671                   const boost::python::object& value);                   const boost::python::object& value);
672    
673    
674    //  /**
675    //     \brief
676    //     Assign the given value to the tag. Implicitly converts this
677    //     object to type DataTagged if it is constant.
678    //
679    //     \param tagKey - Input - Integer key.
680    //     \param value - Input - Value to associate with given key.
681    //    ==>*
682    //  */
683    //   ESCRIPT_DLL_API
684    //   void
685    //   setTaggedValueFromCPP(int tagKey,
686    //                         const DataArrayView& value);
687    
688    /**    /**
689       \brief       \brief
690       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
691       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
692       cannot be converted to a DataTagged object.  
693       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
694         \param pointshape - Input - The shape of the value parameter
695       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
696      ==>*       \param dataOffset - Input - Offset of the begining of the point within the value parameter
697    */    */
698    ESCRIPT_DLL_API    ESCRIPT_DLL_API
699    void    void
700    setTaggedValueFromCPP(int tagKey,    setTaggedValueFromCPP(int tagKey,
701                          const DataArrayView& value);              const DataTypes::ShapeType& pointshape,
702                            const DataTypes::ValueType& value,
703                int dataOffset=0);
704    
705    
706    
707    /**    /**
708      \brief      \brief
# Line 655  class Data { Line 719  class Data {
719    
720    /**    /**
721       \brief       \brief
722         set all values to zero
723         *
724      */
725      ESCRIPT_DLL_API
726      void
727      setToZero();
728    
729      /**
730         \brief
731       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
732       the result as a Data object.       the result as a Data object.
733       *       *
# Line 662  class Data { Line 735  class Data {
735    ESCRIPT_DLL_API    ESCRIPT_DLL_API
736    Data    Data
737    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
738    /**    /**
739       \brief       \brief
740       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 751  class Data { Line 823  class Data {
823    /**    /**
824       \brief       \brief
825       Return the maximum absolute value of this Data object.       Return the maximum absolute value of this Data object.
826         For Data which contain no samples (or tagged Data for which no tags in use have a value)
827         zero is returned.
828       *       *
829    */    */
830    ESCRIPT_DLL_API    ESCRIPT_DLL_API
# Line 759  class Data { Line 833  class Data {
833    
834    /**    /**
835       \brief       \brief
      Return the minimum absolute value of this Data object.  
      *  
   */  
   ESCRIPT_DLL_API  
   double  
   Linf() const;  
   
   /**  
      \brief  
836       Return the maximum value of this Data object.       Return the maximum value of this Data object.
837       *       For Data which contain no samples (or tagged Data for which no tags in use have a value)
838         a large negative value is returned.
839    */    */
840    ESCRIPT_DLL_API    ESCRIPT_DLL_API
841    double    double
# Line 778  class Data { Line 844  class Data {
844    /**    /**
845       \brief       \brief
846       Return the minimum value of this Data object.       Return the minimum value of this Data object.
847         For Data which contain no samples (or tagged Data for which no tags in use have a value)
848         a large positive value is returned.
849       *       *
850    */    */
851    ESCRIPT_DLL_API    ESCRIPT_DLL_API
# Line 882  class Data { Line 950  class Data {
950    /**    /**
951       \brief       \brief
952       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.
953       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
954       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
955       first non-zero entry is positive.       first non-zero entry is positive.
956       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
957       *       *
# Line 1087  class Data { Line 1155  class Data {
1155    /**    /**
1156       \brief       \brief
1157       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.
1158        
1159       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1160       *       *
1161     */     */
# Line 1098  class Data { Line 1166  class Data {
1166    /**    /**
1167       \brief       \brief
1168       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.
1169        
1170       \param left Input - the bases       \param left Input - the bases
1171       *       *
1172     */     */
# Line 1134  class Data { Line 1202  class Data {
1202    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1203    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1204    
1205      ESCRIPT_DLL_API
1206      Data& operator=(const Data& other);
1207    
1208    /**    /**
1209       \brief       \brief
1210       Overloaded operator -=       Overloaded operator -=
# Line 1226  class Data { Line 1297  class Data {
1297    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1298    inline    inline
1299    void    void
1300    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1301    
1302    /**    /**
1303       \brief       \brief
# Line 1237  class Data { Line 1308  class Data {
1308    */    */
1309    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1310    Data    Data
1311    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataTypes::RegionType& region) const;
1312    
1313    /**    /**
1314       \brief       \brief
# Line 1250  class Data { Line 1321  class Data {
1321    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1322    void    void
1323    setSlice(const Data& value,    setSlice(const Data& value,
1324             const DataArrayView::RegionType& region);             const DataTypes::RegionType& region);
1325    
1326    /**    /**
1327       \brief       \brief
1328       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.  
1329    */    */
1330    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1331    void    void
1332    archiveData(const std::string fileName);          print(void);
1333    
1334    /**    /**
1335       \brief       \brief
1336       Extract the Data object archived in the given file, overwriting       return the MPI rank number of the local data
1337       the current Data object.                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1338       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.  
1339    */    */
1340    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1341    void          int
1342    extractData(const std::string fileName,          get_MPIRank(void) const;
               const FunctionSpace& fspace);  
   
1343    
1344    /**    /**
1345       \brief       \brief
1346       print the data values to stdout. Used for debugging       return the MPI rank number of the local data
1347                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1348                     is returned
1349    */    */
1350    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1351    void          int
1352      print(void);          get_MPISize(void) const;
1353    
1354    /**    /**
1355       \brief       \brief
1356       return the MPI rank number of the local data       return the MPI rank number of the local data
1357           MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()                   MPI_COMM_WORLD is assumed and returned.
          is returned  
1358    */    */
1359    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1360      int          MPI_Comm
1361      get_MPIRank(void) const;          get_MPIComm(void) const;
1362    
1363    /**    /**
1364       \brief       \brief
1365       return the MPI rank number of the local data       return the object produced by the factory, which is a DataConstant or DataExpanded
1366           MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()      TODO Ownership of this object should be explained in doco.
          is returned  
1367    */    */
1368    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1369      int          DataAbstract*
1370      get_MPISize(void) const;          borrowData(void) const;
1371    
1372    
1373    /**    /**
1374       \brief       \brief
1375       return the MPI rank number of the local data       Return a pointer to the beginning of the datapoint at the specified offset.
1376           MPI_COMM_WORLD is assumed and returned.       TODO Eventually these should be inlined.
1377         \param i - position(offset) in the underlying datastructure
1378    */    */
1379    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1380      MPI_Comm          DataTypes::ValueType::const_reference
1381      get_MPIComm(void) const;          getDataAtOffset(DataTypes::ValueType::size_type i) const;
1382    
1383    
   /**  
      \brief  
      return the object produced by the factory, which is a DataConstant or DataExpanded  
   */  
1384    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1385      DataAbstract*          DataTypes::ValueType::reference
1386      borrowData(void) const;          getDataAtOffset(DataTypes::ValueType::size_type i);
1387    
1388   protected:   protected:
1389    
# Line 1395  class Data { Line 1460  class Data {
1460       \brief       \brief
1461       Construct a Data object of the appropriate type.       Construct a Data object of the appropriate type.
1462    */    */
1463    template <class IValueType>  
1464    void    void
1465    initialise(const IValueType& value,    initialise(const DataTypes::ValueType& value,
1466             const DataTypes::ShapeType& shape,
1467               const FunctionSpace& what,               const FunctionSpace& what,
1468               bool expanded);               bool expanded);
1469    
1470      void
1471      initialise(const boost::python::numeric::array& value,
1472                     const FunctionSpace& what,
1473                     bool expanded);
1474    
1475    //    //
1476    // flag to protect the data object against any update    // flag to protect the data object against any update
1477    bool m_protected;    bool m_protected;
1478    
1479    //    //
1480    // pointer to the actual data object    // pointer to the actual data object
1481    boost::shared_ptr<DataAbstract> m_data;  //   boost::shared_ptr<DataAbstract> m_data;
1482      DataAbstract_ptr m_data;
   //  
   // pointer to the internal profiling data  
   struct profDataEntry *profData;  
1483    
1484  };  };
1485    
1486  template <class IValueType>  
1487  void  
1488  Data::initialise(const IValueType& value,  /**
1489                   const FunctionSpace& what,     Modify a filename for MPI parallel output to multiple files
1490                   bool expanded)  */
1491  {  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;  
   }  
 }  
1492    
1493  /**  /**
1494     Binary Data object operators.     Binary Data object operators.
1495  */  */
1496  inline double rpow(double x,double y)  inline double rpow(double x,double y)
1497  {  {
1498      return pow(y,x);      return pow(y,x);
1499  };  }
1500    
1501  /**  /**
1502    \brief    \brief
# Line 1537  ESCRIPT_DLL_API Data operator*(const boo Line 1590  ESCRIPT_DLL_API Data operator*(const boo
1590  */  */
1591  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);
1592    
1593    
1594    
1595  /**  /**
1596    \brief    \brief
1597    Output operator    Output operator
# Line 1558  C_GeneralTensorProduct(Data& arg0, Line 1613  C_GeneralTensorProduct(Data& arg0,
1613                       int axis_offset=0,                       int axis_offset=0,
1614                       int transpose=0);                       int transpose=0);
1615    
1616  /**  
1617    \brief  
1618    // /**
1619    /*  \brief
1620    Return true if operands are equivalent, else return false.    Return true if operands are equivalent, else return false.
1621    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
1622    be relied on. Requires further implementation.    be relied on. Requires further implementation.*/
1623  */  //*/
1624  //ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);  // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1625    
1626  /**  /**
1627    \brief    \brief
# Line 1579  Data::binaryOp(const Data& right, Line 1636  Data::binaryOp(const Data& right,
1636  {  {
1637     //     //
1638     // 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
1639     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1640       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.");
1641     }     }
1642     //     //
# Line 1588  Data::binaryOp(const Data& right, Line 1645  Data::binaryOp(const Data& right,
1645     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1646       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1647         //         //
1648         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1649         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1650       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1651         //         //
# Line 1632  Data::binaryOp(const Data& right, Line 1689  Data::binaryOp(const Data& right,
1689       EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");       EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1690       escript::binaryOp(*leftC,*rightC,operation);       escript::binaryOp(*leftC,*rightC,operation);
1691     }     }
    #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);  
   }  
1692  }  }
1693    
1694  /**  /**
# Line 1707  Data::algorithm(BinaryFunction operation Line 1715  Data::algorithm(BinaryFunction operation
1715      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1716      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1717      return escript::algorithm(*leftC,operation,initial_value);      return escript::algorithm(*leftC,operation,initial_value);
1718      } else if (isEmpty()) {
1719        throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1720    }    }
1721    return 0;    return 0;
1722  }  }
# Line 1715  Data::algorithm(BinaryFunction operation Line 1725  Data::algorithm(BinaryFunction operation
1725    \brief    \brief
1726    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.
1727    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1728    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
1729    rank 0 Data object.    rank 0 Data object.
1730    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1731  */  */
# Line 1724  inline Line 1734  inline
1734  Data  Data
1735  Data::dp_algorithm(BinaryFunction operation, double initial_value) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1736  {  {
1737    if (isExpanded()) {    if (isEmpty()) {
1738      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1739      }
1740      else if (isExpanded()) {
1741        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1742      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1743      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1744      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1745      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1746      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1747      return result;      return result;
1748    } else if (isTagged()) {    }
1749      else if (isTagged()) {
1750      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());  
1751      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1752      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      DataTypes::ValueType defval(1);
1753        defval[0]=0;
1754        DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1755      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1756      return result;      return Data(resultT);   // note: the Data object now owns the resultT pointer
1757    } else if (isConstant()) {    }
1758      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());    else if (isConstant()) {
1759        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1760      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1761      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1762      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 1768  Data::dp_algorithm(BinaryFunction operat
1768    return falseRetVal;    return falseRetVal;
1769  }  }
1770    
1771    /**
1772      \brief
1773      Compute a tensor operation with two Data objects
1774      \param arg0 - Input - Data object
1775      \param arg1 - Input - Data object
1776      \param operation - Input - Binary op functor
1777    */
1778    template <typename BinaryFunction>
1779    inline
1780    Data
1781    C_TensorBinaryOperation(Data const &arg_0,
1782                            Data const &arg_1,
1783                            BinaryFunction operation)
1784    {
1785      if (arg_0.isEmpty() || arg_1.isEmpty())
1786      {
1787         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1788      }
1789      // Interpolate if necessary and find an appropriate function space
1790      Data arg_0_Z, arg_1_Z;
1791      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1792        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1793          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1794          arg_1_Z = Data(arg_1);
1795        }
1796        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1797          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1798          arg_0_Z =Data(arg_0);
1799        }
1800        else {
1801          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1802        }
1803      } else {
1804          arg_0_Z = Data(arg_0);
1805          arg_1_Z = Data(arg_1);
1806      }
1807      // Get rank and shape of inputs
1808      int rank0 = arg_0_Z.getDataPointRank();
1809      int rank1 = arg_1_Z.getDataPointRank();
1810      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1811      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1812      int size0 = arg_0_Z.getDataPointSize();
1813      int size1 = arg_1_Z.getDataPointSize();
1814    
1815      // Declare output Data object
1816      Data res;
1817    
1818      if (shape0 == shape1) {
1819    
1820        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1821          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1822    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1823          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1824          double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1825          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1826          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1827          double *ptr_2 = &(res.getDataAtOffset(0));
1828    
1829          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1830        }
1831        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1832    
1833          // Prepare the DataConstant input
1834          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1835    
1836          // Borrow DataTagged input from Data object
1837          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1838    
1839          // Prepare a DataTagged output 2
1840          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1841          res.tag();
1842          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1843    
1844          // Prepare offset into DataConstant
1845          int offset_0 = tmp_0->getPointOffset(0,0);
1846          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1847          // Get the views
1848    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1849    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1850    //       // Get the pointers to the actual data
1851    //       double *ptr_1 = &((view_1.getData())[0]);
1852    //       double *ptr_2 = &((view_2.getData())[0]);
1853    
1854          // Get the pointers to the actual data
1855          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1856          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1857    
1858          // Compute a result for the default
1859          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1860          // Compute a result for each tag
1861          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1862          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1863          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1864            tmp_2->addTag(i->first);
1865    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1866            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1867            double *ptr_1 = &view_1.getData(0);
1868            double *ptr_2 = &view_2.getData(0);*/
1869            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1870            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1871    
1872            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1873          }
1874    
1875        }
1876        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1877    
1878          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1879          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1880          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1881          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1882    
1883          int sampleNo_1,dataPointNo_1;
1884          int numSamples_1 = arg_1_Z.getNumSamples();
1885          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1886          int offset_0 = tmp_0->getPointOffset(0,0);
1887          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1888          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1889            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1890              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1891              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1892    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1893    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1894    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1895    
1896              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1897              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1898              double *ptr_2 = &(res.getDataAtOffset(offset_2));
1899              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1900            }
1901          }
1902    
1903        }
1904        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1905    
1906          // Borrow DataTagged input from Data object
1907          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1908    
1909          // Prepare the DataConstant input
1910          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1911    
1912          // Prepare a DataTagged output 2
1913          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1914          res.tag();
1915          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1916    
1917          // Prepare offset into DataConstant
1918          int offset_1 = tmp_1->getPointOffset(0,0);
1919    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1920          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1921          // Get the views
1922    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1923    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1924    //       // Get the pointers to the actual data
1925    //       double *ptr_0 = &((view_0.getData())[0]);
1926    //       double *ptr_2 = &((view_2.getData())[0]);
1927          // Get the pointers to the actual data
1928          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1929          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1930          // Compute a result for the default
1931          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1932          // Compute a result for each tag
1933          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1934          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1935          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1936            tmp_2->addTag(i->first);
1937    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1938    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1939    //         double *ptr_0 = &view_0.getData(0);
1940    //         double *ptr_2 = &view_2.getData(0);
1941            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1942            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1943            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1944          }
1945    
1946        }
1947        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1948    
1949          // Borrow DataTagged input from Data object
1950          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1951    
1952          // Borrow DataTagged input from Data object
1953          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1954    
1955          // Prepare a DataTagged output 2
1956          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1957          res.tag();        // DataTagged output
1958          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1959    
1960    //       // Get the views
1961    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1962    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1963    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1964    //       // Get the pointers to the actual data
1965    //       double *ptr_0 = &((view_0.getData())[0]);
1966    //       double *ptr_1 = &((view_1.getData())[0]);
1967    //       double *ptr_2 = &((view_2.getData())[0]);
1968    
1969          // Get the pointers to the actual data
1970          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1971          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1972          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1973    
1974          // Compute a result for the default
1975          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1976          // Merge the tags
1977          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1978          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1979          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1980          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1981            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
1982          }
1983          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1984            tmp_2->addTag(i->first);
1985          }
1986          // Compute a result for each tag
1987          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1988          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1989    
1990    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1991    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1992    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1993    //         double *ptr_0 = &view_0.getData(0);
1994    //         double *ptr_1 = &view_1.getData(0);
1995    //         double *ptr_2 = &view_2.getData(0);
1996    
1997            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1998            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1999            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2000    
2001            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2002          }
2003    
2004        }
2005        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2006    
2007          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2008          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2009          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2010          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2011          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2012    
2013          int sampleNo_0,dataPointNo_0;
2014          int numSamples_0 = arg_0_Z.getNumSamples();
2015          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2016          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2017          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2018            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2019            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2020            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2021              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2022              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2023    
2024    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2025    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2026              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2027              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2028    
2029    
2030              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2031            }
2032          }
2033    
2034        }
2035        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2036    
2037          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2038          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2039          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2040          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2041    
2042          int sampleNo_0,dataPointNo_0;
2043          int numSamples_0 = arg_0_Z.getNumSamples();
2044          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2045          int offset_1 = tmp_1->getPointOffset(0,0);
2046          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2047          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2048            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2049              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2050              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2051    
2052    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2053    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2054    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2055    
2056              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2057              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2058              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2059    
2060    
2061              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2062            }
2063          }
2064    
2065        }
2066        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2067    
2068          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2069          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2070          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2071          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2072          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2073    
2074          int sampleNo_0,dataPointNo_0;
2075          int numSamples_0 = arg_0_Z.getNumSamples();
2076          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2077          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2078          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2079            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2080            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2081            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2082              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2083              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2084              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2085              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2086              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2087            }
2088          }
2089    
2090        }
2091        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2092    
2093          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2094          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2095          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2096          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2097          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2098    
2099          int sampleNo_0,dataPointNo_0;
2100          int numSamples_0 = arg_0_Z.getNumSamples();
2101          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2102          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2103          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2104            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2105              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2106              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2107              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2108              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2109              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2110              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2111              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2112            }
2113          }
2114    
2115        }
2116        else {
2117          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2118        }
2119    
2120      } else if (0 == rank0) {
2121    
2122        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2123          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2124          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2125          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2126          double *ptr_2 = &(res.getDataAtOffset(0));
2127          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2128        }
2129        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2130    
2131          // Prepare the DataConstant input
2132          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2133    
2134          // Borrow DataTagged input from Data object
2135          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2136    
2137          // Prepare a DataTagged output 2
2138          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2139          res.tag();
2140          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2141    
2142          // Prepare offset into DataConstant
2143          int offset_0 = tmp_0->getPointOffset(0,0);
2144          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2145          // Get the views
2146    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2147    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2148    //       // Get the pointers to the actual data
2149    //       double *ptr_1 = &((view_1.getData())[0]);
2150    //       double *ptr_2 = &((view_2.getData())[0]);
2151           double *ptr_1 = &(tmp_1->getDefaultValue(0));
2152           double *ptr_2 = &(tmp_2->getDefaultValue(0));
2153    
2154          // Compute a result for the default
2155          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2156          // Compute a result for each tag
2157          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2158          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2159          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2160            tmp_2->addTag(i->first);
2161    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2162    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2163    //         double *ptr_1 = &view_1.getData(0);
2164    //         double *ptr_2 = &view_2.getData(0);
2165            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2166            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2167            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2168          }
2169    
2170        }
2171        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2172    
2173          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2174          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2175          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2176          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2177    
2178          int sampleNo_1,dataPointNo_1;
2179          int numSamples_1 = arg_1_Z.getNumSamples();
2180          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2181          int offset_0 = tmp_0->getPointOffset(0,0);
2182          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2183          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2184            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2185              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2186              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2187              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2188              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2189              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2190              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2191    
2192            }
2193          }
2194    
2195        }
2196        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2197    
2198          // Borrow DataTagged input from Data object
2199          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2200    
2201          // Prepare the DataConstant input
2202          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2203    
2204          // Prepare a DataTagged output 2
2205          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2206          res.tag();
2207          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2208    
2209          // Prepare offset into DataConstant
2210          int offset_1 = tmp_1->getPointOffset(0,0);
2211    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2212          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2213          // Get the views
2214    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2215          DataArrayView view_2 = tmp_2->getDefaultValue();
2216          // Get the pointers to the actual data
2217          double *ptr_0 = &((view_0.getData())[0]);
2218          double *ptr_2 = &((view_2.getData())[0]);*/
2219    
2220          // Get the pointers to the actual data
2221          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2222          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2223    
2224    
2225          // Compute a result for the default
2226          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2227          // Compute a result for each tag
2228          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2229          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2230          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2231            tmp_2->addTag(i->first);
2232    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2233            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2234            double *ptr_0 = &view_0.getData(0);
2235            double *ptr_2 = &view_2.getData(0);*/
2236            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2237            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2238    
2239            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2240          }
2241    
2242        }
2243        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2244    
2245          // Borrow DataTagged input from Data object
2246          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2247    
2248          // Borrow DataTagged input from Data object
2249          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2250    
2251          // Prepare a DataTagged output 2
2252          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2253          res.tag();        // DataTagged output
2254          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2255    
2256          // Get the views
2257    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2258          DataArrayView view_1 = tmp_1->getDefaultValue();
2259          DataArrayView view_2 = tmp_2->getDefaultValue();
2260          // Get the pointers to the actual data
2261          double *ptr_0 = &((view_0.getData())[0]);
2262          double *ptr_1 = &((view_1.getData())[0]);
2263          double *ptr_2 = &((view_2.getData())[0]);*/
2264    
2265          // Get the pointers to the actual data
2266          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2267          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2268          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2269    
2270    
2271          // Compute a result for the default
2272          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2273          // Merge the tags
2274          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2275          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2276          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2277          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2278            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2279          }
2280          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2281            tmp_2->addTag(i->first);
2282          }
2283          // Compute a result for each tag
2284          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2285          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2286    
2287    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2288            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2289            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2290            double *ptr_0 = &view_0.getData(0);
2291            double *ptr_1 = &view_1.getData(0);
2292            double *ptr_2 = &view_2.getData(0);*/
2293    
2294            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2295            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2296            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2297    
2298            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2299          }
2300    
2301        }
2302        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2303    
2304          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2305          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2306          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2307          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2308          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2309    
2310          int sampleNo_0,dataPointNo_0;
2311          int numSamples_0 = arg_0_Z.getNumSamples();
2312          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2313          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2314          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2315            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2316            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2317            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2318              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2319              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2320              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2321              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2322              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2323            }
2324          }
2325    
2326        }
2327        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2328    
2329          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2330          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2331          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2332          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2333    
2334          int sampleNo_0,dataPointNo_0;
2335          int numSamples_0 = arg_0_Z.getNumSamples();
2336          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2337          int offset_1 = tmp_1->getPointOffset(0,0);
2338          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2339          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2340            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2341              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2342              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2343              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2344              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2345              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2346              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2347            }
2348          }
2349    
2350    
2351        }
2352        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2353    
2354          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2355          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2356          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2357          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2358          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2359    
2360          int sampleNo_0,dataPointNo_0;
2361          int numSamples_0 = arg_0_Z.getNumSamples();
2362          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2363          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2364          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2365            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2366            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2367            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2368              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2369              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2370              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2371              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2372              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2373            }
2374          }
2375    
2376        }
2377        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2378    
2379          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2380          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2381          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2382          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2383          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2384    
2385          int sampleNo_0,dataPointNo_0;
2386          int numSamples_0 = arg_0_Z.getNumSamples();
2387          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2388          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2389          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2390            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2391              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2392              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2393              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2394              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2395              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2396              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2397              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2398            }
2399          }
2400    
2401        }
2402        else {
2403          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2404        }
2405    
2406      } else if (0 == rank1) {
2407    
2408        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2409          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2410          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2411          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2412          double *ptr_2 = &(res.getDataAtOffset(0));
2413          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2414        }
2415        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2416    
2417          // Prepare the DataConstant input
2418          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2419    
2420          // Borrow DataTagged input from Data object
2421          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2422    
2423          // Prepare a DataTagged output 2
2424          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2425          res.tag();
2426          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2427    
2428          // Prepare offset into DataConstant
2429          int offset_0 = tmp_0->getPointOffset(0,0);
2430          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2431          // Get the views
2432    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2433          DataArrayView view_2 = tmp_2->getDefaultValue();
2434          // Get the pointers to the actual data
2435          double *ptr_1 = &((view_1.getData())[0]);
2436          double *ptr_2 = &((view_2.getData())[0]);*/
2437          //Get the pointers to the actual data
2438          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2439          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2440    
2441          // Compute a result for the default
2442          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2443          // Compute a result for each tag
2444          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2445          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2446          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2447            tmp_2->addTag(i->first);
2448    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2449    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2450    //         double *ptr_1 = &view_1.getData(0);
2451    //         double *ptr_2 = &view_2.getData(0);
2452            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2453            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2454    
2455    
2456            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2457          }
2458    
2459        }
2460        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2461    
2462          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2463          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2464          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2465          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2466    
2467          int sampleNo_1,dataPointNo_1;
2468          int numSamples_1 = arg_1_Z.getNumSamples();
2469          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2470          int offset_0 = tmp_0->getPointOffset(0,0);
2471          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2472          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2473            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2474              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2475              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2476              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2477              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2478              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2479              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2480            }
2481          }
2482    
2483        }
2484        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2485    
2486          // Borrow DataTagged input from Data object
2487          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2488    
2489          // Prepare the DataConstant input
2490          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2491    
2492          // Prepare a DataTagged output 2
2493          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2494          res.tag();
2495          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2496    
2497          // Prepare offset into DataConstant
2498          int offset_1 = tmp_1->getPointOffset(0,0);
2499          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2500          // Get the views
2501    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2502    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2503    //       // Get the pointers to the actual data
2504    //       double *ptr_0 = &((view_0.getData())[0]);
2505    //       double *ptr_2 = &((view_2.getData())[0]);
2506          // Get the pointers to the actual data
2507          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2508          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2509          // Compute a result for the default
2510          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2511          // Compute a result for each tag
2512          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2513          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2514          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2515            tmp_2->addTag(i->first);
2516    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2517            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2518            double *ptr_0 = &view_0.getData(0);
2519            double *ptr_2 = &view_2.getData(0);*/
2520            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2521            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2522            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2523          }
2524    
2525        }
2526        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2527    
2528          // Borrow DataTagged input from Data object
2529          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2530    
2531          // Borrow DataTagged input from Data object
2532          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2533    
2534          // Prepare a DataTagged output 2
2535          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2536          res.tag();        // DataTagged output
2537          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2538    
2539          // Get the views
2540    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2541    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2542    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2543    //       // Get the pointers to the actual data
2544    //       double *ptr_0 = &((view_0.getData())[0]);
2545    //       double *ptr_1 = &((view_1.getData())[0]);
2546    //       double *ptr_2 = &((view_2.getData())[0]);
2547    
2548          // Get the pointers to the actual data
2549          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2550          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2551          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2552    
2553          // Compute a result for the default
2554          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2555          // Merge the tags
2556          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2557          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2558          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2559          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2560            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2561          }
2562          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2563            tmp_2->addTag(i->first);
2564          }
2565          // Compute a result for each tag
2566          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2567          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2568    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2569    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2570    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2571    //         double *ptr_0 = &view_0.getData(0);
2572    //         double *ptr_1 = &view_1.getData(0);
2573    //         double *ptr_2 = &view_2.getData(0);
2574    
2575            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2576            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2577            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2578            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2579          }
2580    
2581        }
2582        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2583    
2584          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2585          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2586          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2587          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2588          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2589    
2590          int sampleNo_0,dataPointNo_0;
2591          int numSamples_0 = arg_0_Z.getNumSamples();
2592          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2593          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2594          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2595            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2596            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2597            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2598              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2599              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2600              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2601              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2602              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2603            }
2604          }
2605    
2606        }
2607        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2608    
2609          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2610          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2611          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2612          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2613    
2614          int sampleNo_0,dataPointNo_0;
2615          int numSamples_0 = arg_0_Z.getNumSamples();
2616          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2617          int offset_1 = tmp_1->getPointOffset(0,0);
2618          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2619          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2620            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2621              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2622              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2623              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2624              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2625              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2626              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2627            }
2628          }
2629    
2630    
2631        }
2632        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2633    
2634          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2635          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2636          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2637          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2638          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2639    
2640          int sampleNo_0,dataPointNo_0;
2641          int numSamples_0 = arg_0_Z.getNumSamples();
2642          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2643          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2644          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2645            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2646            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2647            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2648              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2649              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2650              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2651              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2652              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2653            }
2654          }
2655    
2656        }
2657        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2658    
2659          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2660          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2661          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2662          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2663          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2664    
2665          int sampleNo_0,dataPointNo_0;
2666          int numSamples_0 = arg_0_Z.getNumSamples();
2667          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2668          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2669          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2670            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2671              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2672              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2673              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2674              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2675              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2676              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2677              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2678            }
2679          }
2680    
2681        }
2682        else {
2683          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2684        }
2685    
2686      } else {
2687        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2688      }
2689    
2690      return res;
2691    }
2692    
2693    template <typename UnaryFunction>
2694    Data
2695    C_TensorUnaryOperation(Data const &arg_0,
2696                           UnaryFunction operation)
2697    {
2698      if (arg_0.isEmpty())  // do this before we attempt to interpolate
2699      {
2700         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2701      }
2702    
2703      // Interpolate if necessary and find an appropriate function space
2704      Data arg_0_Z = Data(arg_0);
2705    
2706      // Get rank and shape of inputs
2707    //  int rank0 = arg_0_Z.getDataPointRank();
2708      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2709      int size0 = arg_0_Z.getDataPointSize();
2710    
2711      // Declare output Data object
2712      Data res;
2713    
2714      if (arg_0_Z.isConstant()) {
2715        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2716    //     double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2717    //     double *ptr_2 = &((res.getPointDataView().getData())[0]);
2718        double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2719        double *ptr_2 = &(res.getDataAtOffset(0));
2720        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2721      }
2722      else if (arg_0_Z.isTagged()) {
2723    
2724        // Borrow DataTagged input from Data object
2725        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2726    
2727        // Prepare a DataTagged output 2
2728        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2729        res.tag();
2730        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2731    
2732    //     // Get the views
2733    //     DataArrayView view_0 = tmp_0->getDefaultValue();
2734    //     DataArrayView view_2 = tmp_2->getDefaultValue();
2735    //     // Get the pointers to the actual data
2736    //     double *ptr_0 = &((view_0.getData())[0]);
2737    //     double *ptr_2 = &((view_2.getData())[0]);
2738        // Get the pointers to the actual data
2739        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2740        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2741        // Compute a result for the default
2742        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2743        // Compute a result for each tag
2744        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2745        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2746        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2747          tmp_2->addTag(i->first);
2748    //       DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2749    //       DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2750    //       double *ptr_0 = &view_0.getData(0);
2751    //       double *ptr_2 = &view_2.getData(0);
2752          double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2753          double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2754          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2755        }
2756    
2757      }
2758      else if (arg_0_Z.isExpanded()) {
2759    
2760        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2761        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2762        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2763    
2764        int sampleNo_0,dataPointNo_0;
2765        int numSamples_0 = arg_0_Z.getNumSamples();
2766        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2767        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2768        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2769          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2770    //         int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2771    //         int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2772    //         double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2773    //         double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2774            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2775            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2776            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2777            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2778            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2779          }
2780        }
2781      }
2782      else {
2783        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2784      }
2785    
2786      return res;
2787    }
2788    
2789  }  }
2790  #endif  #endif

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

  ViewVC Help
Powered by ViewVC 1.1.26