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

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

  ViewVC Help
Powered by ViewVC 1.1.26