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

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

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

trunk/escript/src/Data.h revision 698 by gross, Fri Mar 31 04:52:55 2006 UTC branches/schroedinger/escript/src/Data.h revision 1864 by jfenwick, Thu Oct 9 03:09:30 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    
17  #ifndef DATA_H  #ifndef DATA_H
18  #define DATA_H  #define DATA_H
19    #include "system_dep.h"
20    
21  #include "DataAbstract.h"  #include "DataAbstract.h"
22  #include "DataAlgorithm.h"  #include "DataAlgorithm.h"
# Line 22  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" doesn't belong in this file...causes trouble for BruceFactory.cpp */
32  }  }
33    
34    #include "esysmpi.h"
35  #include <string>  #include <string>
36  #include <algorithm>  #include <algorithm>
37    #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 45  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 64  class Data { Line 72  class Data {
72    typedef double (*UnaryDFunPtr)(double);    typedef double (*UnaryDFunPtr)(double);
73    typedef double (*BinaryDFunPtr)(double,double);    typedef double (*BinaryDFunPtr)(double,double);
74    
75    
76    /**    /**
77       Constructors.       Constructors.
78    */    */
# Line 73  class Data { Line 82  class Data {
82       Default constructor.       Default constructor.
83       Creates a DataEmpty object.       Creates a DataEmpty object.
84    */    */
85      ESCRIPT_DLL_API
86    Data();    Data();
87    
88    /**    /**
# Line 80  class Data { Line 90  class Data {
90       Copy constructor.       Copy constructor.
91       WARNING: Only performs a shallow copy.       WARNING: Only performs a shallow copy.
92    */    */
93      ESCRIPT_DLL_API
94    Data(const Data& inData);    Data(const Data& inData);
95    
96    /**    /**
# Line 88  class Data { Line 99  class Data {
99       function space of inData the inData are tried to be interpolated to what,       function space of inData the inData are tried to be interpolated to what,
100       otherwise a shallow copy of inData is returned.       otherwise a shallow copy of inData is returned.
101    */    */
102      ESCRIPT_DLL_API
103    Data(const Data& inData,    Data(const Data& inData,
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    
110       \param value - Input - Data value for a single point.    ESCRIPT_DLL_API
111       \param what - Input - A description of what this data represents.    Data(const DataTypes::ValueType& value,
112       \param expanded - Input - Flag, if true fill the entire container with           const DataTypes::ShapeType& shape,
113                         the value. Otherwise a more efficient storage                   const FunctionSpace& what=FunctionSpace(),
114                         mechanism will be used.                   bool expanded=false);
   */  
   Data(const DataArrayView& value,  
        const FunctionSpace& what=FunctionSpace(),  
        bool expanded=false);  
115    
116    /**    /**
117       \brief       \brief
# Line 116  class Data { Line 124  class Data {
124                         the given value. Otherwise a more efficient storage                         the given value. Otherwise a more efficient storage
125                         mechanism will be used.                         mechanism will be used.
126    */    */
127      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 128  class Data { Line 137  class Data {
137       \param inData - Input - Input Data object.       \param inData - Input - Input Data object.
138       \param region - Input - Region to copy.       \param region - Input - Region to copy.
139    */    */
140      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.  
     ==>*  
   */  
   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 161  class Data { Line 151  class Data {
151                         the value. Otherwise a more efficient storage                         the value. Otherwise a more efficient storage
152                         mechanism will be used.                         mechanism will be used.
153    */    */
154      ESCRIPT_DLL_API
155    Data(const boost::python::numeric::array& value,    Data(const boost::python::numeric::array& value,
156         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
157         bool expanded=false);         bool expanded=false);
# Line 176  class Data { Line 167  class Data {
167                         the value. Otherwise a more efficient storage                         the value. Otherwise a more efficient storage
168                         mechanism will be used.                         mechanism will be used.
169    */    */
170      ESCRIPT_DLL_API
171    Data(const boost::python::object& value,    Data(const boost::python::object& value,
172         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
173         bool expanded=false);         bool expanded=false);
# Line 189  class Data { Line 181  class Data {
181       \param value - Input - Input data.       \param value - Input - Input data.
182       \param other - Input - contains all other parameters.       \param other - Input - contains all other parameters.
183    */    */
184      ESCRIPT_DLL_API
185    Data(const boost::python::object& value,    Data(const boost::python::object& value,
186         const Data& other);         const Data& other);
187    
# Line 196  class Data { Line 189  class Data {
189       \brief       \brief
190       Constructor which creates a DataConstant of "shape" with constant value.       Constructor which creates a DataConstant of "shape" with constant value.
191    */    */
192    Data(double value,    ESCRIPT_DLL_API
193         const boost::python::tuple& shape=boost::python::make_tuple(),    Data(double value,
194           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
211    */    */
212      ESCRIPT_DLL_API
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
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         \brief produce a delayed evaluation version of this Data.
232      */
233      ESCRIPT_DLL_API
234      Data
235      delay();
236    
237      /**
238       Member access methods.       Member access methods.
239    */    */
240    
241    /**    /**
242       \brief       \brief
243       Return the values of all data-points as a single python numarray object.       switches on update protection
244    
245    */    */
246    const boost::python::numeric::array    ESCRIPT_DLL_API
247    convertToNumArray();    void
248      setProtection();
249    
250    /**    /**
251       \brief       \brief
252       Return the values of all data-points for the given sample as a single python numarray object.       Returns trueif the data object is protected against update
253    
254    */    */
255    const boost::python::numeric::array    ESCRIPT_DLL_API
256    convertToNumArrayFromSampleNo(int sampleNo);    bool
257      isProtected() const;
258    
259    /**    /**
260       \brief       \brief
261       Return the value of the specified data-point as a single python numarray object.       Return the values of a data point on this process
262    */    */
263      ESCRIPT_DLL_API
264    const boost::python::numeric::array    const boost::python::numeric::array
265    convertToNumArrayFromDPNo(int sampleNo,    getValueOfDataPoint(int dataPointNo);
266                              int dataPointNo);  
267      /**
268         \brief
269         sets the values of a data-point from a python object on this process
270      */
271      ESCRIPT_DLL_API
272      void
273      setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
274    
275    /**    /**
276       \brief       \brief
277       Fills the expanded Data object from values of a python numarray object.       sets the values of a data-point from a numarray object on this process
278    */    */
279      ESCRIPT_DLL_API
280    void    void
281    fillFromNumArray(const boost::python::numeric::array);    setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
282    
283      /**
284         \brief
285         sets the values of a data-point on this process
286      */
287      ESCRIPT_DLL_API
288      void
289      setValueOfDataPoint(int dataPointNo, const double);
290    
291      /**
292         \brief
293         Return the value of the specified data-point across all processors
294      */
295      ESCRIPT_DLL_API
296      const boost::python::numeric::array
297      getValueOfGlobalDataPoint(int procNo, int dataPointNo);
298    
299    /**    /**
300       \brief       \brief
301       Return the tag number associated with the given data-point.       Return the tag number associated with the given data-point.
302    
      The data-point number here corresponds to the data-point number in the  
      numarray returned by convertToNumArray.  
303    */    */
304      ESCRIPT_DLL_API
305    int    int
306    getTagNumber(int dpno);    getTagNumber(int dpno);
307    
# Line 260  class Data { Line 309  class Data {
309       \brief       \brief
310       Return the C wrapper for the Data object.       Return the C wrapper for the Data object.
311    */    */
312      ESCRIPT_DLL_API
313    escriptDataC    escriptDataC
314    getDataC();    getDataC();
315    
316    
317    
318    
319    
320    
321    // REMOVE ME
322    // ESCRIPT_DLL_API
323    // void
324    // CompareDebug(const Data& rd);
325    
326    
327    /**    /**
328       \brief       \brief
329       Return the C wrapper for the Data object - const version.       Return the C wrapper for the Data object - const version.
330    */    */
331      ESCRIPT_DLL_API
332    escriptDataC    escriptDataC
333    getDataC() const;    getDataC() const;
334    
335    /**    /**
336       \brief       \brief
337       Write the data as a string.       Write the data as a string. For large amounts of data, a summary is printed.
338    */    */
339    inline    ESCRIPT_DLL_API
340    std::string    std::string
341    toString() const    toString() const;
   {  
     return m_data->toString();  
   }  
342    
343    /**  
344       \brief  //  /**
345    /*     \brief
346       Return the DataArrayView of the point data. This essentially contains       Return the DataArrayView of the point data. This essentially contains
347       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
348       to manipulate the point data.       to manipulate the point data.*/
349    */  //  */
350    inline  //   ESCRIPT_DLL_API
351    const DataArrayView&  //   inline
352    getPointDataView() const  //   const DataArrayView&
353    {  //   getPointDataView() const
354       return m_data->getPointDataView();  //   {
355    }  //      return m_data->getPointDataView();
356    //   }
357    
358    /**    /**
359       \brief       \brief
360       Whatever the current Data type make this into a DataExpanded.       Whatever the current Data type make this into a DataExpanded.
361    */    */
362      ESCRIPT_DLL_API
363    void    void
364    expand();    expand();
365    
# Line 308  class Data { Line 370  class Data {
370       Expanded data to tagged will throw an exception.       Expanded data to tagged will throw an exception.
371      ==>*      ==>*
372    */    */
373      ESCRIPT_DLL_API
374    void    void
375    tag();    tag();
376    
# Line 315  class Data { Line 378  class Data {
378       \brief       \brief
379       Return true if this Data is expanded.       Return true if this Data is expanded.
380    */    */
381      ESCRIPT_DLL_API
382    bool    bool
383    isExpanded() const;    isExpanded() const;
384    
# Line 322  class Data { Line 386  class Data {
386       \brief       \brief
387       Return true if this Data is tagged.       Return true if this Data is tagged.
388    */    */
389      ESCRIPT_DLL_API
390    bool    bool
391    isTagged() const;    isTagged() const;
392    
# Line 329  class Data { Line 394  class Data {
394       \brief       \brief
395       Return true if this Data is constant.       Return true if this Data is constant.
396    */    */
397      ESCRIPT_DLL_API
398    bool    bool
399    isConstant() const;    isConstant() const;
400    
401    /**    /**
402         \brief Return true if this Data is lazy.
403      */
404      ESCRIPT_DLL_API
405      bool
406      isLazy() const;
407    
408      /**
409       \brief       \brief
410       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
411    contains datapoints.
412    */    */
413      ESCRIPT_DLL_API
414    bool    bool
415    isEmpty() const;    isEmpty() const;
416    
# Line 343  class Data { Line 418  class Data {
418       \brief       \brief
419       Return the function space.       Return the function space.
420    */    */
421      ESCRIPT_DLL_API
422    inline    inline
423    const FunctionSpace&    const FunctionSpace&
424    getFunctionSpace() const    getFunctionSpace() const
# Line 354  class Data { Line 430  class Data {
430       \brief       \brief
431       Return a copy of the function space.       Return a copy of the function space.
432    */    */
433      ESCRIPT_DLL_API
434    const FunctionSpace    const FunctionSpace
435    getCopyOfFunctionSpace() const;    getCopyOfFunctionSpace() const;
436    
# Line 361  class Data { Line 438  class Data {
438       \brief       \brief
439       Return the domain.       Return the domain.
440    */    */
441      ESCRIPT_DLL_API
442    inline    inline
443    const AbstractDomain&  //   const AbstractDomain&
444      const_Domain_ptr
445    getDomain() const    getDomain() const
446    {    {
447       return getFunctionSpace().getDomain();       return getFunctionSpace().getDomain();
448    }    }
449    
450    
451      /**
452         \brief
453         Return the domain.
454         TODO: For internal use only.   This should be removed.
455      */
456      ESCRIPT_DLL_API
457      inline
458    //   const AbstractDomain&
459      Domain_ptr
460      getDomainPython() const
461      {
462         return getFunctionSpace().getDomainPython();
463      }
464    
465    /**    /**
466       \brief       \brief
467       Return a copy of the domain.       Return a copy of the domain.
468    */    */
469      ESCRIPT_DLL_API
470    const AbstractDomain    const AbstractDomain
471    getCopyOfDomain() const;    getCopyOfDomain() const;
472    
# Line 379  class Data { Line 474  class Data {
474       \brief       \brief
475       Return the rank of the point data.       Return the rank of the point data.
476    */    */
477      ESCRIPT_DLL_API
478    inline    inline
479    int    int
480    getDataPointRank() const    getDataPointRank() const
481    {    {
482      return m_data->getPointDataView().getRank();  //    return m_data->getPointDataView().getRank();
483        return m_data->getRank();
484    }    }
485    
486    /**    /**
487       \brief       \brief
488         Return the number of data points
489      */
490      ESCRIPT_DLL_API
491      inline
492      int
493      getNumDataPoints() const
494      {
495        return getNumSamples() * getNumDataPointsPerSample();
496      }
497      /**
498         \brief
499       Return the number of samples.       Return the number of samples.
500    */    */
501      ESCRIPT_DLL_API
502    inline    inline
503    int    int
504    getNumSamples() const    getNumSamples() const
# Line 401  class Data { Line 510  class Data {
510       \brief       \brief
511       Return the number of data points per sample.       Return the number of data points per sample.
512    */    */
513      ESCRIPT_DLL_API
514    inline    inline
515    int    int
516    getNumDataPointsPerSample() const    getNumDataPointsPerSample() const
# Line 408  class Data { Line 518  class Data {
518      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
519    }    }
520    
521    
522      /**
523        \brief
524        Return the number of values in the shape for this object.
525      */
526      ESCRIPT_DLL_API
527      int
528      getNoValues() const
529      {
530        return m_data->getNoValues();
531      }
532    
533    
534      /**
535         \brief
536         dumps the object into a netCDF file
537      */
538      ESCRIPT_DLL_API
539      void
540      dump(const std::string fileName) const;
541    
542    /**    /**
543       \brief       \brief
544       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
545       preferred interface but is provided for use by C code.       preferred interface but is provided for use by C code.
546       \param sampleNo - Input - the given sample no.       \param sampleNo - Input - the given sample no.
547    */    */
548      ESCRIPT_DLL_API
549    inline    inline
550    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
551    getSampleData(DataAbstract::ValueType::size_type sampleNo)    getSampleData(DataAbstract::ValueType::size_type sampleNo);
   {  
     return m_data->getSampleData(sampleNo);  
   }  
552    
553    /**    /**
554       \brief       \brief
# Line 427  class Data { Line 556  class Data {
556       access data that isn't tagged an exception will be thrown.       access data that isn't tagged an exception will be thrown.
557       \param tag - Input - the tag key.       \param tag - Input - the tag key.
558    */    */
559      ESCRIPT_DLL_API
560    inline    inline
561    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
562    getSampleDataByTag(int tag)    getSampleDataByTag(int tag)
# Line 436  class Data { Line 566  class Data {
566    
567    /**    /**
568       \brief       \brief
569       Assign the given value to the data-points referenced by the given       Return a view into the data for the data point specified.
570       reference number.       NOTE: Construction of the DataArrayView is a relatively expensive
571         operation.
572       The value supplied is a python numarray object.  The data from this numarray       \param sampleNo - Input -
573       is unpacked into a DataArray, and this is used to set the corresponding       \param dataPointNo - Input -
      data-points in the underlying Data object.  
   
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
   
      \param ref - Input - reference number.  
      \param value - Input - value to assign to data-points associated with  
                             the given reference number.  
574    */    */
575    void    ESCRIPT_DLL_API
576    setRefValue(int ref,    DataTypes::ValueType::const_reference
577                const boost::python::numeric::array& value);    getDataPoint(int sampleNo, int dataPointNo) const;
578    
   /**  
      \brief  
      Return the values associated with the data-points referenced by the given  
      reference number.  
579    
580       The value supplied is a python numarray object. The data from the corresponding    ESCRIPT_DLL_API
581       data-points in this Data object are packed into the given numarray object.    DataTypes::ValueType::reference
582      getDataPoint(int sampleNo, int dataPointNo);
583    
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
584    
      \param ref - Input - reference number.  
      \param value - Output - object to receive values from data-points  
                              associated with the given reference number.  
   */  
   void  
   getRefValue(int ref,  
               boost::python::numeric::array& value);  
585    
586    /**    /**
587       \brief       \brief
588       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 -  
589    */    */
590      ESCRIPT_DLL_API
591    inline    inline
592    DataArrayView    DataTypes::ValueType::size_type
593    getDataPoint(int sampleNo,    getDataOffset(int sampleNo,
594                 int dataPointNo)                 int dataPointNo)
595    {    {
596      return m_data->getDataPoint(sampleNo,dataPointNo);        return m_data->getPointOffset(sampleNo,dataPointNo);
597    }    }
598    
599    /**    /**
600       \brief       \brief
601       Return a reference to the data point shape.       Return a reference to the data point shape.
602    */    */
603    const DataArrayView::ShapeType&    ESCRIPT_DLL_API
604    getDataPointShape() const;    inline
605      const DataTypes::ShapeType&
606      getDataPointShape() const
607      {
608        return m_data->getShape();
609      }
610    
611    /**    /**
612       \brief       \brief
613       Return the data point shape as a tuple of integers.       Return the data point shape as a tuple of integers.
614    */    */
615      ESCRIPT_DLL_API
616    const boost::python::tuple    const boost::python::tuple
617    getShapeTuple() const;    getShapeTuple() const;
618    
# Line 508  class Data { Line 621  class Data {
621       Return the size of the data point. It is the product of the       Return the size of the data point. It is the product of the
622       data point shape dimensions.       data point shape dimensions.
623    */    */
624      ESCRIPT_DLL_API
625    int    int
626    getDataPointSize() const;    getDataPointSize() const;
627    
# Line 515  class Data { Line 629  class Data {
629       \brief       \brief
630       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
631    */    */
632    DataArrayView::ValueType::size_type    ESCRIPT_DLL_API
633      DataTypes::ValueType::size_type
634    getLength() const;    getLength() const;
635    
636    
637    
638    /**    /**
639       \brief       \brief
640       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag assocciated with name. Implicitly converts this
641       object to type DataTagged. Throws an exception if this object       object to type DataTagged. Throws an exception if this object
642       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
643       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
644       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
645      ==>*      ==>*
646    */    */
647      ESCRIPT_DLL_API
648      void
649      setTaggedValueByName(std::string name,
650                           const boost::python::object& value);
651    
652      /**
653         \brief
654         Assign the given value to the tag. Implicitly converts this
655         object to type DataTagged if it is constant.
656    
657         \param tagKey - Input - Integer key.
658         \param value - Input - Value to associate with given key.
659        ==>*
660      */
661      ESCRIPT_DLL_API
662    void    void
663    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
664                   const boost::python::object& value);                   const boost::python::object& value);
# Line 534  class Data { Line 666  class Data {
666    /**    /**
667       \brief       \brief
668       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
669       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
670       cannot be converted to a DataTagged object.  
671       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
672         \param pointshape - Input - The shape of the value parameter
673       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
674      ==>*       \param dataOffset - Input - Offset of the begining of the point within the value parameter
675    */    */
676      ESCRIPT_DLL_API
677    void    void
678    setTaggedValueFromCPP(int tagKey,    setTaggedValueFromCPP(int tagKey,
679                          const DataArrayView& value);              const DataTypes::ShapeType& pointshape,
680                            const DataTypes::ValueType& value,
681                int dataOffset=0);
682    
683    
684    
685    /**    /**
686      \brief      \brief
687      Copy other Data object into this Data object where mask is positive.      Copy other Data object into this Data object where mask is positive.
688    */    */
689      ESCRIPT_DLL_API
690    void    void
691    copyWithMask(const Data& other,    copyWithMask(const Data& other,
692                 const Data& mask);                 const Data& mask);
# Line 558  class Data { Line 697  class Data {
697    
698    /**    /**
699       \brief       \brief
700         set all values to zero
701         *
702      */
703      ESCRIPT_DLL_API
704      void
705      setToZero();
706    
707      /**
708         \brief
709       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
710       the result as a Data object.       the result as a Data object.
711       *       *
712    */    */
713      ESCRIPT_DLL_API
714    Data    Data
715    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
716    /**    /**
717       \brief       \brief
718       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
719       If functionspace is not present the function space of Function(getDomain()) is used.       If functionspace is not present the function space of Function(getDomain()) is used.
720       *       *
721    */    */
722      ESCRIPT_DLL_API
723    Data    Data
724    gradOn(const FunctionSpace& functionspace) const;    gradOn(const FunctionSpace& functionspace) const;
725    
726      ESCRIPT_DLL_API
727    Data    Data
728    grad() const;    grad() const;
729    
# Line 582  class Data { Line 732  class Data {
732       Calculate the integral over the function space domain.       Calculate the integral over the function space domain.
733       *       *
734    */    */
735      ESCRIPT_DLL_API
736    boost::python::numeric::array    boost::python::numeric::array
737    integrate() const;    integrate() const;
738    
739    /**    /**
740       \brief       \brief
741         Returns 1./ Data object
742         *
743      */
744      ESCRIPT_DLL_API
745      Data
746      oneOver() const;
747      /**
748         \brief
749       Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.       Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.
750       *       *
751    */    */
752      ESCRIPT_DLL_API
753    Data    Data
754    wherePositive() const;    wherePositive() const;
755    
# Line 598  class Data { Line 758  class Data {
758       Return a Data with a 1 for -ive values and a 0 for +ive or 0 values.       Return a Data with a 1 for -ive values and a 0 for +ive or 0 values.
759       *       *
760    */    */
761      ESCRIPT_DLL_API
762    Data    Data
763    whereNegative() const;    whereNegative() const;
764    
# Line 606  class Data { Line 767  class Data {
767       Return a Data with a 1 for +ive or 0 values and a 0 for -ive values.       Return a Data with a 1 for +ive or 0 values and a 0 for -ive values.
768       *       *
769    */    */
770      ESCRIPT_DLL_API
771    Data    Data
772    whereNonNegative() const;    whereNonNegative() const;
773    
# Line 614  class Data { Line 776  class Data {
776       Return a Data with a 1 for -ive or 0 values and a 0 for +ive values.       Return a Data with a 1 for -ive or 0 values and a 0 for +ive values.
777       *       *
778    */    */
779      ESCRIPT_DLL_API
780    Data    Data
781    whereNonPositive() const;    whereNonPositive() const;
782    
# Line 622  class Data { Line 785  class Data {
785       Return a Data with a 1 for 0 values and a 0 for +ive or -ive values.       Return a Data with a 1 for 0 values and a 0 for +ive or -ive values.
786       *       *
787    */    */
788      ESCRIPT_DLL_API
789    Data    Data
790    whereZero(double tol=0.0) const;    whereZero(double tol=0.0) const;
791    
# Line 630  class Data { Line 794  class Data {
794       Return a Data with a 0 for 0 values and a 1 for +ive or -ive values.       Return a Data with a 0 for 0 values and a 1 for +ive or -ive values.
795       *       *
796    */    */
797      ESCRIPT_DLL_API
798    Data    Data
799    whereNonZero(double tol=0.0) const;    whereNonZero(double tol=0.0) const;
800    
# Line 638  class Data { Line 803  class Data {
803       Return the maximum absolute value of this Data object.       Return the maximum absolute value of this Data object.
804       *       *
805    */    */
806      ESCRIPT_DLL_API
807    double    double
808    Lsup() const;    Lsup() const;
809    
810    /**    /**
811       \brief       \brief
      Return the minimum absolute value of this Data object.  
      *  
   */  
   double  
   Linf() const;  
   
   /**  
      \brief  
812       Return the maximum value of this Data object.       Return the maximum value of this Data object.
813       *       *
814    */    */
815      ESCRIPT_DLL_API
816    double    double
817    sup() const;    sup() const;
818    
# Line 662  class Data { Line 821  class Data {
821       Return the minimum value of this Data object.       Return the minimum value of this Data object.
822       *       *
823    */    */
824      ESCRIPT_DLL_API
825    double    double
826    inf() const;    inf() const;
827    
# Line 670  class Data { Line 830  class Data {
830       Return the absolute value of each data point of this Data object.       Return the absolute value of each data point of this Data object.
831       *       *
832    */    */
833      ESCRIPT_DLL_API
834    Data    Data
835    abs() const;    abs() const;
836    
# Line 678  class Data { Line 839  class Data {
839       Return the maximum value of each data point of this Data object.       Return the maximum value of each data point of this Data object.
840       *       *
841    */    */
842      ESCRIPT_DLL_API
843    Data    Data
844    maxval() const;    maxval() const;
845    
# Line 686  class Data { Line 848  class Data {
848       Return the minimum value of each data point of this Data object.       Return the minimum value of each data point of this Data object.
849       *       *
850    */    */
851      ESCRIPT_DLL_API
852    Data    Data
853    minval() const;    minval() const;
854    
# Line 694  class Data { Line 857  class Data {
857       Return the (sample number, data-point number) of the data point with       Return the (sample number, data-point number) of the data point with
858       the minimum value in this Data object.       the minimum value in this Data object.
859    */    */
860      ESCRIPT_DLL_API
861    const boost::python::tuple    const boost::python::tuple
862    mindp() const;    minGlobalDataPoint() const;
863    
864      ESCRIPT_DLL_API
865    void    void
866    calc_mindp(int& SampleNo,    calc_minGlobalDataPoint(int& ProcNo,  int& DataPointNo) const;
              int& DataPointNo) const;  
   
867    /**    /**
868       \brief       \brief
869       Return the sign of each data point of this Data object.       Return the sign of each data point of this Data object.
870       -1 for negative values, zero for zero values, 1 for positive values.       -1 for negative values, zero for zero values, 1 for positive values.
871       *       *
872    */    */
873      ESCRIPT_DLL_API
874    Data    Data
875    sign() const;    sign() const;
876    
877    /**    /**
878       \brief       \brief
879         Return the symmetric part of a matrix which is half the matrix plus its transpose.
880         *
881      */
882      ESCRIPT_DLL_API
883      Data
884      symmetric() const;
885    
886      /**
887         \brief
888         Return the nonsymmetric part of a matrix which is half the matrix minus its transpose.
889         *
890      */
891      ESCRIPT_DLL_API
892      Data
893      nonsymmetric() const;
894    
895      /**
896         \brief
897         Return the trace of a matrix
898         *
899      */
900      ESCRIPT_DLL_API
901      Data
902      trace(int axis_offset) const;
903    
904      /**
905         \brief
906         Transpose each data point of this Data object around the given axis.
907         *
908      */
909      ESCRIPT_DLL_API
910      Data
911      transpose(int axis_offset) const;
912    
913      /**
914         \brief
915       Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.       Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.
916       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.
917       *       *
918    */    */
919      ESCRIPT_DLL_API
920    Data    Data
921    eigenvalues() const;    eigenvalues() const;
922    
923    /**    /**
924       \brief       \brief
925       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.
926       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
927       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
928       first non-zero entry is positive.       first non-zero entry is positive.
929       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
930       *       *
931    */    */
932      ESCRIPT_DLL_API
933    const boost::python::tuple    const boost::python::tuple
934    eigenvalues_and_eigenvectors(const double tol=1.e-12) const;    eigenvalues_and_eigenvectors(const double tol=1.e-12) const;
935    
936    /**    /**
937       \brief       \brief
938       Transpose each data point of this Data object around the given axis.       swaps the components axis0 and axis1
      --* not implemented yet *--  
939       *       *
940    */    */
941      ESCRIPT_DLL_API
942    Data    Data
943    transpose(int axis) const;    swapaxes(const int axis0, const int axis1) const;
944    
945    /**    /**
946       \brief       \brief
947       Calculate the trace of each data point of this Data object.       Return the error function erf of each data point of this Data object.
948       *       *
949    */    */
950      ESCRIPT_DLL_API
951    Data    Data
952    trace() const;    erf() const;
953    
954    /**    /**
955       \brief       \brief
956       Return the sin of each data point of this Data object.       Return the sin of each data point of this Data object.
957       *       *
958    */    */
959      ESCRIPT_DLL_API
960    Data    Data
961    sin() const;    sin() const;
962    
# Line 761  class Data { Line 965  class Data {
965       Return the cos of each data point of this Data object.       Return the cos of each data point of this Data object.
966       *       *
967    */    */
968      ESCRIPT_DLL_API
969    Data    Data
970    cos() const;    cos() const;
971    
# Line 769  class Data { Line 974  class Data {
974       Return the tan of each data point of this Data object.       Return the tan of each data point of this Data object.
975       *       *
976    */    */
977      ESCRIPT_DLL_API
978    Data    Data
979    tan() const;    tan() const;
980    
# Line 777  class Data { Line 983  class Data {
983       Return the asin of each data point of this Data object.       Return the asin of each data point of this Data object.
984       *       *
985    */    */
986      ESCRIPT_DLL_API
987    Data    Data
988    asin() const;    asin() const;
989    
# Line 785  class Data { Line 992  class Data {
992       Return the acos of each data point of this Data object.       Return the acos of each data point of this Data object.
993       *       *
994    */    */
995      ESCRIPT_DLL_API
996    Data    Data
997    acos() const;    acos() const;
998    
# Line 793  class Data { Line 1001  class Data {
1001       Return the atan of each data point of this Data object.       Return the atan of each data point of this Data object.
1002       *       *
1003    */    */
1004      ESCRIPT_DLL_API
1005    Data    Data
1006    atan() const;    atan() const;
1007    
# Line 801  class Data { Line 1010  class Data {
1010       Return the sinh of each data point of this Data object.       Return the sinh of each data point of this Data object.
1011       *       *
1012    */    */
1013      ESCRIPT_DLL_API
1014    Data    Data
1015    sinh() const;    sinh() const;
1016    
# Line 809  class Data { Line 1019  class Data {
1019       Return the cosh of each data point of this Data object.       Return the cosh of each data point of this Data object.
1020       *       *
1021    */    */
1022      ESCRIPT_DLL_API
1023    Data    Data
1024    cosh() const;    cosh() const;
1025    
# Line 817  class Data { Line 1028  class Data {
1028       Return the tanh of each data point of this Data object.       Return the tanh of each data point of this Data object.
1029       *       *
1030    */    */
1031      ESCRIPT_DLL_API
1032    Data    Data
1033    tanh() const;    tanh() const;
1034    
# Line 825  class Data { Line 1037  class Data {
1037       Return the asinh of each data point of this Data object.       Return the asinh of each data point of this Data object.
1038       *       *
1039    */    */
1040      ESCRIPT_DLL_API
1041    Data    Data
1042    asinh() const;    asinh() const;
1043    
# Line 833  class Data { Line 1046  class Data {
1046       Return the acosh of each data point of this Data object.       Return the acosh of each data point of this Data object.
1047       *       *
1048    */    */
1049      ESCRIPT_DLL_API
1050    Data    Data
1051    acosh() const;    acosh() const;
1052    
# Line 841  class Data { Line 1055  class Data {
1055       Return the atanh of each data point of this Data object.       Return the atanh of each data point of this Data object.
1056       *       *
1057    */    */
1058      ESCRIPT_DLL_API
1059    Data    Data
1060    atanh() const;    atanh() const;
1061    
# Line 849  class Data { Line 1064  class Data {
1064       Return the log to base 10 of each data point of this Data object.       Return the log to base 10 of each data point of this Data object.
1065       *       *
1066    */    */
1067      ESCRIPT_DLL_API
1068    Data    Data
1069    log10() const;    log10() const;
1070    
# Line 857  class Data { Line 1073  class Data {
1073       Return the natural log of each data point of this Data object.       Return the natural log of each data point of this Data object.
1074       *       *
1075    */    */
1076      ESCRIPT_DLL_API
1077    Data    Data
1078    log() const;    log() const;
1079    
# Line 865  class Data { Line 1082  class Data {
1082       Return the exponential function of each data point of this Data object.       Return the exponential function of each data point of this Data object.
1083       *       *
1084    */    */
1085      ESCRIPT_DLL_API
1086    Data    Data
1087    exp() const;    exp() const;
1088    
# Line 873  class Data { Line 1091  class Data {
1091       Return the square root of each data point of this Data object.       Return the square root of each data point of this Data object.
1092       *       *
1093    */    */
1094      ESCRIPT_DLL_API
1095    Data    Data
1096    sqrt() const;    sqrt() const;
1097    
# Line 881  class Data { Line 1100  class Data {
1100       Return the negation of each data point of this Data object.       Return the negation of each data point of this Data object.
1101       *       *
1102    */    */
1103      ESCRIPT_DLL_API
1104    Data    Data
1105    neg() const;    neg() const;
1106    
# Line 890  class Data { Line 1110  class Data {
1110       Simply returns this object unmodified.       Simply returns this object unmodified.
1111       *       *
1112    */    */
1113      ESCRIPT_DLL_API
1114    Data    Data
1115    pos() const;    pos() const;
1116    
# Line 900  class Data { Line 1121  class Data {
1121       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1122       *       *
1123    */    */
1124      ESCRIPT_DLL_API
1125    Data    Data
1126    powD(const Data& right) const;    powD(const Data& right) const;
1127    
1128    /**    /**
1129       \brief       \brief
1130       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.
1131        
1132       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1133       *       *
1134     */     */
1135      ESCRIPT_DLL_API
1136    Data    Data
1137    powO(const boost::python::object& right) const;    powO(const boost::python::object& right) const;
1138    
1139    /**    /**
1140       \brief       \brief
1141         Return the given power of each data point of this boost python object.
1142    
1143         \param left Input - the bases
1144         *
1145       */
1146    
1147      ESCRIPT_DLL_API
1148      Data
1149      rpowO(const boost::python::object& left) const;
1150    
1151      /**
1152         \brief
1153       writes the object to a file in the DX file format       writes the object to a file in the DX file format
1154    */    */
1155      ESCRIPT_DLL_API
1156    void    void
1157    saveDX(std::string fileName) const;    saveDX(std::string fileName) const;
1158    
# Line 924  class Data { Line 1160  class Data {
1160       \brief       \brief
1161       writes the object to a file in the VTK file format       writes the object to a file in the VTK file format
1162    */    */
1163      ESCRIPT_DLL_API
1164    void    void
1165    saveVTK(std::string fileName) const;    saveVTK(std::string fileName) const;
1166    
# Line 933  class Data { Line 1170  class Data {
1170       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1171       *       *
1172    */    */
1173      ESCRIPT_DLL_API
1174    Data& operator+=(const Data& right);    Data& operator+=(const Data& right);
1175      ESCRIPT_DLL_API
1176    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1177    
1178      ESCRIPT_DLL_API
1179      Data& operator=(const Data& other);
1180    
1181    /**    /**
1182       \brief       \brief
1183       Overloaded operator -=       Overloaded operator -=
1184       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1185       *       *
1186    */    */
1187      ESCRIPT_DLL_API
1188    Data& operator-=(const Data& right);    Data& operator-=(const Data& right);
1189      ESCRIPT_DLL_API
1190    Data& operator-=(const boost::python::object& right);    Data& operator-=(const boost::python::object& right);
1191    
1192   /**   /**
# Line 951  class Data { Line 1195  class Data {
1195       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1196       *       *
1197    */    */
1198      ESCRIPT_DLL_API
1199    Data& operator*=(const Data& right);    Data& operator*=(const Data& right);
1200      ESCRIPT_DLL_API
1201    Data& operator*=(const boost::python::object& right);    Data& operator*=(const boost::python::object& right);
1202    
1203   /**   /**
# Line 960  class Data { Line 1206  class Data {
1206       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1207       *       *
1208    */    */
1209      ESCRIPT_DLL_API
1210    Data& operator/=(const Data& right);    Data& operator/=(const Data& right);
1211      ESCRIPT_DLL_API
1212    Data& operator/=(const boost::python::object& right);    Data& operator/=(const boost::python::object& right);
1213    
1214    /**    /**
1215       \brief       \brief
1216       Returns true if this can be interpolated to functionspace.       Returns true if this can be interpolated to functionspace.
1217    */    */
1218      ESCRIPT_DLL_API
1219    bool    bool
1220    probeInterpolation(const FunctionSpace& functionspace) const;    probeInterpolation(const FunctionSpace& functionspace) const;
1221    
# Line 985  class Data { Line 1234  class Data {
1234       \param key - Input - python slice tuple specifying       \param key - Input - python slice tuple specifying
1235       slice to return.       slice to return.
1236    */    */
1237      ESCRIPT_DLL_API
1238    Data    Data
1239    getItem(const boost::python::object& key) const;    getItem(const boost::python::object& key) const;
1240    
# Line 999  class Data { Line 1249  class Data {
1249       slice to copy from value.       slice to copy from value.
1250       \param value - Input - Data object to copy from.       \param value - Input - Data object to copy from.
1251    */    */
1252      ESCRIPT_DLL_API
1253    void    void
1254    setItemD(const boost::python::object& key,    setItemD(const boost::python::object& key,
1255             const Data& value);             const Data& value);
1256    
1257      ESCRIPT_DLL_API
1258    void    void
1259    setItemO(const boost::python::object& key,    setItemO(const boost::python::object& key,
1260             const boost::python::object& value);             const boost::python::object& value);
# Line 1015  class Data { Line 1267  class Data {
1267       this Data object.       this Data object.
1268    */    */
1269    template <class UnaryFunction>    template <class UnaryFunction>
1270      ESCRIPT_DLL_API
1271    inline    inline
1272    void    void
1273    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1274    
1275    /**    /**
1276       \brief       \brief
# Line 1026  class Data { Line 1279  class Data {
1279       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1280       *       *
1281    */    */
1282      ESCRIPT_DLL_API
1283    Data    Data
1284    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataTypes::RegionType& region) const;
1285    
1286    /**    /**
1287       \brief       \brief
# Line 1037  class Data { Line 1291  class Data {
1291       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1292       *       *
1293    */    */
1294      ESCRIPT_DLL_API
1295    void    void
1296    setSlice(const Data& value,    setSlice(const Data& value,
1297             const DataArrayView::RegionType& region);             const DataTypes::RegionType& region);
1298    
1299    /**    /**
1300       \brief       \brief
1301       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.  
1302    */    */
1303      ESCRIPT_DLL_API
1304    void    void
1305    archiveData(const std::string fileName);          print(void);
1306    
1307    /**    /**
1308       \brief       \brief
1309       Extract the Data object archived in the given file, overwriting       return the MPI rank number of the local data
1310       the current Data object.                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1311       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.  
1312    */    */
1313    void    ESCRIPT_DLL_API
1314    extractData(const std::string fileName,          int
1315                const FunctionSpace& fspace);          get_MPIRank(void) const;
1316    
1317      /**
1318         \brief
1319         return the MPI rank number of the local data
1320                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1321                     is returned
1322      */
1323      ESCRIPT_DLL_API
1324            int
1325            get_MPISize(void) const;
1326    
1327      /**
1328         \brief
1329         return the MPI rank number of the local data
1330                     MPI_COMM_WORLD is assumed and returned.
1331      */
1332      ESCRIPT_DLL_API
1333            MPI_Comm
1334            get_MPIComm(void) const;
1335    
1336      /**
1337         \brief
1338         return the object produced by the factory, which is a DataConstant or DataExpanded
1339        TODO Ownership of this object should be explained in doco.
1340      */
1341      ESCRIPT_DLL_API
1342            DataAbstract*
1343            borrowData(void) const;
1344    
1345    
1346      /**
1347         \brief
1348         Return a pointer to the beginning of the datapoint at the specified offset.
1349         TODO Eventually these should be inlined.
1350         \param i - position(offset) in the underlying datastructure
1351      */
1352      ESCRIPT_DLL_API
1353            DataTypes::ValueType::const_reference
1354            getDataAtOffset(DataTypes::ValueType::size_type i) const;
1355    
1356    
1357      ESCRIPT_DLL_API
1358            DataTypes::ValueType::reference
1359            getDataAtOffset(DataTypes::ValueType::size_type i);
1360    
1361   protected:   protected:
1362    
# Line 1118  class Data { Line 1415  class Data {
1415    
1416    /**    /**
1417       \brief       \brief
      Perform the given binary operation on all of the data's elements.  
      RHS is a boost::python object.  
   */  
   template <class BinaryFunction>  
   inline  
   void  
   binaryOp(const boost::python::object& right,  
            BinaryFunction operation);  
   
   /**  
      \brief  
1418       Convert the data type of the RHS to match this.       Convert the data type of the RHS to match this.
1419       \param right - Input - data type to match.       \param right - Input - data type to match.
1420    */    */
# Line 1147  class Data { Line 1433  class Data {
1433       \brief       \brief
1434       Construct a Data object of the appropriate type.       Construct a Data object of the appropriate type.
1435    */    */
1436    template <class IValueType>  
1437    void    void
1438    initialise(const IValueType& value,    initialise(const DataTypes::ValueType& value,
1439             const DataTypes::ShapeType& shape,
1440               const FunctionSpace& what,               const FunctionSpace& what,
1441               bool expanded);               bool expanded);
1442    
   /**  
      \brief  
      Reshape the data point if the data point is currently rank 0.  
      Will throw an exception if the data points are not rank 0.  
      The original data point value is used for all values of the new  
      data point.  
   */  
1443    void    void
1444    reshapeDataPoint(const DataArrayView::ShapeType& shape);    initialise(const boost::python::numeric::array& value,
1445                     const FunctionSpace& what,
1446                     bool expanded);
1447    
1448    //    //
1449    // pointer to the actual data object    // flag to protect the data object against any update
1450    boost::shared_ptr<DataAbstract> m_data;    bool m_protected;
1451    
1452    //    //
1453    // pointer to the internal profiling data    // pointer to the actual data object
1454    struct profDataEntry *profData;  //   boost::shared_ptr<DataAbstract> m_data;
1455      DataAbstract_ptr m_data;
1456    
1457      const DataReady*
1458      getReady() const;
1459    
1460      DataReady*
1461      getReady();
1462    
1463  };  };
1464    
1465  template <class IValueType>  }   // end namespace escript
1466  void  
1467  Data::initialise(const IValueType& value,  
1468                   const FunctionSpace& what,  // No, this is not supposed to be at the top of the file
1469                   bool expanded)  #include "DataReady.h"
1470    
1471    namespace escript
1472  {  {
1473    //  
1474    // Construct a Data object of the appropriate type.  inline
1475    // Construct the object first as there seems to be a bug which causes  const DataReady*
1476    // undefined behaviour if an exception is thrown during construction  Data::getReady() const
1477    // within the shared_ptr constructor.  {
1478    if (expanded) {     const DataReady* dr=dynamic_cast<const DataReady*>(m_data.get());
1479      DataAbstract* temp=new DataExpanded(value,what);     EsysAssert((dr!=0), "Error - casting to DataReady.");
1480      boost::shared_ptr<DataAbstract> temp_data(temp);     return dr;
     m_data=temp_data;  
   } else {  
     DataAbstract* temp=new DataConstant(value,what);  
     boost::shared_ptr<DataAbstract> temp_data(temp);  
     m_data=temp_data;  
   }  
1481  }  }
1482    
1483    inline
1484    DataReady*
1485    Data::getReady()
1486    {
1487       DataReady* dr=dynamic_cast<DataReady*>(m_data.get());
1488       EsysAssert((dr!=0), "Error - casting to DataReady.");
1489       return dr;
1490    }
1491    
1492    inline
1493    DataAbstract::ValueType::value_type*
1494    Data::getSampleData(DataAbstract::ValueType::size_type sampleNo)
1495    {
1496       return getReady()->getSampleData(sampleNo);
1497    }
1498    
1499    
1500    /**
1501       Modify a filename for MPI parallel output to multiple files
1502    */
1503    char *Escript_MPI_appendRankToFileName(const char *, int, int);
1504    
1505  /**  /**
1506     Binary Data object operators.     Binary Data object operators.
1507  */  */
1508    inline double rpow(double x,double y)
1509    {
1510        return pow(y,x);
1511    }
1512    
1513  /**  /**
1514    \brief    \brief
1515    Operator+    Operator+
1516    Takes two Data objects.    Takes two Data objects.
1517  */  */
1518  Data operator+(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1519    
1520  /**  /**
1521    \brief    \brief
1522    Operator-    Operator-
1523    Takes two Data objects.    Takes two Data objects.
1524  */  */
1525  Data operator-(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1526    
1527  /**  /**
1528    \brief    \brief
1529    Operator*    Operator*
1530    Takes two Data objects.    Takes two Data objects.
1531  */  */
1532  Data operator*(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1533    
1534  /**  /**
1535    \brief    \brief
1536    Operator/    Operator/
1537    Takes two Data objects.    Takes two Data objects.
1538  */  */
1539  Data operator/(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1540    
1541  /**  /**
1542    \brief    \brief
# Line 1233  Data operator/(const Data& left, const D Line 1544  Data operator/(const Data& left, const D
1544    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1545    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1546  */  */
1547  Data operator+(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const boost::python::object& right);
1548    
1549  /**  /**
1550    \brief    \brief
# Line 1241  Data operator+(const Data& left, const b Line 1552  Data operator+(const Data& left, const b
1552    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1553    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1554  */  */
1555  Data operator-(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const boost::python::object& right);
1556    
1557  /**  /**
1558    \brief    \brief
# Line 1249  Data operator-(const Data& left, const b Line 1560  Data operator-(const Data& left, const b
1560    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1561    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1562  */  */
1563  Data operator*(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const boost::python::object& right);
1564    
1565  /**  /**
1566    \brief    \brief
# Line 1257  Data operator*(const Data& left, const b Line 1568  Data operator*(const Data& left, const b
1568    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1569    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1570  */  */
1571  Data operator/(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const boost::python::object& right);
1572    
1573  /**  /**
1574    \brief    \brief
# Line 1265  Data operator/(const Data& left, const b Line 1576  Data operator/(const Data& left, const b
1576    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1577    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1578  */  */
1579  Data operator+(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const boost::python::object& left, const Data& right);
1580    
1581  /**  /**
1582    \brief    \brief
# Line 1273  Data operator+(const boost::python::obje Line 1584  Data operator+(const boost::python::obje
1584    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1585    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1586  */  */
1587  Data operator-(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const boost::python::object& left, const Data& right);
1588    
1589  /**  /**
1590    \brief    \brief
# Line 1281  Data operator-(const boost::python::obje Line 1592  Data operator-(const boost::python::obje
1592    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1593    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1594  */  */
1595  Data operator*(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const boost::python::object& left, const Data& right);
1596    
1597  /**  /**
1598    \brief    \brief
# Line 1289  Data operator*(const boost::python::obje Line 1600  Data operator*(const boost::python::obje
1600    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1601    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1602  */  */
1603  Data operator/(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1604    
1605    
1606    
1607  /**  /**
1608    \brief    \brief
1609    Output operator    Output operator
1610  */  */
1611  std::ostream& operator<<(std::ostream& o, const Data& data);  ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1612    
1613  /**  /**
1614    \brief    \brief
1615    Return true if operands are equivalent, else return false.    Compute a tensor product of two Data objects
1616    NB: this operator does very little at this point, and isn't to    \param arg0 - Input - Data object
1617    be relied on. Requires further implementation.    \param arg1 - Input - Data object
1618      \param axis_offset - Input - axis offset
1619      \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1620  */  */
1621  //bool operator==(const Data& left, const Data& right);  ESCRIPT_DLL_API
1622    Data
1623    C_GeneralTensorProduct(Data& arg0,
1624                         Data& arg1,
1625                         int axis_offset=0,
1626                         int transpose=0);
1627    
1628    
1629    
1630    // /**
1631    /*  \brief
1632      Return true if operands are equivalent, else return false.
1633      NB: this operator does very little at this point, and isn't to
1634      be relied on. Requires further implementation.*/
1635    //*/
1636    // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1637    
1638  /**  /**
1639    \brief    \brief
# Line 1318  Data::binaryOp(const Data& right, Line 1648  Data::binaryOp(const Data& right,
1648  {  {
1649     //     //
1650     // 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
1651     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1652       reshapeDataPoint(right.getPointDataView().getShape());       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1653       }
1654    
1655       if (isLazy() || right.isLazy())
1656       {
1657         throw DataException("Programmer error - attempt to call binaryOp with Lazy Data.");
1658     }     }
1659     //     //
1660     // initially make the temporary a shallow copy     // initially make the temporary a shallow copy
1661     Data tempRight(right);     Data tempRight(right);
1662    
1663     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1664       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1665         //         //
1666         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1667         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1668       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1669         //         //
# Line 1349  Data::binaryOp(const Data& right, Line 1685  Data::binaryOp(const Data& right,
1685       // of any data type       // of any data type
1686       DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());       DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1687       EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");       EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1688       escript::binaryOp(*leftC,*(tempRight.m_data.get()),operation);       escript::binaryOp(*leftC,*(tempRight.getReady()),operation);
1689     } else if (isTagged()) {     } else if (isTagged()) {
1690       //       //
1691       // Tagged data is operated on serially, the right hand side can be       // Tagged data is operated on serially, the right hand side can be
# Line 1375  Data::binaryOp(const Data& right, Line 1711  Data::binaryOp(const Data& right,
1711    
1712  /**  /**
1713    \brief    \brief
   Perform the given binary operation with this and right as operands.  
   Right is a boost::python object.  
 */  
 template <class BinaryFunction>  
 inline  
 void  
 Data::binaryOp(const boost::python::object& right,  
                BinaryFunction operation)  
 {  
    DataArray temp(right);  
    //  
    // if this has a rank of zero promote it to the rank of the RHS.  
    if (getPointDataView().getRank()==0 && temp.getView().getRank()!=0) {  
       reshapeDataPoint(temp.getView().getShape());  
    }  
    //  
    // Always allow scalar values for the RHS but check other shapes  
    if (temp.getView().getRank()!=0) {  
      if (!getPointDataView().checkShape(temp.getView().getShape())) {  
        throw DataException(getPointDataView().createShapeErrorMessage(  
                   "Error - RHS shape doesn't match LHS shape.",temp.getView().getShape()));  
      }  
    }  
    if (isExpanded()) {  
      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());  
      EsysAssert((leftC!=0),"Programming error - casting to DataExpanded.");  
      escript::binaryOp(*leftC,temp.getView(),operation);  
    } else if (isTagged()) {  
      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());  
      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");  
      escript::binaryOp(*leftC,temp.getView(),operation);  
    } else if (isConstant()) {  
      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());  
      EsysAssert((leftC!=0),"Programming error - casting to DataConstant.");  
      escript::binaryOp(*leftC,temp.getView(),operation);  
    }  
 }  
   
 /**  
   \brief  
   Perform the given unary operation on other and return the result.  
   Given operation is performed on each element of each data point, thus  
   argument object is a rank n Data object, and returned object is a rank n  
   Data object.  
   Calls Data::unaryOp.  
 */  
 template <class UnaryFunction>  
 inline  
 Data  
 unaryOp(const Data& other,  
         UnaryFunction operation)  
 {  
   Data result;  
   result.copy(other);  
   result.unaryOp(operation);  
   return result;  
 }  
   
 /**  
   \brief  
   Perform the given unary operation on this.  
   Given operation is performed on each element of each data point.  
   Calls escript::unaryOp.  
 */  
 template <class UnaryFunction>  
 inline  
 void  
 Data::unaryOp(UnaryFunction operation)  
 {  
   if (isExpanded()) {  
     DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());  
     EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");  
     escript::unaryOp(*leftC,operation);  
   } else if (isTagged()) {  
     DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());  
     EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");  
     escript::unaryOp(*leftC,operation);  
   } else if (isConstant()) {  
     DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());  
     EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");  
     escript::unaryOp(*leftC,operation);  
   }  
 }  
   
 /**  
   \brief  
1714    Perform the given Data object reduction algorithm on this and return the result.    Perform the given Data object reduction algorithm on this and return the result.
1715    Given operation combines each element of each data point, thus argument    Given operation combines each element of each data point, thus argument
1716    object (*this) is a rank n Data object, and returned object is a scalar.    object (*this) is a rank n Data object, and returned object is a scalar.
# Line 1483  Data::algorithm(BinaryFunction operation Line 1733  Data::algorithm(BinaryFunction operation
1733      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1734      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1735      return escript::algorithm(*leftC,operation,initial_value);      return escript::algorithm(*leftC,operation,initial_value);
1736      } else if (isEmpty()) {
1737        throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1738    }    }
1739    return 0;    return 0;
1740  }  }
# Line 1491  Data::algorithm(BinaryFunction operation Line 1743  Data::algorithm(BinaryFunction operation
1743    \brief    \brief
1744    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.
1745    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1746    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
1747    rank 0 Data object.    rank 0 Data object.
1748    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1749  */  */
# Line 1500  inline Line 1752  inline
1752  Data  Data
1753  Data::dp_algorithm(BinaryFunction operation, double initial_value) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1754  {  {
1755    if (isExpanded()) {    if (isEmpty()) {
1756      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1757      }
1758      else if (isExpanded()) {
1759        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1760      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1761      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1762      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1763      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1764      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1765      return result;      return result;
1766    } else if (isTagged()) {    }
1767      else if (isTagged()) {
1768      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());  
1769      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1770      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      DataTypes::ValueType defval(1);
1771        defval[0]=0;
1772        DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1773      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1774      return result;      return Data(resultT);   // note: the Data object now owns the resultT pointer
1775    } else if (isConstant()) {    }
1776      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());    else if (isConstant()) {
1777        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1778      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1779      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1780      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
# Line 1540  Data::dp_algorithm(BinaryFunction operat Line 1786  Data::dp_algorithm(BinaryFunction operat
1786    return falseRetVal;    return falseRetVal;
1787  }  }
1788    
1789    /**
1790      \brief
1791      Compute a tensor operation with two Data objects
1792      \param arg0 - Input - Data object
1793      \param arg1 - Input - Data object
1794      \param operation - Input - Binary op functor
1795    */
1796    template <typename BinaryFunction>
1797    inline
1798    Data
1799    C_TensorBinaryOperation(Data const &arg_0,
1800                            Data const &arg_1,
1801                            BinaryFunction operation)
1802    {
1803      if (arg_0.isEmpty() || arg_1.isEmpty())
1804      {
1805         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1806      }
1807      // Interpolate if necessary and find an appropriate function space
1808      Data arg_0_Z, arg_1_Z;
1809      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1810        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1811          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1812          arg_1_Z = Data(arg_1);
1813        }
1814        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1815          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1816          arg_0_Z =Data(arg_0);
1817        }
1818        else {
1819          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1820        }
1821      } else {
1822          arg_0_Z = Data(arg_0);
1823          arg_1_Z = Data(arg_1);
1824      }
1825      // Get rank and shape of inputs
1826      int rank0 = arg_0_Z.getDataPointRank();
1827      int rank1 = arg_1_Z.getDataPointRank();
1828      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1829      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1830      int size0 = arg_0_Z.getDataPointSize();
1831      int size1 = arg_1_Z.getDataPointSize();
1832    
1833      // Declare output Data object
1834      Data res;
1835    
1836      if (shape0 == shape1) {
1837    
1838        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1839          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1840    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1841          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1842          double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1843          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1844          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1845          double *ptr_2 = &(res.getDataAtOffset(0));
1846    
1847          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1848        }
1849        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1850    
1851          // Prepare the DataConstant input
1852          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1853    
1854          // Borrow DataTagged input from Data object
1855          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1856    
1857          // Prepare a DataTagged output 2
1858          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1859          res.tag();
1860          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1861    
1862          // Prepare offset into DataConstant
1863          int offset_0 = tmp_0->getPointOffset(0,0);
1864          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1865          // Get the views
1866    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1867    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1868    //       // Get the pointers to the actual data
1869    //       double *ptr_1 = &((view_1.getData())[0]);
1870    //       double *ptr_2 = &((view_2.getData())[0]);
1871    
1872          // Get the pointers to the actual data
1873          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1874          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1875    
1876          // Compute a result for the default
1877          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1878          // Compute a result for each tag
1879          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1880          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1881          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1882            tmp_2->addTag(i->first);
1883    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1884            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1885            double *ptr_1 = &view_1.getData(0);
1886            double *ptr_2 = &view_2.getData(0);*/
1887            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1888            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1889    
1890            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1891          }
1892    
1893        }
1894        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1895    
1896          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1897          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1898          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1899          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1900    
1901          int sampleNo_1,dataPointNo_1;
1902          int numSamples_1 = arg_1_Z.getNumSamples();
1903          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1904          int offset_0 = tmp_0->getPointOffset(0,0);
1905          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1906          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1907            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1908              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1909              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1910    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1911    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1912    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1913    
1914              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1915              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1916              double *ptr_2 = &(res.getDataAtOffset(offset_2));
1917              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1918            }
1919          }
1920    
1921        }
1922        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1923    
1924          // Borrow DataTagged input from Data object
1925          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1926    
1927          // Prepare the DataConstant input
1928          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1929    
1930          // Prepare a DataTagged output 2
1931          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1932          res.tag();
1933          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1934    
1935          // Prepare offset into DataConstant
1936          int offset_1 = tmp_1->getPointOffset(0,0);
1937    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1938          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1939          // Get the views
1940    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1941    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1942    //       // Get the pointers to the actual data
1943    //       double *ptr_0 = &((view_0.getData())[0]);
1944    //       double *ptr_2 = &((view_2.getData())[0]);
1945          // Get the pointers to the actual data
1946          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1947          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1948          // Compute a result for the default
1949          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1950          // Compute a result for each tag
1951          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1952          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1953          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1954            tmp_2->addTag(i->first);
1955    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1956    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1957    //         double *ptr_0 = &view_0.getData(0);
1958    //         double *ptr_2 = &view_2.getData(0);
1959            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1960            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1961            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1962          }
1963    
1964        }
1965        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1966    
1967          // Borrow DataTagged input from Data object
1968          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1969    
1970          // Borrow DataTagged input from Data object
1971          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1972    
1973          // Prepare a DataTagged output 2
1974          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1975          res.tag();        // DataTagged output
1976          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1977    
1978    //       // Get the views
1979    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1980    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1981    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1982    //       // Get the pointers to the actual data
1983    //       double *ptr_0 = &((view_0.getData())[0]);
1984    //       double *ptr_1 = &((view_1.getData())[0]);
1985    //       double *ptr_2 = &((view_2.getData())[0]);
1986    
1987          // Get the pointers to the actual data
1988          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1989          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1990          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1991    
1992          // Compute a result for the default
1993          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1994          // Merge the tags
1995          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1996          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1997          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1998          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1999            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2000          }
2001          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2002            tmp_2->addTag(i->first);
2003          }
2004          // Compute a result for each tag
2005          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2006          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2007    
2008    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2009    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2010    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2011    //         double *ptr_0 = &view_0.getData(0);
2012    //         double *ptr_1 = &view_1.getData(0);
2013    //         double *ptr_2 = &view_2.getData(0);
2014    
2015            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2016            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2017            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2018    
2019            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2020          }
2021    
2022        }
2023        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2024    
2025          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2026          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2027          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2028          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2029          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2030    
2031          int sampleNo_0,dataPointNo_0;
2032          int numSamples_0 = arg_0_Z.getNumSamples();
2033          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2034          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2035          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2036            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2037            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2038            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2039              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2040              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2041    
2042    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2043    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2044              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2045              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2046    
2047    
2048              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2049            }
2050          }
2051    
2052        }
2053        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2054    
2055          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2056          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2057          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2058          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2059    
2060          int sampleNo_0,dataPointNo_0;
2061          int numSamples_0 = arg_0_Z.getNumSamples();
2062          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2063          int offset_1 = tmp_1->getPointOffset(0,0);
2064          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2065          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2066            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2067              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2068              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2069    
2070    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2071    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2072    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2073    
2074              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2075              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2076              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2077    
2078    
2079              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2080            }
2081          }
2082    
2083        }
2084        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2085    
2086          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2087          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2088          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2089          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2090          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2091    
2092          int sampleNo_0,dataPointNo_0;
2093          int numSamples_0 = arg_0_Z.getNumSamples();
2094          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2095          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2096          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2097            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2098            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2099            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2100              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2101              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2102              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2103              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2104              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2105            }
2106          }
2107    
2108        }
2109        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2110    
2111          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2112          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2113          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2114          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2115          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2116    
2117          int sampleNo_0,dataPointNo_0;
2118          int numSamples_0 = arg_0_Z.getNumSamples();
2119          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2120          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2121          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2122            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2123              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2124              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2125              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2126              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2127              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2128              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2129              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2130            }
2131          }
2132    
2133        }
2134        else {
2135          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2136        }
2137    
2138      } else if (0 == rank0) {
2139    
2140        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2141          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2142          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2143          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2144          double *ptr_2 = &(res.getDataAtOffset(0));
2145          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2146        }
2147        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2148    
2149          // Prepare the DataConstant input
2150          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2151    
2152          // Borrow DataTagged input from Data object
2153          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2154    
2155          // Prepare a DataTagged output 2
2156          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2157          res.tag();
2158          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2159    
2160          // Prepare offset into DataConstant
2161          int offset_0 = tmp_0->getPointOffset(0,0);
2162          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2163          // Get the views
2164    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2165    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2166    //       // Get the pointers to the actual data
2167    //       double *ptr_1 = &((view_1.getData())[0]);
2168    //       double *ptr_2 = &((view_2.getData())[0]);
2169           double *ptr_1 = &(tmp_1->getDefaultValue(0));
2170           double *ptr_2 = &(tmp_2->getDefaultValue(0));
2171    
2172          // Compute a result for the default
2173          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2174          // Compute a result for each tag
2175          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2176          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2177          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2178            tmp_2->addTag(i->first);
2179    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2180    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2181    //         double *ptr_1 = &view_1.getData(0);
2182    //         double *ptr_2 = &view_2.getData(0);
2183            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2184            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2185            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2186          }
2187    
2188        }
2189        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2190    
2191          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2192          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2193          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2194          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2195    
2196          int sampleNo_1,dataPointNo_1;
2197          int numSamples_1 = arg_1_Z.getNumSamples();
2198          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2199          int offset_0 = tmp_0->getPointOffset(0,0);
2200          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2201          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2202            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2203              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2204              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2205              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2206              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2207              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2208              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2209    
2210            }
2211          }
2212    
2213        }
2214        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2215    
2216          // Borrow DataTagged input from Data object
2217          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2218    
2219          // Prepare the DataConstant input
2220          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2221    
2222          // Prepare a DataTagged output 2
2223          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2224          res.tag();
2225          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2226    
2227          // Prepare offset into DataConstant
2228          int offset_1 = tmp_1->getPointOffset(0,0);
2229    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2230          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2231          // Get the views
2232    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2233          DataArrayView view_2 = tmp_2->getDefaultValue();
2234          // Get the pointers to the actual data
2235          double *ptr_0 = &((view_0.getData())[0]);
2236          double *ptr_2 = &((view_2.getData())[0]);*/
2237    
2238          // Get the pointers to the actual data
2239          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2240          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2241    
2242    
2243          // Compute a result for the default
2244          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2245          // Compute a result for each tag
2246          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2247          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2248          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2249            tmp_2->addTag(i->first);
2250    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2251            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2252            double *ptr_0 = &view_0.getData(0);
2253            double *ptr_2 = &view_2.getData(0);*/
2254            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2255            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2256    
2257            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2258          }
2259    
2260        }
2261        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2262    
2263          // Borrow DataTagged input from Data object
2264          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2265    
2266          // Borrow DataTagged input from Data object
2267          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2268    
2269          // Prepare a DataTagged output 2
2270          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2271          res.tag();        // DataTagged output
2272          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2273    
2274          // Get the views
2275    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2276          DataArrayView view_1 = tmp_1->getDefaultValue();
2277          DataArrayView view_2 = tmp_2->getDefaultValue();
2278          // Get the pointers to the actual data
2279          double *ptr_0 = &((view_0.getData())[0]);
2280          double *ptr_1 = &((view_1.getData())[0]);
2281          double *ptr_2 = &((view_2.getData())[0]);*/
2282    
2283          // Get the pointers to the actual data
2284          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2285          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2286          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2287    
2288    
2289          // Compute a result for the default
2290          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2291          // Merge the tags
2292          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2293          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2294          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2295          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2296            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2297          }
2298          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2299            tmp_2->addTag(i->first);
2300          }
2301          // Compute a result for each tag
2302          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2303          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2304    
2305    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2306            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2307            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2308            double *ptr_0 = &view_0.getData(0);
2309            double *ptr_1 = &view_1.getData(0);
2310            double *ptr_2 = &view_2.getData(0);*/
2311    
2312            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2313            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2314            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2315    
2316            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2317          }
2318    
2319        }
2320        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2321    
2322          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2323          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2324          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2325          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2326          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2327    
2328          int sampleNo_0,dataPointNo_0;
2329          int numSamples_0 = arg_0_Z.getNumSamples();
2330          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2331          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2332          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2333            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2334            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2335            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2336              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2337              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2338              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2339              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2340              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2341            }
2342          }
2343    
2344        }
2345        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2346    
2347          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2348          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2349          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2350          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2351    
2352          int sampleNo_0,dataPointNo_0;
2353          int numSamples_0 = arg_0_Z.getNumSamples();
2354          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2355          int offset_1 = tmp_1->getPointOffset(0,0);
2356          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2357          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2358            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2359              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2360              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2361              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2362              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2363              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2364              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2365            }
2366          }
2367    
2368    
2369        }
2370        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2371    
2372          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2373          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2374          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2375          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2376          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2377    
2378          int sampleNo_0,dataPointNo_0;
2379          int numSamples_0 = arg_0_Z.getNumSamples();
2380          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2381          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2382          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2383            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2384            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2385            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2386              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2387              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2388              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2389              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2390              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2391            }
2392          }
2393    
2394        }
2395        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2396    
2397          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2398          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2399          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2400          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2401          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2402    
2403          int sampleNo_0,dataPointNo_0;
2404          int numSamples_0 = arg_0_Z.getNumSamples();
2405          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2406          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2407          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2408            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2409              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2410              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2411              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2412              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2413              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2414              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2415              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2416            }
2417          }
2418    
2419        }
2420        else {
2421          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2422        }
2423    
2424      } else if (0 == rank1) {
2425    
2426        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2427          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2428          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2429          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2430          double *ptr_2 = &(res.getDataAtOffset(0));
2431          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2432        }
2433        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2434    
2435          // Prepare the DataConstant input
2436          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2437    
2438          // Borrow DataTagged input from Data object
2439          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2440    
2441          // Prepare a DataTagged output 2
2442          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2443          res.tag();
2444          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2445    
2446          // Prepare offset into DataConstant
2447          int offset_0 = tmp_0->getPointOffset(0,0);
2448          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2449          // Get the views
2450    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2451          DataArrayView view_2 = tmp_2->getDefaultValue();
2452          // Get the pointers to the actual data
2453          double *ptr_1 = &((view_1.getData())[0]);
2454          double *ptr_2 = &((view_2.getData())[0]);*/
2455          //Get the pointers to the actual data
2456          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2457          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2458    
2459          // Compute a result for the default
2460          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2461          // Compute a result for each tag
2462          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2463          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2464          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2465            tmp_2->addTag(i->first);
2466    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2467    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2468    //         double *ptr_1 = &view_1.getData(0);
2469    //         double *ptr_2 = &view_2.getData(0);
2470            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2471            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2472    
2473    
2474            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2475          }
2476    
2477        }
2478        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2479    
2480          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2481          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2482          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2483          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2484    
2485          int sampleNo_1,dataPointNo_1;
2486          int numSamples_1 = arg_1_Z.getNumSamples();
2487          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2488          int offset_0 = tmp_0->getPointOffset(0,0);
2489          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2490          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2491            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2492              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2493              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2494              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2495              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2496              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2497              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2498            }
2499          }
2500    
2501        }
2502        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2503    
2504          // Borrow DataTagged input from Data object
2505          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2506    
2507          // Prepare the DataConstant input
2508          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2509    
2510          // Prepare a DataTagged output 2
2511          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2512          res.tag();
2513          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2514    
2515          // Prepare offset into DataConstant
2516          int offset_1 = tmp_1->getPointOffset(0,0);
2517          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2518          // Get the views
2519    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2520    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2521    //       // Get the pointers to the actual data
2522    //       double *ptr_0 = &((view_0.getData())[0]);
2523    //       double *ptr_2 = &((view_2.getData())[0]);
2524          // Get the pointers to the actual data
2525          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2526          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2527          // Compute a result for the default
2528          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2529          // Compute a result for each tag
2530          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2531          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2532          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2533            tmp_2->addTag(i->first);
2534    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2535            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2536            double *ptr_0 = &view_0.getData(0);
2537            double *ptr_2 = &view_2.getData(0);*/
2538            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2539            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2540            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2541          }
2542    
2543        }
2544        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2545    
2546          // Borrow DataTagged input from Data object
2547          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2548    
2549          // Borrow DataTagged input from Data object
2550          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2551    
2552          // Prepare a DataTagged output 2
2553          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2554          res.tag();        // DataTagged output
2555          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2556    
2557          // Get the views
2558    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2559    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2560    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2561    //       // Get the pointers to the actual data
2562    //       double *ptr_0 = &((view_0.getData())[0]);
2563    //       double *ptr_1 = &((view_1.getData())[0]);
2564    //       double *ptr_2 = &((view_2.getData())[0]);
2565    
2566          // Get the pointers to the actual data
2567          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2568          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2569          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2570    
2571          // Compute a result for the default
2572          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2573          // Merge the tags
2574          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2575          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2576          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2577          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2578            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2579          }
2580          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2581            tmp_2->addTag(i->first);
2582          }
2583          // Compute a result for each tag
2584          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2585          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2586    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2587    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2588    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2589    //         double *ptr_0 = &view_0.getData(0);
2590    //         double *ptr_1 = &view_1.getData(0);
2591    //         double *ptr_2 = &view_2.getData(0);
2592    
2593            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2594            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2595            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2596            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2597          }
2598    
2599        }
2600        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2601    
2602          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2603          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2604          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2605          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2606          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2607    
2608          int sampleNo_0,dataPointNo_0;
2609          int numSamples_0 = arg_0_Z.getNumSamples();
2610          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2611          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2612          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2613            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2614            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2615            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2616              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2617              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2618              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2619              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2620              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2621            }
2622          }
2623    
2624        }
2625        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2626    
2627          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2628          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2629          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2630          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2631    
2632          int sampleNo_0,dataPointNo_0;
2633          int numSamples_0 = arg_0_Z.getNumSamples();
2634          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2635          int offset_1 = tmp_1->getPointOffset(0,0);
2636          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2637          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2638            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2639              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2640              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2641              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2642              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2643              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2644              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2645            }
2646          }
2647    
2648    
2649        }
2650        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2651    
2652          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2653          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2654          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2655          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2656          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2657    
2658          int sampleNo_0,dataPointNo_0;
2659          int numSamples_0 = arg_0_Z.getNumSamples();
2660          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2661          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2662          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2663            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2664            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2665            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2666              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2667              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2668              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2669              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2670              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2671            }
2672          }
2673    
2674        }
2675        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2676    
2677          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2678          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2679          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2680          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2681          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2682    
2683          int sampleNo_0,dataPointNo_0;
2684          int numSamples_0 = arg_0_Z.getNumSamples();
2685          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2686          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2687          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2688            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2689              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2690              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2691              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2692              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2693              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2694              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2695              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2696            }
2697          }
2698    
2699        }
2700        else {
2701          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2702        }
2703    
2704      } else {
2705        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2706      }
2707    
2708      return res;
2709    }
2710    
2711    template <typename UnaryFunction>
2712    Data
2713    C_TensorUnaryOperation(Data const &arg_0,
2714                           UnaryFunction operation)
2715    {
2716      if (arg_0.isEmpty())  // do this before we attempt to interpolate
2717      {
2718         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2719      }
2720    
2721      // Interpolate if necessary and find an appropriate function space
2722      Data arg_0_Z = Data(arg_0);
2723    
2724      // Get rank and shape of inputs
2725      int rank0 = arg_0_Z.getDataPointRank();
2726      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2727      int size0 = arg_0_Z.getDataPointSize();
2728    
2729      // Declare output Data object
2730      Data res;
2731    
2732      if (arg_0_Z.isConstant()) {
2733        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2734    //     double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2735    //     double *ptr_2 = &((res.getPointDataView().getData())[0]);
2736        double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2737        double *ptr_2 = &(res.getDataAtOffset(0));
2738        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2739      }
2740      else if (arg_0_Z.isTagged()) {
2741    
2742        // Borrow DataTagged input from Data object
2743        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2744    
2745        // Prepare a DataTagged output 2
2746        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2747        res.tag();
2748        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2749    
2750    //     // Get the views
2751    //     DataArrayView view_0 = tmp_0->getDefaultValue();
2752    //     DataArrayView view_2 = tmp_2->getDefaultValue();
2753    //     // Get the pointers to the actual data
2754    //     double *ptr_0 = &((view_0.getData())[0]);
2755    //     double *ptr_2 = &((view_2.getData())[0]);
2756        // Get the pointers to the actual data
2757        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2758        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2759        // Compute a result for the default
2760        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2761        // Compute a result for each tag
2762        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2763        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2764        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2765          tmp_2->addTag(i->first);
2766    //       DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2767    //       DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2768    //       double *ptr_0 = &view_0.getData(0);
2769    //       double *ptr_2 = &view_2.getData(0);
2770          double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2771          double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2772          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2773        }
2774    
2775      }
2776      else if (arg_0_Z.isExpanded()) {
2777    
2778        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2779        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2780        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2781    
2782        int sampleNo_0,dataPointNo_0;
2783        int numSamples_0 = arg_0_Z.getNumSamples();
2784        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2785        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2786        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2787          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2788    //         int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2789    //         int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2790    //         double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2791    //         double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2792            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2793            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2794            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2795            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2796            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2797          }
2798        }
2799      }
2800      else {
2801        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2802      }
2803    
2804      return res;
2805    }
2806    
2807  }  }
2808  #endif  #endif

Legend:
Removed from v.698  
changed lines
  Added in v.1864

  ViewVC Help
Powered by ViewVC 1.1.26