/[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/esys2/escript/src/Data/Data.h revision 117 by jgs, Fri Apr 1 05:48:57 2005 UTC branches/more_shared_ptrs_from_1812/escript/src/Data.h revision 1821 by jfenwick, Wed Oct 1 04:46:59 2008 UTC
# Line 1  Line 1 
 // $Id$  
 /*=============================================================================  
1    
2   ******************************************************************************  /*******************************************************
3   *                                                                            *  *
4   *       COPYRIGHT ACcESS 2004 -  All Rights Reserved                         *  * Copyright (c) 2003-2008 by University of Queensland
5   *                                                                            *  * Earth Systems Science Computational Center (ESSCC)
6   * This software is the property of ACcESS.  No part of this code             *  * http://www.uq.edu.au/esscc
7   * may be copied in any form or by any means without the expressed written    *  *
8   * consent of ACcESS.  Copying, use or modification of this software          *  * Primary Business: Queensland, Australia
9   * by any unauthorised person is illegal unless that                          *  * Licensed under the Open Software License version 3.0
10   * person has a software license agreement with ACcESS.                       *  * http://www.opensource.org/licenses/osl-3.0.php
11   *                                                                            *  *
12   ******************************************************************************  *******************************************************/
13    
14  ******************************************************************************/  
15    /** \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 "escript/Data/DataAbstract.h"  #include "DataAbstract.h"
22  #include "escript/Data/DataTagged.h"  #include "DataAlgorithm.h"
23  #include "escript/Data/FunctionSpace.h"  #include "FunctionSpace.h"
24  #include "escript/Data/BinaryOp.h"  #include "BinaryOp.h"
25  #include "escript/Data/UnaryOp.h"  #include "UnaryOp.h"
26  #include "escript/Data/DataException.h"  #include "DataException.h"
27    #include "DataTypes.h"
28    
29  extern "C" {  extern "C" {
30  #include "escript/Data/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 <iostream>  #include "esysmpi.h"
35  #include <string>  #include <string>
 #include <memory>  
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>
 #include <boost/python/list.hpp>  
42  #include <boost/python/tuple.hpp>  #include <boost/python/tuple.hpp>
43  #include <boost/python/numeric.hpp>  #include <boost/python/numeric.hpp>
44    
 /**  
    \brief  
    Data is essentially a factory class which creates the appropriate Data  
    object for the given construction arguments. It retains control over  
    the object created for the lifetime of the object.  
    The type of Data object referred to may change during the lifetime of  
    the Data object.  
   
    Description:  
    Data is essentially a factory class which creates the appropriate Data  
    object for the given construction arguments. It retains control over  
    the object created for the lifetime of the object.  
    The type of Data object referred to may change during the lifetime of  
    the Data object.  
 */  
   
45  namespace escript {  namespace escript {
46    
47  //  //
48  // Forward declaration for various implimentations of Data.  // Forward declaration for various implementations of Data.
 class DataEmpty;  
49  class DataConstant;  class DataConstant;
50  class DataTagged;  class DataTagged;
51  class DataExpanded;  class DataExpanded;
52    
53    /**
54       \brief
55       Data represents a collection of datapoints.
56    
57       Description:
58       Internally, the datapoints are actually stored by a DataAbstract object.
59       The specific instance of DataAbstract used may vary over the lifetime
60       of the Data object.
61       Some methods on this class return references (eg getShape()).
62       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    
68    public:    public:
# Line 74  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 83  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 90  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 98  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 126  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 138  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 170  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 185  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 198  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 205  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       Perform a deep copy.       Destructor
211      */
212      ESCRIPT_DLL_API
213      ~Data();
214    
215      /**
216         \brief Make this object a deep copy of "other".
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    
232      /**
233       Member access methods.       Member access methods.
234    */    */
235    
236    /**    /**
237       \brief       \brief
238       Return the values of all data-points in a single python numarray object.       switches on update protection
239    
240    */    */
241    boost::python::numeric::array    ESCRIPT_DLL_API
242    convertToNumArray();    void
243      setProtection();
244    
245      /**
246         \brief
247         Returns trueif the data object is protected against update
248    
249      */
250      ESCRIPT_DLL_API
251      bool
252      isProtected() const;
253    
254      /**
255         \brief
256         Return the values of a data point on this process
257      */
258      ESCRIPT_DLL_API
259      const boost::python::numeric::array
260      getValueOfDataPoint(int dataPointNo);
261    
262      /**
263         \brief
264         sets the values of a data-point from a python object on this process
265      */
266      ESCRIPT_DLL_API
267      void
268      setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
269    
270      /**
271         \brief
272         sets the values of a data-point from a numarray object on this process
273      */
274      ESCRIPT_DLL_API
275      void
276      setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
277    
278      /**
279         \brief
280         sets the values of a data-point on this process
281      */
282      ESCRIPT_DLL_API
283      void
284      setValueOfDataPoint(int dataPointNo, const double);
285    
286      /**
287         \brief
288         Return the value of the specified data-point across all processors
289      */
290      ESCRIPT_DLL_API
291      const boost::python::numeric::array
292      getValueOfGlobalDataPoint(int procNo, int dataPointNo);
293    
294      /**
295         \brief
296         Return the tag number associated with the given data-point.
297    
298      */
299      ESCRIPT_DLL_API
300      int
301      getTagNumber(int dpno);
302    
303    /**    /**
304       \brief       \brief
305       Return the C wrapper for the Data object.       Return the C wrapper for the Data object.
306    */    */
307      ESCRIPT_DLL_API
308    escriptDataC    escriptDataC
309    getDataC();    getDataC();
310    
311    
312    
313    
314    
315    
316    // REMOVE ME
317    // ESCRIPT_DLL_API
318    // void
319    // CompareDebug(const Data& rd);
320    
321    
322    /**    /**
323       \brief       \brief
324       Return the C wrapper for the Data object - const version.       Return the C wrapper for the Data object - const version.
325    */    */
326      ESCRIPT_DLL_API
327    escriptDataC    escriptDataC
328    getDataC() const;    getDataC() const;
329    
330    /**    /**
331       \brief       \brief
332       Write the data as a string.       Write the data as a string. For large amounts of data, a summary is printed.
333    */    */
334    inline    ESCRIPT_DLL_API
335    std::string    std::string
336    toString() const    toString() const;
   {  
     return m_data->toString();  
   }  
337    
338    /**  
339       \brief  //  /**
340    /*     \brief
341       Return the DataArrayView of the point data. This essentially contains       Return the DataArrayView of the point data. This essentially contains
342       the shape information for each data point although it also may be used       the shape information for each data point although it also may be used
343       to manipulate the point data.       to manipulate the point data.*/
344    */  //  */
345    inline  //   ESCRIPT_DLL_API
346    const DataArrayView&  //   inline
347    getPointDataView() const  //   const DataArrayView&
348    {  //   getPointDataView() const
349       return m_data->getPointDataView();  //   {
350    }  //      return m_data->getPointDataView();
351    //   }
352    
353    /**    /**
354       \brief       \brief
355       Whatever the current Data type make this into a DataExpanded.       Whatever the current Data type make this into a DataExpanded.
356    */    */
357      ESCRIPT_DLL_API
358    void    void
359    expand();    expand();
360    
# Line 278  class Data { Line 363  class Data {
363       If possible convert this Data to DataTagged. This will only allow       If possible convert this Data to DataTagged. This will only allow
364       Constant data to be converted to tagged. An attempt to convert       Constant data to be converted to tagged. An attempt to convert
365       Expanded data to tagged will throw an exception.       Expanded data to tagged will throw an exception.
366        ==>*
367    */    */
368      ESCRIPT_DLL_API
369    void    void
370    tag();    tag();
371    
# Line 286  class Data { Line 373  class Data {
373       \brief       \brief
374       Return true if this Data is expanded.       Return true if this Data is expanded.
375    */    */
376      ESCRIPT_DLL_API
377    bool    bool
378    isExpanded() const;    isExpanded() const;
379    
# Line 293  class Data { Line 381  class Data {
381       \brief       \brief
382       Return true if this Data is tagged.       Return true if this Data is tagged.
383    */    */
384      ESCRIPT_DLL_API
385    bool    bool
386    isTagged() const;    isTagged() const;
387    
# Line 300  class Data { Line 389  class Data {
389       \brief       \brief
390       Return true if this Data is constant.       Return true if this Data is constant.
391    */    */
392      ESCRIPT_DLL_API
393    bool    bool
394    isConstant() const;    isConstant() const;
395    
396    /**    /**
397       \brief       \brief
398       Return true if this Data is empty.       Return true if this Data holds an instance of DataEmpty. This is _not_ the same as asking if the object
399    contains datapoints.
400    */    */
401      ESCRIPT_DLL_API
402    bool    bool
403    isEmpty() const;    isEmpty() const;
404    
# Line 314  class Data { Line 406  class Data {
406       \brief       \brief
407       Return the function space.       Return the function space.
408    */    */
409      ESCRIPT_DLL_API
410    inline    inline
411    const FunctionSpace&    const FunctionSpace&
412    getFunctionSpace() const    getFunctionSpace() const
# Line 325  class Data { Line 418  class Data {
418       \brief       \brief
419       Return a copy of the function space.       Return a copy of the function space.
420    */    */
421      ESCRIPT_DLL_API
422    const FunctionSpace    const FunctionSpace
423    getCopyOfFunctionSpace() const;    getCopyOfFunctionSpace() const;
424    
# Line 332  class Data { Line 426  class Data {
426       \brief       \brief
427       Return the domain.       Return the domain.
428    */    */
429      ESCRIPT_DLL_API
430    inline    inline
431    const AbstractDomain&  //   const AbstractDomain&
432      const_Domain_ptr
433    getDomain() const    getDomain() const
434    {    {
435       return getFunctionSpace().getDomain();       return getFunctionSpace().getDomain();
# Line 343  class Data { Line 439  class Data {
439       \brief       \brief
440       Return a copy of the domain.       Return a copy of the domain.
441    */    */
442      ESCRIPT_DLL_API
443    const AbstractDomain    const AbstractDomain
444    getCopyOfDomain() const;    getCopyOfDomain() const;
445    
# Line 350  class Data { Line 447  class Data {
447       \brief       \brief
448       Return the rank of the point data.       Return the rank of the point data.
449    */    */
450      ESCRIPT_DLL_API
451    inline    inline
452    int    int
453    getDataPointRank() const    getDataPointRank() const
454    {    {
455      return m_data->getPointDataView().getRank();  //    return m_data->getPointDataView().getRank();
456        return m_data->getRank();
457    }    }
458    
459    /**    /**
460       \brief       \brief
461         Return the number of data points
462      */
463      ESCRIPT_DLL_API
464      inline
465      int
466      getNumDataPoints() const
467      {
468        return getNumSamples() * getNumDataPointsPerSample();
469      }
470      /**
471         \brief
472       Return the number of samples.       Return the number of samples.
473    */    */
474      ESCRIPT_DLL_API
475    inline    inline
476    int    int
477    getNumSamples() const    getNumSamples() const
# Line 372  class Data { Line 483  class Data {
483       \brief       \brief
484       Return the number of data points per sample.       Return the number of data points per sample.
485    */    */
486      ESCRIPT_DLL_API
487    inline    inline
488    int    int
489    getNumDataPointsPerSample() const    getNumDataPointsPerSample() const
# Line 379  class Data { Line 491  class Data {
491      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
492    }    }
493    
494    
495      /**
496        \brief
497        Return the number of values in the shape for this object.
498      */
499      ESCRIPT_DLL_API
500      int
501      getNoValues() const
502      {
503        return m_data->getNoValues();
504      }
505    
506    
507      /**
508         \brief
509         dumps the object into a netCDF file
510      */
511      ESCRIPT_DLL_API
512      void
513      dump(const std::string fileName) const;
514    /**    /**
515       \brief       \brief
516       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
517       preferred interface but is provided for use by C code.       preferred interface but is provided for use by C code.
518       \param sampleNo - Input - the given sample no.       \param sampleNo - Input - the given sample no.
519    */    */
520      ESCRIPT_DLL_API
521    inline    inline
522    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
523    getSampleData(DataAbstract::ValueType::size_type sampleNo)    getSampleData(DataAbstract::ValueType::size_type sampleNo)
# Line 398  class Data { Line 531  class Data {
531       access data that isn't tagged an exception will be thrown.       access data that isn't tagged an exception will be thrown.
532       \param tag - Input - the tag key.       \param tag - Input - the tag key.
533    */    */
534      ESCRIPT_DLL_API
535    inline    inline
536    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
537    getSampleDataByTag(int tag)    getSampleDataByTag(int tag)
# Line 405  class Data { Line 539  class Data {
539      return m_data->getSampleDataByTag(tag);      return m_data->getSampleDataByTag(tag);
540    }    }
541    
542    /**  //  /**
543       \brief  /*     \brief
544       Assign the given value to the data-points referenced by the given       Return a view into the data for the data point specified.
545       reference number.       NOTE: Construction of the DataArrayView is a relatively expensive
546         operation.
547       The value supplied is a python numarray object.  The data from this numarray       \param sampleNo - Input -
548       is unpacked into a DataArray, and this is used to set the corresponding       \param dataPointNo - Input -*/
549       data-points in the underlying Data object.  //  */
550    //   ESCRIPT_DLL_API
551       If the underlying Data object cannot be accessed via reference numbers, an  //   inline
552       exception will be thrown.  //   DataArrayView
553    //   getDataPoint(int sampleNo,
554       \param ref - Input - reference number.  //                int dataPointNo)
555       \param value - Input - value to assign to data-points associated with  //   {
556                              the given reference number.  //                 return m_data->getDataPoint(sampleNo,dataPointNo);
557    */  //   }
   void  
   setRefValue(int ref,  
               const boost::python::numeric::array& value);  
   
   /**  
      \brief  
      Return the values associated with the data-points referenced by the given  
      reference number.  
   
      The value supplied is a python numarray object. The data from the corresponding  
      data-points in this Data object are packed into the given numarray object.  
   
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
558    
      \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);  
559    
560    /**    /**
561       \brief       \brief
# Line 452  class Data { Line 565  class Data {
565       \param sampleNo - Input -       \param sampleNo - Input -
566       \param dataPointNo - Input -       \param dataPointNo - Input -
567    */    */
568      ESCRIPT_DLL_API
569      DataTypes::ValueType::const_reference
570      getDataPoint(int sampleNo, int dataPointNo) const;
571    
572    
573      ESCRIPT_DLL_API
574      DataTypes::ValueType::reference
575      getDataPoint(int sampleNo, int dataPointNo);
576    
577    
578    
579      /**
580         \brief
581         Return the offset for the given sample and point within the sample
582      */
583      ESCRIPT_DLL_API
584    inline    inline
585    DataArrayView    DataTypes::ValueType::size_type
586    getDataPoint(int sampleNo,    getDataOffset(int sampleNo,
587                 int dataPointNo)                 int dataPointNo)
588    {    {
589      return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getPointOffset(sampleNo,dataPointNo);
590    }    }
591    
592    /**    /**
593       \brief       \brief
594       Return a reference to the data point shape.       Return a reference to the data point shape.
595    */    */
596    const DataArrayView::ShapeType&    ESCRIPT_DLL_API
597    getDataPointShape() const;    inline
598      const DataTypes::ShapeType&
599      getDataPointShape() const
600      {
601        return m_data->getShape();
602      }
603    
604    /**    /**
605       \brief       \brief
606       Return the data point shape as a tuple of integers.       Return the data point shape as a tuple of integers.
607    */    */
608    boost::python::tuple    ESCRIPT_DLL_API
609      const boost::python::tuple
610    getShapeTuple() const;    getShapeTuple() const;
611    
612    /**    /**
# Line 479  class Data { Line 614  class Data {
614       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
615       data point shape dimensions.       data point shape dimensions.
616    */    */
617      ESCRIPT_DLL_API
618    int    int
619    getDataPointSize() const;    getDataPointSize() const;
620    
# Line 486  class Data { Line 622  class Data {
622       \brief       \brief
623       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
624    */    */
625    DataArrayView::ValueType::size_type    ESCRIPT_DLL_API
626      DataTypes::ValueType::size_type
627    getLength() const;    getLength() const;
628    
629    
630    
631    /**    /**
632       \brief       \brief
633       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag assocciated with name. Implicitly converts this
634       object to type DataTagged. Throws an exception if this object       object to type DataTagged. Throws an exception if this object
635       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
636       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
637       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
638        ==>*
639    */    */
640      ESCRIPT_DLL_API
641    void    void
642    setTaggedValue(int tagKey,    setTaggedValueByName(std::string name,
643                   const boost::python::object& value);                         const boost::python::object& value);
644    
645    /**    /**
646       \brief       \brief
647       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
648       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
649       cannot be converted to a DataTagged object.  
650       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
651       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
652       Note: removed for now - this version not needed, and breaks escript.cpp      ==>*
653    */    */
654    /*    ESCRIPT_DLL_API
655    void    void
656    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
657                   const DataArrayView& value);                   const boost::python::object& value);
658    
659    
660    //  /**
661    //     \brief
662    //     Assign the given value to the tag. Implicitly converts this
663    //     object to type DataTagged if it is constant.
664    //
665    //     \param tagKey - Input - Integer key.
666    //     \param value - Input - Value to associate with given key.
667    //    ==>*
668    //  */
669    //   ESCRIPT_DLL_API
670    //   void
671    //   setTaggedValueFromCPP(int tagKey,
672    //                         const DataArrayView& value);
673    
674      /**
675         \brief
676         Assign the given value to the tag. Implicitly converts this
677         object to type DataTagged if it is constant.
678    
679         \param tagKey - Input - Integer key.
680         \param pointshape - Input - The shape of the value parameter
681         \param value - Input - Value to associate with given key.
682         \param dataOffset - Input - Offset of the begining of the point within the value parameter
683    */    */
684      ESCRIPT_DLL_API
685      void
686      setTaggedValueFromCPP(int tagKey,
687                const DataTypes::ShapeType& pointshape,
688                            const DataTypes::ValueType& value,
689                int dataOffset=0);
690    
691    
692    
693    /**    /**
694      \brief      \brief
695      Copy other Data object into this Data object where mask is positive.      Copy other Data object into this Data object where mask is positive.
696    */    */
697      ESCRIPT_DLL_API
698    void    void
699    copyWithMask(const Data& other,    copyWithMask(const Data& other,
700                 const Data& mask);                 const Data& mask);
# Line 530  class Data { Line 705  class Data {
705    
706    /**    /**
707       \brief       \brief
708         set all values to zero
709         *
710      */
711      ESCRIPT_DLL_API
712      void
713      setToZero();
714    
715      /**
716         \brief
717       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
718       the result as a Data object.       the result as a Data object.
719         *
720    */    */
721      ESCRIPT_DLL_API
722    Data    Data
723    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
724    /**    /**
725       \brief       \brief
726       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
727       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.
728         *
729    */    */
730      ESCRIPT_DLL_API
731    Data    Data
732    gradOn(const FunctionSpace& functionspace) const;    gradOn(const FunctionSpace& functionspace) const;
733    
734      ESCRIPT_DLL_API
735    Data    Data
736    grad() const;    grad() const;
737    
738    /**    /**
739       \brief       \brief
740       Calculate the integral over the function space domain.       Calculate the integral over the function space domain.
741         *
742    */    */
743      ESCRIPT_DLL_API
744    boost::python::numeric::array    boost::python::numeric::array
745    integrate() const;    integrate() const;
746    
747    /**    /**
748       \brief       \brief
749         Returns 1./ Data object
750         *
751      */
752      ESCRIPT_DLL_API
753      Data
754      oneOver() const;
755      /**
756         \brief
757       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.
758         *
759    */    */
760      ESCRIPT_DLL_API
761    Data    Data
762    wherePositive() const;    wherePositive() const;
763    
764    /**    /**
765       \brief       \brief
766       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.
767         *
768    */    */
769      ESCRIPT_DLL_API
770    Data    Data
771    whereNegative() const;    whereNegative() const;
772    
773    /**    /**
774       \brief       \brief
775       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.
776         *
777    */    */
778      ESCRIPT_DLL_API
779    Data    Data
780    whereNonNegative() const;    whereNonNegative() const;
781    
782    /**    /**
783       \brief       \brief
784       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.
785         *
786    */    */
787      ESCRIPT_DLL_API
788    Data    Data
789    whereNonPositive() const;    whereNonPositive() const;
790    
791    /**    /**
792       \brief       \brief
793       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.
794         *
795    */    */
796      ESCRIPT_DLL_API
797    Data    Data
798    whereZero() const;    whereZero(double tol=0.0) const;
799    
800    /**    /**
801       \brief       \brief
802       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.
803         *
804    */    */
805      ESCRIPT_DLL_API
806    Data    Data
807    whereNonZero() const;    whereNonZero(double tol=0.0) const;
808    
809      /**
810         \brief
811         Return the maximum absolute value of this Data object.
812         *
813      */
814      ESCRIPT_DLL_API
815      double
816      Lsup() const;
817    
818      /**
819         \brief
820         Return the maximum value of this Data object.
821         *
822      */
823      ESCRIPT_DLL_API
824      double
825      sup() const;
826    
827      /**
828         \brief
829         Return the minimum value of this Data object.
830         *
831      */
832      ESCRIPT_DLL_API
833      double
834      inf() const;
835    
836      /**
837         \brief
838         Return the absolute value of each data point of this Data object.
839         *
840      */
841      ESCRIPT_DLL_API
842      Data
843      abs() const;
844    
845      /**
846         \brief
847         Return the maximum value of each data point of this Data object.
848         *
849      */
850      ESCRIPT_DLL_API
851      Data
852      maxval() const;
853    
854      /**
855         \brief
856         Return the minimum value of each data point of this Data object.
857         *
858      */
859      ESCRIPT_DLL_API
860      Data
861      minval() const;
862    
863      /**
864         \brief
865         Return the (sample number, data-point number) of the data point with
866         the minimum value in this Data object.
867      */
868      ESCRIPT_DLL_API
869      const boost::python::tuple
870      minGlobalDataPoint() const;
871    
872      ESCRIPT_DLL_API
873      void
874      calc_minGlobalDataPoint(int& ProcNo,  int& DataPointNo) const;
875      /**
876         \brief
877         Return the sign of each data point of this Data object.
878         -1 for negative values, zero for zero values, 1 for positive values.
879         *
880      */
881      ESCRIPT_DLL_API
882      Data
883      sign() const;
884    
885      /**
886         \brief
887         Return the symmetric part of a matrix which is half the matrix plus its transpose.
888         *
889      */
890      ESCRIPT_DLL_API
891      Data
892      symmetric() const;
893    
894      /**
895         \brief
896         Return the nonsymmetric part of a matrix which is half the matrix minus its transpose.
897         *
898      */
899      ESCRIPT_DLL_API
900      Data
901      nonsymmetric() const;
902    
903      /**
904         \brief
905         Return the trace of a matrix
906         *
907      */
908      ESCRIPT_DLL_API
909      Data
910      trace(int axis_offset) const;
911    
912      /**
913         \brief
914         Transpose each data point of this Data object around the given axis.
915         *
916      */
917      ESCRIPT_DLL_API
918      Data
919      transpose(int axis_offset) const;
920    
921      /**
922         \brief
923         Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.
924         Currently this function is restricted to rank 2, square shape, and dimension 3.
925         *
926      */
927      ESCRIPT_DLL_API
928      Data
929      eigenvalues() const;
930    
931      /**
932         \brief
933         Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.
934         the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than
935         tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the
936         first non-zero entry is positive.
937         Currently this function is restricted to rank 2, square shape, and dimension 3
938         *
939      */
940      ESCRIPT_DLL_API
941      const boost::python::tuple
942      eigenvalues_and_eigenvectors(const double tol=1.e-12) const;
943    
944      /**
945         \brief
946         swaps the components axis0 and axis1
947         *
948      */
949      ESCRIPT_DLL_API
950      Data
951      swapaxes(const int axis0, const int axis1) const;
952    
953      /**
954         \brief
955         Return the error function erf of each data point of this Data object.
956         *
957      */
958      ESCRIPT_DLL_API
959      Data
960      erf() const;
961    
962    /**    /**
963       \brief       \brief
964       Return the sin of each data point of this Data object.       Return the sin of each data point of this Data object.
965         *
966    */    */
967      ESCRIPT_DLL_API
968    Data    Data
969    sin() const;    sin() const;
970    
971    /**    /**
972       \brief       \brief
973       Return the cos of each data point of this Data object.       Return the cos of each data point of this Data object.
974         *
975    */    */
976      ESCRIPT_DLL_API
977    Data    Data
978    cos() const;    cos() const;
979    
980    /**    /**
981       \brief       \brief
982       Return the tan of each data point of this Data object.       Return the tan of each data point of this Data object.
983         *
984    */    */
985      ESCRIPT_DLL_API
986    Data    Data
987    tan() const;    tan() const;
988    
989    /**    /**
990       \brief       \brief
991       Return the log to base 10 of each data point of this Data object.       Return the asin of each data point of this Data object.
992         *
993    */    */
994      ESCRIPT_DLL_API
995    Data    Data
996    log() const;    asin() const;
997    
998    /**    /**
999       \brief       \brief
1000       Return the natural log of each data point of this Data object.       Return the acos of each data point of this Data object.
1001         *
1002    */    */
1003      ESCRIPT_DLL_API
1004    Data    Data
1005    ln() const;    acos() const;
1006    
1007    /**    /**
1008       \brief       \brief
1009       Return the maximum absolute value of this Data object.       Return the atan of each data point of this Data object.
1010         *
1011    */    */
1012    double    ESCRIPT_DLL_API
1013    Lsup() const;    Data
1014      atan() const;
1015    
1016    /**    /**
1017       \brief       \brief
1018       Return the minimum absolute value of this Data object.       Return the sinh of each data point of this Data object.
1019         *
1020    */    */
1021    double    ESCRIPT_DLL_API
1022    Linf() const;    Data
1023      sinh() const;
1024    
1025    /**    /**
1026       \brief       \brief
1027       Return the maximum value of this Data object.       Return the cosh of each data point of this Data object.
1028         *
1029    */    */
1030    double    ESCRIPT_DLL_API
1031    sup() const;    Data
1032      cosh() const;
1033    
1034    /**    /**
1035       \brief       \brief
1036       Return the minimum value of this Data object.       Return the tanh of each data point of this Data object.
1037         *
1038    */    */
1039    double    ESCRIPT_DLL_API
1040    inf() const;    Data
1041      tanh() const;
1042    
1043    /**    /**
1044       \brief       \brief
1045       Return the absolute value of each data point of this Data object.       Return the asinh of each data point of this Data object.
1046         *
1047    */    */
1048      ESCRIPT_DLL_API
1049    Data    Data
1050    abs() const;    asinh() const;
1051    
1052    /**    /**
1053       \brief       \brief
1054       Return the maximum value of each data point of this Data object.       Return the acosh of each data point of this Data object.
1055         *
1056    */    */
1057      ESCRIPT_DLL_API
1058    Data    Data
1059    maxval() const;    acosh() const;
1060    
1061    /**    /**
1062       \brief       \brief
1063       Return the minimum value of each data point of this Data object.       Return the atanh of each data point of this Data object.
1064         *
1065    */    */
1066      ESCRIPT_DLL_API
1067    Data    Data
1068    minval() const;    atanh() const;
1069    
1070    /**    /**
1071       \brief       \brief
1072       Return the length of each data point of this Data object.       Return the log to base 10 of each data point of this Data object.
1073       sqrt(sum(A[i,j,k,l]^2))       *
1074    */    */
1075      ESCRIPT_DLL_API
1076    Data    Data
1077    length() const;    log10() const;
1078    
1079    /**    /**
1080       \brief       \brief
1081       Return the sign of each data point of this Data object.       Return the natural log of each data point of this Data object.
1082       -1 for negative values, zero for zero values, 1 for positive values.       *
1083    */    */
1084      ESCRIPT_DLL_API
1085    Data    Data
1086    sign() const;    log() const;
1087    
1088    /**    /**
1089      \transpose       \brief
1090      Transpose each data point of this Data object around the given axis.       Return the exponential function of each data point of this Data object.
1091      --* not implemented yet *--       *
1092    */    */
1093      ESCRIPT_DLL_API
1094    Data    Data
1095    transpose(int axis) const;    exp() const;
1096    
1097    /**    /**
1098      \trace       \brief
1099      Calculate the trace of each data point of this Data object.       Return the square root of each data point of this Data object.
1100      sum(A[i,i,i,i])       *
1101    */    */
1102      ESCRIPT_DLL_API
1103    Data    Data
1104    trace() const;    sqrt() const;
1105    
1106    /**    /**
1107      \exp       \brief
1108      Return the exponential function of each data point of this Data object.       Return the negation of each data point of this Data object.
1109         *
1110    */    */
1111      ESCRIPT_DLL_API
1112    Data    Data
1113    exp() const;    neg() const;
1114    
1115    /**    /**
1116      \sqrt       \brief
1117      Return the square root of each data point of this Data object.       Return the identity of each data point of this Data object.
1118         Simply returns this object unmodified.
1119         *
1120    */    */
1121      ESCRIPT_DLL_API
1122    Data    Data
1123    sqrt() const;    pos() const;
1124    
1125    /**    /**
1126       \brief       \brief
1127       Return the given power of each data point of this Data object.       Return the given power of each data point of this Data object.
1128    
1129         \param right Input - the power to raise the object to.
1130         *
1131    */    */
1132      ESCRIPT_DLL_API
1133    Data    Data
1134    powD(const Data& right) const;    powD(const Data& right) const;
1135    
1136      /**
1137         \brief
1138         Return the given power of each data point of this boost python object.
1139    
1140         \param right Input - the power to raise the object to.
1141         *
1142       */
1143      ESCRIPT_DLL_API
1144    Data    Data
1145    powO(const boost::python::object& right) const;    powO(const boost::python::object& right) const;
1146    
1147    /**    /**
1148      \brief       \brief
1149      writes the object to a file in the DX file format       Return the given power of each data point of this boost python object.
1150    
1151         \param left Input - the bases
1152         *
1153       */
1154    
1155      ESCRIPT_DLL_API
1156      Data
1157      rpowO(const boost::python::object& left) const;
1158    
1159      /**
1160         \brief
1161         writes the object to a file in the DX file format
1162    */    */
1163      ESCRIPT_DLL_API
1164    void    void
1165    saveDX(std::string fileName) const;    saveDX(std::string fileName) const;
1166    
1167    /**    /**
1168      \brief       \brief
1169      writes the object to a file in the VTK file format       writes the object to a file in the VTK file format
1170    */    */
1171      ESCRIPT_DLL_API
1172    void    void
1173    saveVTK(std::string fileName) const;    saveVTK(std::string fileName) const;
1174    
1175    /**    /**
     \brief  
     Return the negation of each data point of this Data object.  
   */  
   Data  
   neg() const;  
   
   /**  
     \brief  
     Return the identity of each data point of this Data object.  
     Simply returns this object unmodified.  
   */  
   Data  
   pos() const;  
   
   /**  
1176       \brief       \brief
1177       Overloaded operator +=       Overloaded operator +=
1178       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1179         *
1180    */    */
1181      ESCRIPT_DLL_API
1182    Data& operator+=(const Data& right);    Data& operator+=(const Data& right);
1183      ESCRIPT_DLL_API
1184    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1185    
1186      ESCRIPT_DLL_API
1187      Data& operator=(const Data& other);
1188    
1189    /**    /**
1190       \brief       \brief
1191       Overloaded operator -=       Overloaded operator -=
1192       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1193         *
1194    */    */
1195      ESCRIPT_DLL_API
1196    Data& operator-=(const Data& right);    Data& operator-=(const Data& right);
1197      ESCRIPT_DLL_API
1198    Data& operator-=(const boost::python::object& right);    Data& operator-=(const boost::python::object& right);
1199    
1200   /**   /**
1201       \brief       \brief
1202       Overloaded operator *=       Overloaded operator *=
1203       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1204         *
1205    */    */
1206      ESCRIPT_DLL_API
1207    Data& operator*=(const Data& right);    Data& operator*=(const Data& right);
1208      ESCRIPT_DLL_API
1209    Data& operator*=(const boost::python::object& right);    Data& operator*=(const boost::python::object& right);
1210    
1211   /**   /**
1212       \brief       \brief
1213       Overloaded operator /=       Overloaded operator /=
1214       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1215         *
1216    */    */
1217      ESCRIPT_DLL_API
1218    Data& operator/=(const Data& right);    Data& operator/=(const Data& right);
1219      ESCRIPT_DLL_API
1220    Data& operator/=(const boost::python::object& right);    Data& operator/=(const boost::python::object& right);
1221    
1222    /**    /**
1223       \brief       \brief
1224       Returns true if this can be interpolated to functionspace.       Returns true if this can be interpolated to functionspace.
1225    */    */
1226      ESCRIPT_DLL_API
1227    bool    bool
1228    probeInterpolation(const FunctionSpace& functionspace) const;    probeInterpolation(const FunctionSpace& functionspace) const;
1229    
# Line 819  class Data { Line 1242  class Data {
1242       \param key - Input - python slice tuple specifying       \param key - Input - python slice tuple specifying
1243       slice to return.       slice to return.
1244    */    */
1245      ESCRIPT_DLL_API
1246    Data    Data
1247    getItem(const boost::python::object& key) const;    getItem(const boost::python::object& key) const;
1248    
# Line 826  class Data { Line 1250  class Data {
1250       \brief       \brief
1251       Copies slice from value into this Data object.       Copies slice from value into this Data object.
1252    
      \description  
1253       Implements the [] set operator in python.       Implements the [] set operator in python.
1254       Calls setSlice.       Calls setSlice.
1255    
# Line 834  class Data { Line 1257  class Data {
1257       slice to copy from value.       slice to copy from value.
1258       \param value - Input - Data object to copy from.       \param value - Input - Data object to copy from.
1259    */    */
1260      ESCRIPT_DLL_API
1261    void    void
1262    setItemD(const boost::python::object& key,    setItemD(const boost::python::object& key,
1263             const Data& value);             const Data& value);
1264    
1265      ESCRIPT_DLL_API
1266    void    void
1267    setItemO(const boost::python::object& key,    setItemO(const boost::python::object& key,
1268             const boost::python::object& value);             const boost::python::object& value);
# Line 850  class Data { Line 1275  class Data {
1275       this Data object.       this Data object.
1276    */    */
1277    template <class UnaryFunction>    template <class UnaryFunction>
1278      ESCRIPT_DLL_API
1279    inline    inline
1280    void    void
1281    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1282    
1283    /**    /**
1284       \brief       \brief
1285       Return a Data object containing the specified slice of       Return a Data object containing the specified slice of
1286       this Data object.       this Data object.
1287       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1288         *
1289    */    */
1290      ESCRIPT_DLL_API
1291    Data    Data
1292    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataTypes::RegionType& region) const;
1293    
1294    /**    /**
1295       \brief       \brief
# Line 869  class Data { Line 1297  class Data {
1297       Data object.       Data object.
1298       \param value - Input - Data to copy from.       \param value - Input - Data to copy from.
1299       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1300         *
1301    */    */
1302      ESCRIPT_DLL_API
1303    void    void
1304    setSlice(const Data& value,    setSlice(const Data& value,
1305             const DataArrayView::RegionType& region);             const DataTypes::RegionType& region);
1306    
1307      /**
1308         \brief
1309         print the data values to stdout. Used for debugging
1310      */
1311      ESCRIPT_DLL_API
1312      void
1313            print(void);
1314    
1315      /**
1316         \brief
1317         return the MPI rank number of the local data
1318                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1319                     is returned
1320      */
1321      ESCRIPT_DLL_API
1322            int
1323            get_MPIRank(void) const;
1324    
1325      /**
1326         \brief
1327         return the MPI rank number of the local data
1328                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1329                     is returned
1330      */
1331      ESCRIPT_DLL_API
1332            int
1333            get_MPISize(void) const;
1334    
1335      /**
1336         \brief
1337         return the MPI rank number of the local data
1338                     MPI_COMM_WORLD is assumed and returned.
1339      */
1340      ESCRIPT_DLL_API
1341            MPI_Comm
1342            get_MPIComm(void) const;
1343    
1344      /**
1345         \brief
1346         return the object produced by the factory, which is a DataConstant or DataExpanded
1347        TODO Ownership of this object should be explained in doco.
1348      */
1349      ESCRIPT_DLL_API
1350            DataAbstract*
1351            borrowData(void) const;
1352    
1353    
1354      /**
1355         \brief
1356         Return a pointer to the beginning of the datapoint at the specified offset.
1357         TODO Eventually these should be inlined.
1358         \param i - position(offset) in the underlying datastructure
1359      */
1360      ESCRIPT_DLL_API
1361            DataTypes::ValueType::const_reference
1362            getDataAtOffset(DataTypes::ValueType::size_type i) const;
1363    
1364    
1365      ESCRIPT_DLL_API
1366            DataTypes::ValueType::reference
1367            getDataAtOffset(DataTypes::ValueType::size_type i);
1368    
1369   protected:   protected:
1370    
# Line 896  class Data { Line 1388  class Data {
1388       Perform the specified reduction algorithm on every element of every data point in       Perform the specified reduction algorithm on every element of every data point in
1389       this Data object according to the given function and return the single value result.       this Data object according to the given function and return the single value result.
1390    */    */
1391    template <class UnaryFunction>    template <class BinaryFunction>
1392    inline    inline
1393    double    double
1394    algorithm(UnaryFunction operation) const;    algorithm(BinaryFunction operation,
1395                double initial_value) const;
1396    
1397    /**    /**
1398       \brief       \brief
# Line 908  class Data { Line 1401  class Data {
1401       one value - the result of the reduction operation on the corresponding data-point in       one value - the result of the reduction operation on the corresponding data-point in
1402       this Data object       this Data object
1403    */    */
1404    template <class UnaryFunction>    template <class BinaryFunction>
1405    inline    inline
1406    Data    Data
1407    dp_algorithm(UnaryFunction operation) const;    dp_algorithm(BinaryFunction operation,
1408                   double initial_value) const;
1409    
1410    /**    /**
1411       \brief       \brief
# Line 929  class Data { Line 1423  class Data {
1423    
1424    /**    /**
1425       \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  
1426       Convert the data type of the RHS to match this.       Convert the data type of the RHS to match this.
1427       \param right - Input - data type to match.       \param right - Input - data type to match.
1428    */    */
# Line 958  class Data { Line 1441  class Data {
1441       \brief       \brief
1442       Construct a Data object of the appropriate type.       Construct a Data object of the appropriate type.
1443    */    */
1444    template <class IValueType>  
1445    void    void
1446    initialise(const IValueType& value,    initialise(const DataTypes::ValueType& value,
1447             const DataTypes::ShapeType& shape,
1448               const FunctionSpace& what,               const FunctionSpace& what,
1449               bool expanded);               bool expanded);
1450    
   /**  
      \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.  
   */  
1451    void    void
1452    reshapeDataPoint(const DataArrayView::ShapeType& shape);    initialise(const boost::python::numeric::array& value,
1453                     const FunctionSpace& what,
1454                     bool expanded);
1455    
1456      //
1457      // flag to protect the data object against any update
1458      bool m_protected;
1459    
1460    //    //
1461    // pointer to the actual data object    // pointer to the actual data object
# Line 980  class Data { Line 1463  class Data {
1463    
1464  };  };
1465    
1466  template <class IValueType>  
1467  void  
1468  Data::initialise(const IValueType& value,  /**
1469                   const FunctionSpace& what,     Modify a filename for MPI parallel output to multiple files
1470                   bool expanded)  */
1471  {  char *Escript_MPI_appendRankToFileName(const char *, int, int);
   //  
   // Construct a Data object of the appropriate type.  
   // Construct the object first as there seems to be a bug which causes  
   // undefined behaviour if an exception is thrown during construction  
   // within the shared_ptr constructor.  
   if (expanded) {  
     DataAbstract* temp=new DataExpanded(value,what);  
     boost::shared_ptr<DataAbstract> temp_data(temp);  
     m_data=temp_data;  
   } else {  
     DataAbstract* temp=new DataConstant(value,what);  
     boost::shared_ptr<DataAbstract> temp_data(temp);  
     m_data=temp_data;  
   }  
 }  
1472    
1473  /**  /**
1474     Binary Data object operators.     Binary Data object operators.
1475  */  */
1476    inline double rpow(double x,double y)
1477    {
1478        return pow(y,x);
1479    }
1480    
1481  /**  /**
1482    \brief    \brief
1483    Operator+    Operator+
1484    Takes two Data objects.    Takes two Data objects.
1485  */  */
1486  Data operator+(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1487    
1488  /**  /**
1489    \brief    \brief
1490    Operator-    Operator-
1491    Takes two Data objects.    Takes two Data objects.
1492  */  */
1493  Data operator-(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1494    
1495  /**  /**
1496    \brief    \brief
1497    Operator*    Operator*
1498    Takes two Data objects.    Takes two Data objects.
1499  */  */
1500  Data operator*(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1501    
1502  /**  /**
1503    \brief    \brief
1504    Operator/    Operator/
1505    Takes two Data objects.    Takes two Data objects.
1506  */  */
1507  Data operator/(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1508    
1509  /**  /**
1510    \brief    \brief
# Line 1040  Data operator/(const Data& left, const D Line 1512  Data operator/(const Data& left, const D
1512    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1513    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1514  */  */
1515  Data operator+(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const boost::python::object& right);
1516    
1517  /**  /**
1518    \brief    \brief
# Line 1048  Data operator+(const Data& left, const b Line 1520  Data operator+(const Data& left, const b
1520    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1521    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1522  */  */
1523  Data operator-(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const boost::python::object& right);
1524    
1525  /**  /**
1526    \brief    \brief
# Line 1056  Data operator-(const Data& left, const b Line 1528  Data operator-(const Data& left, const b
1528    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1529    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1530  */  */
1531  Data operator*(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const boost::python::object& right);
1532    
1533  /**  /**
1534    \brief    \brief
# Line 1064  Data operator*(const Data& left, const b Line 1536  Data operator*(const Data& left, const b
1536    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1537    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1538  */  */
1539  Data operator/(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const boost::python::object& right);
1540    
1541  /**  /**
1542    \brief    \brief
# Line 1072  Data operator/(const Data& left, const b Line 1544  Data operator/(const Data& left, const b
1544    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1545    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1546  */  */
1547  Data operator+(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const boost::python::object& left, const Data& right);
1548    
1549  /**  /**
1550    \brief    \brief
# Line 1080  Data operator+(const boost::python::obje Line 1552  Data operator+(const boost::python::obje
1552    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1553    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1554  */  */
1555  Data operator-(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const boost::python::object& left, const Data& right);
1556    
1557  /**  /**
1558    \brief    \brief
# Line 1088  Data operator-(const boost::python::obje Line 1560  Data operator-(const boost::python::obje
1560    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1561    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1562  */  */
1563  Data operator*(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const boost::python::object& left, const Data& right);
1564    
1565  /**  /**
1566    \brief    \brief
# Line 1096  Data operator*(const boost::python::obje Line 1568  Data operator*(const boost::python::obje
1568    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1569    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1570  */  */
1571  Data operator/(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1572    
1573    
1574    
1575  /**  /**
1576    \brief    \brief
1577    Output operator    Output operator
1578  */  */
1579  std::ostream& operator<<(std::ostream& o, const Data& data);  ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1580    
1581  /**  /**
1582    \brief    \brief
1583    Return true if operands are equivalent, else return false.    Compute a tensor product of two Data objects
1584    NB: this operator does very little at this point, and isn't to    \param arg0 - Input - Data object
1585    be relied on. Requires further implementation.    \param arg1 - Input - Data object
1586      \param axis_offset - Input - axis offset
1587      \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1588  */  */
1589  //bool operator==(const Data& left, const Data& right);  ESCRIPT_DLL_API
1590    Data
1591    C_GeneralTensorProduct(Data& arg0,
1592                         Data& arg1,
1593                         int axis_offset=0,
1594                         int transpose=0);
1595    
1596    
1597    
1598    // /**
1599    /*  \brief
1600      Return true if operands are equivalent, else return false.
1601      NB: this operator does very little at this point, and isn't to
1602      be relied on. Requires further implementation.*/
1603    //*/
1604    // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1605    
1606  /**  /**
1607    \brief    \brief
# Line 1125  Data::binaryOp(const Data& right, Line 1616  Data::binaryOp(const Data& right,
1616  {  {
1617     //     //
1618     // 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
1619     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1620       reshapeDataPoint(right.getPointDataView().getShape());       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1621     }     }
1622     //     //
1623     // initially make the temporary a shallow copy     // initially make the temporary a shallow copy
# Line 1134  Data::binaryOp(const Data& right, Line 1625  Data::binaryOp(const Data& right,
1625     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1626       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1627         //         //
1628         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1629         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1630       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1631         //         //
# Line 1182  Data::binaryOp(const Data& right, Line 1673  Data::binaryOp(const Data& right,
1673    
1674  /**  /**
1675    \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  
1676    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.
1677    Given operation combines each element of each data point, thus argument    Given operation combines each element of each data point, thus argument
1678    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.
1679    Calls escript::algorithm.    Calls escript::algorithm.
1680  */  */
1681  template <class UnaryFunction>  template <class BinaryFunction>
1682  inline  inline
1683  double  double
1684  Data::algorithm(UnaryFunction operation) const  Data::algorithm(BinaryFunction operation, double initial_value) const
1685  {  {
1686    if (isExpanded()) {    if (isExpanded()) {
1687      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1688      EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");      EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1689      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1690    } else if (isTagged()) {    } else if (isTagged()) {
1691      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1692      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1693      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1694    } else if (isConstant()) {    } else if (isConstant()) {
1695      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1696      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1697      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1698      } else if (isEmpty()) {
1699        throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1700    }    }
1701    return 0;    return 0;
1702  }  }
# Line 1298  Data::algorithm(UnaryFunction operation) Line 1705  Data::algorithm(UnaryFunction operation)
1705    \brief    \brief
1706    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.
1707    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1708    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
1709    rank 0 Data object.    rank 0 Data object.
1710    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1711  */  */
1712  template <class UnaryFunction>  template <class BinaryFunction>
1713  inline  inline
1714  Data  Data
1715  Data::dp_algorithm(UnaryFunction operation) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1716  {  {
1717    Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());    if (isEmpty()) {
1718    if (isExpanded()) {      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1719      }
1720      else if (isExpanded()) {
1721        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1722      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1723      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1724      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1725      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1726      escript::dp_algorithm(*dataE,*resultE,operation);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1727    } else if (isTagged()) {      return result;
1728      }
1729      else if (isTagged()) {
1730      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
     DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());  
1731      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1732      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      DataTypes::ValueType defval(1);
1733      escript::dp_algorithm(*dataT,*resultT,operation);      defval[0]=0;
1734    } else if (isConstant()) {      DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1735        escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1736        return Data(resultT);   // note: the Data object now owns the resultT pointer
1737      }
1738      else if (isConstant()) {
1739        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1740      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1741      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1742      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1743      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1744      escript::dp_algorithm(*dataC,*resultC,operation);      escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1745        return result;
1746      }
1747      Data falseRetVal; // to keep compiler quiet
1748      return falseRetVal;
1749    }
1750    
1751    /**
1752      \brief
1753      Compute a tensor operation with two Data objects
1754      \param arg0 - Input - Data object
1755      \param arg1 - Input - Data object
1756      \param operation - Input - Binary op functor
1757    */
1758    template <typename BinaryFunction>
1759    inline
1760    Data
1761    C_TensorBinaryOperation(Data const &arg_0,
1762                            Data const &arg_1,
1763                            BinaryFunction operation)
1764    {
1765      if (arg_0.isEmpty() || arg_1.isEmpty())
1766      {
1767         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1768    }    }
1769    return result;    // Interpolate if necessary and find an appropriate function space
1770      Data arg_0_Z, arg_1_Z;
1771      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1772        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1773          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1774          arg_1_Z = Data(arg_1);
1775        }
1776        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1777          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1778          arg_0_Z =Data(arg_0);
1779        }
1780        else {
1781          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1782        }
1783      } else {
1784          arg_0_Z = Data(arg_0);
1785          arg_1_Z = Data(arg_1);
1786      }
1787      // Get rank and shape of inputs
1788      int rank0 = arg_0_Z.getDataPointRank();
1789      int rank1 = arg_1_Z.getDataPointRank();
1790      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1791      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1792      int size0 = arg_0_Z.getDataPointSize();
1793      int size1 = arg_1_Z.getDataPointSize();
1794    
1795      // Declare output Data object
1796      Data res;
1797    
1798      if (shape0 == shape1) {
1799    
1800        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1801          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1802    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1803          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1804          double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1805          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1806          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1807          double *ptr_2 = &(res.getDataAtOffset(0));
1808    
1809          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1810        }
1811        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1812    
1813          // Prepare the DataConstant input
1814          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1815    
1816          // Borrow DataTagged input from Data object
1817          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1818    
1819          // Prepare a DataTagged output 2
1820          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1821          res.tag();
1822          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1823    
1824          // Prepare offset into DataConstant
1825          int offset_0 = tmp_0->getPointOffset(0,0);
1826          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1827          // Get the views
1828    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1829    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1830    //       // Get the pointers to the actual data
1831    //       double *ptr_1 = &((view_1.getData())[0]);
1832    //       double *ptr_2 = &((view_2.getData())[0]);
1833    
1834          // Get the pointers to the actual data
1835          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1836          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1837    
1838          // Compute a result for the default
1839          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1840          // Compute a result for each tag
1841          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1842          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1843          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1844            tmp_2->addTag(i->first);
1845    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1846            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1847            double *ptr_1 = &view_1.getData(0);
1848            double *ptr_2 = &view_2.getData(0);*/
1849            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1850            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1851    
1852            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1853          }
1854    
1855        }
1856        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1857    
1858          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1859          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1860          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1861          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1862    
1863          int sampleNo_1,dataPointNo_1;
1864          int numSamples_1 = arg_1_Z.getNumSamples();
1865          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1866          int offset_0 = tmp_0->getPointOffset(0,0);
1867          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1868          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1869            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1870              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1871              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1872    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1873    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1874    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1875    
1876              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1877              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1878              double *ptr_2 = &(res.getDataAtOffset(offset_2));
1879              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1880            }
1881          }
1882    
1883        }
1884        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1885    
1886          // Borrow DataTagged input from Data object
1887          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1888    
1889          // Prepare the DataConstant input
1890          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1891    
1892          // Prepare a DataTagged output 2
1893          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1894          res.tag();
1895          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1896    
1897          // Prepare offset into DataConstant
1898          int offset_1 = tmp_1->getPointOffset(0,0);
1899    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1900          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1901          // Get the views
1902    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1903    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1904    //       // Get the pointers to the actual data
1905    //       double *ptr_0 = &((view_0.getData())[0]);
1906    //       double *ptr_2 = &((view_2.getData())[0]);
1907          // Get the pointers to the actual data
1908          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1909          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1910          // Compute a result for the default
1911          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1912          // Compute a result for each tag
1913          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1914          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1915          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1916            tmp_2->addTag(i->first);
1917    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1918    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1919    //         double *ptr_0 = &view_0.getData(0);
1920    //         double *ptr_2 = &view_2.getData(0);
1921            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1922            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1923            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1924          }
1925    
1926        }
1927        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1928    
1929          // Borrow DataTagged input from Data object
1930          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1931    
1932          // Borrow DataTagged input from Data object
1933          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1934    
1935          // Prepare a DataTagged output 2
1936          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1937          res.tag();        // DataTagged output
1938          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1939    
1940    //       // Get the views
1941    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1942    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1943    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1944    //       // Get the pointers to the actual data
1945    //       double *ptr_0 = &((view_0.getData())[0]);
1946    //       double *ptr_1 = &((view_1.getData())[0]);
1947    //       double *ptr_2 = &((view_2.getData())[0]);
1948    
1949          // Get the pointers to the actual data
1950          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1951          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1952          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1953    
1954          // Compute a result for the default
1955          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1956          // Merge the tags
1957          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1958          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1959          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1960          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1961            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
1962          }
1963          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1964            tmp_2->addTag(i->first);
1965          }
1966          // Compute a result for each tag
1967          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1968          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1969    
1970    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1971    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1972    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1973    //         double *ptr_0 = &view_0.getData(0);
1974    //         double *ptr_1 = &view_1.getData(0);
1975    //         double *ptr_2 = &view_2.getData(0);
1976    
1977            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1978            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1979            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1980    
1981            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1982          }
1983    
1984        }
1985        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
1986    
1987          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1988          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1989          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1990          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1991          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1992    
1993          int sampleNo_0,dataPointNo_0;
1994          int numSamples_0 = arg_0_Z.getNumSamples();
1995          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1996          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1997          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1998            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
1999            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2000            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2001              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2002              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2003    
2004    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2005    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2006              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2007              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2008    
2009    
2010              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2011            }
2012          }
2013    
2014        }
2015        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2016    
2017          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2018          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2019          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2020          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2021    
2022          int sampleNo_0,dataPointNo_0;
2023          int numSamples_0 = arg_0_Z.getNumSamples();
2024          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2025          int offset_1 = tmp_1->getPointOffset(0,0);
2026          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2027          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2028            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2029              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2030              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2031    
2032    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2033    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2034    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2035    
2036              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2037              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2038              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2039    
2040    
2041              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2042            }
2043          }
2044    
2045        }
2046        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2047    
2048          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2049          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2050          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2051          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2052          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2053    
2054          int sampleNo_0,dataPointNo_0;
2055          int numSamples_0 = arg_0_Z.getNumSamples();
2056          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2057          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2058          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2059            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2060            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2061            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2062              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2063              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2064              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2065              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2066              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2067            }
2068          }
2069    
2070        }
2071        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2072    
2073          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2074          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2075          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2076          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2077          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2078    
2079          int sampleNo_0,dataPointNo_0;
2080          int numSamples_0 = arg_0_Z.getNumSamples();
2081          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2082          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2083          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2084            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2085              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2086              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2087              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2088              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2089              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2090              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2091              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2092            }
2093          }
2094    
2095        }
2096        else {
2097          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2098        }
2099    
2100      } else if (0 == rank0) {
2101    
2102        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2103          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2104          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2105          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2106          double *ptr_2 = &(res.getDataAtOffset(0));
2107          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2108        }
2109        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2110    
2111          // Prepare the DataConstant input
2112          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2113    
2114          // Borrow DataTagged input from Data object
2115          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2116    
2117          // Prepare a DataTagged output 2
2118          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2119          res.tag();
2120          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2121    
2122          // Prepare offset into DataConstant
2123          int offset_0 = tmp_0->getPointOffset(0,0);
2124          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2125          // Get the views
2126    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2127    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2128    //       // Get the pointers to the actual data
2129    //       double *ptr_1 = &((view_1.getData())[0]);
2130    //       double *ptr_2 = &((view_2.getData())[0]);
2131           double *ptr_1 = &(tmp_1->getDefaultValue(0));
2132           double *ptr_2 = &(tmp_2->getDefaultValue(0));
2133    
2134          // Compute a result for the default
2135          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2136          // Compute a result for each tag
2137          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2138          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2139          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2140            tmp_2->addTag(i->first);
2141    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2142    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2143    //         double *ptr_1 = &view_1.getData(0);
2144    //         double *ptr_2 = &view_2.getData(0);
2145            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2146            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2147            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2148          }
2149    
2150        }
2151        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2152    
2153          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2154          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2155          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2156          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2157    
2158          int sampleNo_1,dataPointNo_1;
2159          int numSamples_1 = arg_1_Z.getNumSamples();
2160          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2161          int offset_0 = tmp_0->getPointOffset(0,0);
2162          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2163          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2164            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2165              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2166              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2167              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2168              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2169              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2170              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2171    
2172            }
2173          }
2174    
2175        }
2176        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2177    
2178          // Borrow DataTagged input from Data object
2179          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2180    
2181          // Prepare the DataConstant input
2182          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2183    
2184          // Prepare a DataTagged output 2
2185          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2186          res.tag();
2187          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2188    
2189          // Prepare offset into DataConstant
2190          int offset_1 = tmp_1->getPointOffset(0,0);
2191    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2192          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2193          // Get the views
2194    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2195          DataArrayView view_2 = tmp_2->getDefaultValue();
2196          // Get the pointers to the actual data
2197          double *ptr_0 = &((view_0.getData())[0]);
2198          double *ptr_2 = &((view_2.getData())[0]);*/
2199    
2200          // Get the pointers to the actual data
2201          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2202          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2203    
2204    
2205          // Compute a result for the default
2206          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2207          // Compute a result for each tag
2208          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2209          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2210          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2211            tmp_2->addTag(i->first);
2212    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2213            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2214            double *ptr_0 = &view_0.getData(0);
2215            double *ptr_2 = &view_2.getData(0);*/
2216            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2217            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2218    
2219            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2220          }
2221    
2222        }
2223        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2224    
2225          // Borrow DataTagged input from Data object
2226          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2227    
2228          // Borrow DataTagged input from Data object
2229          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2230    
2231          // Prepare a DataTagged output 2
2232          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2233          res.tag();        // DataTagged output
2234          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2235    
2236          // Get the views
2237    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2238          DataArrayView view_1 = tmp_1->getDefaultValue();
2239          DataArrayView view_2 = tmp_2->getDefaultValue();
2240          // Get the pointers to the actual data
2241          double *ptr_0 = &((view_0.getData())[0]);
2242          double *ptr_1 = &((view_1.getData())[0]);
2243          double *ptr_2 = &((view_2.getData())[0]);*/
2244    
2245          // Get the pointers to the actual data
2246          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2247          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2248          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2249    
2250    
2251          // Compute a result for the default
2252          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2253          // Merge the tags
2254          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2255          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2256          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2257          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2258            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2259          }
2260          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2261            tmp_2->addTag(i->first);
2262          }
2263          // Compute a result for each tag
2264          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2265          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2266    
2267    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2268            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2269            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2270            double *ptr_0 = &view_0.getData(0);
2271            double *ptr_1 = &view_1.getData(0);
2272            double *ptr_2 = &view_2.getData(0);*/
2273    
2274            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2275            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2276            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2277    
2278            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2279          }
2280    
2281        }
2282        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2283    
2284          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2285          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2286          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2287          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2288          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2289    
2290          int sampleNo_0,dataPointNo_0;
2291          int numSamples_0 = arg_0_Z.getNumSamples();
2292          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2293          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2294          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2295            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2296            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2297            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2298              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2299              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2300              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2301              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2302              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2303            }
2304          }
2305    
2306        }
2307        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2308    
2309          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2310          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2311          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2312          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2313    
2314          int sampleNo_0,dataPointNo_0;
2315          int numSamples_0 = arg_0_Z.getNumSamples();
2316          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2317          int offset_1 = tmp_1->getPointOffset(0,0);
2318          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2319          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2320            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2321              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2322              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2323              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2324              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2325              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2326              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2327            }
2328          }
2329    
2330    
2331        }
2332        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2333    
2334          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2335          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2336          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2337          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2338          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2339    
2340          int sampleNo_0,dataPointNo_0;
2341          int numSamples_0 = arg_0_Z.getNumSamples();
2342          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2343          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2344          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2345            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2346            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2347            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2348              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2349              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2350              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2351              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2352              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2353            }
2354          }
2355    
2356        }
2357        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2358    
2359          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2360          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2361          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2362          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2363          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2364    
2365          int sampleNo_0,dataPointNo_0;
2366          int numSamples_0 = arg_0_Z.getNumSamples();
2367          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2368          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2369          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2370            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2371              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2372              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2373              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2374              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2375              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2376              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2377              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2378            }
2379          }
2380    
2381        }
2382        else {
2383          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2384        }
2385    
2386      } else if (0 == rank1) {
2387    
2388        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2389          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2390          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2391          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2392          double *ptr_2 = &(res.getDataAtOffset(0));
2393          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2394        }
2395        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2396    
2397          // Prepare the DataConstant input
2398          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2399    
2400          // Borrow DataTagged input from Data object
2401          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2402    
2403          // Prepare a DataTagged output 2
2404          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2405          res.tag();
2406          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2407    
2408          // Prepare offset into DataConstant
2409          int offset_0 = tmp_0->getPointOffset(0,0);
2410          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2411          // Get the views
2412    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2413          DataArrayView view_2 = tmp_2->getDefaultValue();
2414          // Get the pointers to the actual data
2415          double *ptr_1 = &((view_1.getData())[0]);
2416          double *ptr_2 = &((view_2.getData())[0]);*/
2417          //Get the pointers to the actual data
2418          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2419          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2420    
2421          // Compute a result for the default
2422          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2423          // Compute a result for each tag
2424          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2425          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2426          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2427            tmp_2->addTag(i->first);
2428    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2429    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2430    //         double *ptr_1 = &view_1.getData(0);
2431    //         double *ptr_2 = &view_2.getData(0);
2432            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2433            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2434    
2435    
2436            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2437          }
2438    
2439        }
2440        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2441    
2442          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2443          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2444          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2445          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2446    
2447          int sampleNo_1,dataPointNo_1;
2448          int numSamples_1 = arg_1_Z.getNumSamples();
2449          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2450          int offset_0 = tmp_0->getPointOffset(0,0);
2451          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2452          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2453            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2454              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2455              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2456              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2457              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2458              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2459              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2460            }
2461          }
2462    
2463        }
2464        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2465    
2466          // Borrow DataTagged input from Data object
2467          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2468    
2469          // Prepare the DataConstant input
2470          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2471    
2472          // Prepare a DataTagged output 2
2473          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2474          res.tag();
2475          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2476    
2477          // Prepare offset into DataConstant
2478          int offset_1 = tmp_1->getPointOffset(0,0);
2479          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2480          // Get the views
2481    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2482    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2483    //       // Get the pointers to the actual data
2484    //       double *ptr_0 = &((view_0.getData())[0]);
2485    //       double *ptr_2 = &((view_2.getData())[0]);
2486          // Get the pointers to the actual data
2487          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2488          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2489          // Compute a result for the default
2490          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2491          // Compute a result for each tag
2492          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2493          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2494          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2495            tmp_2->addTag(i->first);
2496    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2497            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2498            double *ptr_0 = &view_0.getData(0);
2499            double *ptr_2 = &view_2.getData(0);*/
2500            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2501            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2502            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2503          }
2504    
2505        }
2506        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2507    
2508          // Borrow DataTagged input from Data object
2509          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2510    
2511          // Borrow DataTagged input from Data object
2512          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2513    
2514          // Prepare a DataTagged output 2
2515          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2516          res.tag();        // DataTagged output
2517          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2518    
2519          // Get the views
2520    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2521    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2522    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2523    //       // Get the pointers to the actual data
2524    //       double *ptr_0 = &((view_0.getData())[0]);
2525    //       double *ptr_1 = &((view_1.getData())[0]);
2526    //       double *ptr_2 = &((view_2.getData())[0]);
2527    
2528          // Get the pointers to the actual data
2529          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2530          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2531          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2532    
2533          // Compute a result for the default
2534          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2535          // Merge the tags
2536          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2537          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2538          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2539          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2540            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2541          }
2542          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2543            tmp_2->addTag(i->first);
2544          }
2545          // Compute a result for each tag
2546          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2547          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2548    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2549    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2550    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2551    //         double *ptr_0 = &view_0.getData(0);
2552    //         double *ptr_1 = &view_1.getData(0);
2553    //         double *ptr_2 = &view_2.getData(0);
2554    
2555            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2556            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2557            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2558            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2559          }
2560    
2561        }
2562        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2563    
2564          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2565          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2566          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2567          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2568          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2569    
2570          int sampleNo_0,dataPointNo_0;
2571          int numSamples_0 = arg_0_Z.getNumSamples();
2572          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2573          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2574          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2575            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2576            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2577            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2578              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2579              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2580              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2581              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2582              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2583            }
2584          }
2585    
2586        }
2587        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2588    
2589          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2590          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2591          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2592          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2593    
2594          int sampleNo_0,dataPointNo_0;
2595          int numSamples_0 = arg_0_Z.getNumSamples();
2596          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2597          int offset_1 = tmp_1->getPointOffset(0,0);
2598          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2599          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2600            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2601              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2602              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2603              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2604              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2605              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2606              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2607            }
2608          }
2609    
2610    
2611        }
2612        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2613    
2614          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2615          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2616          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2617          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2618          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2619    
2620          int sampleNo_0,dataPointNo_0;
2621          int numSamples_0 = arg_0_Z.getNumSamples();
2622          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2623          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2624          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2625            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2626            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2627            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2628              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2629              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2630              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2631              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2632              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2633            }
2634          }
2635    
2636        }
2637        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2638    
2639          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2640          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2641          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2642          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2643          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2644    
2645          int sampleNo_0,dataPointNo_0;
2646          int numSamples_0 = arg_0_Z.getNumSamples();
2647          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2648          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2649          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2650            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2651              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2652              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2653              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2654              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2655              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2656              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2657              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2658            }
2659          }
2660    
2661        }
2662        else {
2663          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2664        }
2665    
2666      } else {
2667        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2668      }
2669    
2670      return res;
2671    }
2672    
2673    template <typename UnaryFunction>
2674    Data
2675    C_TensorUnaryOperation(Data const &arg_0,
2676                           UnaryFunction operation)
2677    {
2678      if (arg_0.isEmpty())  // do this before we attempt to interpolate
2679      {
2680         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2681      }
2682    
2683      // Interpolate if necessary and find an appropriate function space
2684      Data arg_0_Z = Data(arg_0);
2685    
2686      // Get rank and shape of inputs
2687      int rank0 = arg_0_Z.getDataPointRank();
2688      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2689      int size0 = arg_0_Z.getDataPointSize();
2690    
2691      // Declare output Data object
2692      Data res;
2693    
2694      if (arg_0_Z.isConstant()) {
2695        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2696    //     double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2697    //     double *ptr_2 = &((res.getPointDataView().getData())[0]);
2698        double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2699        double *ptr_2 = &(res.getDataAtOffset(0));
2700        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2701      }
2702      else if (arg_0_Z.isTagged()) {
2703    
2704        // Borrow DataTagged input from Data object
2705        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2706    
2707        // Prepare a DataTagged output 2
2708        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2709        res.tag();
2710        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2711    
2712    //     // Get the views
2713    //     DataArrayView view_0 = tmp_0->getDefaultValue();
2714    //     DataArrayView view_2 = tmp_2->getDefaultValue();
2715    //     // Get the pointers to the actual data
2716    //     double *ptr_0 = &((view_0.getData())[0]);
2717    //     double *ptr_2 = &((view_2.getData())[0]);
2718        // Get the pointers to the actual data
2719        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2720        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2721        // Compute a result for the default
2722        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2723        // Compute a result for each tag
2724        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2725        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2726        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2727          tmp_2->addTag(i->first);
2728    //       DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2729    //       DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2730    //       double *ptr_0 = &view_0.getData(0);
2731    //       double *ptr_2 = &view_2.getData(0);
2732          double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2733          double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2734          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2735        }
2736    
2737      }
2738      else if (arg_0_Z.isExpanded()) {
2739    
2740        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2741        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2742        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2743    
2744        int sampleNo_0,dataPointNo_0;
2745        int numSamples_0 = arg_0_Z.getNumSamples();
2746        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2747        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2748        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2749          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2750    //         int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2751    //         int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2752    //         double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2753    //         double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2754            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2755            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2756            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2757            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2758            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2759          }
2760        }
2761      }
2762      else {
2763        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2764      }
2765    
2766      return res;
2767  }  }
2768    
2769  }  }

Legend:
Removed from v.117  
changed lines
  Added in v.1821

  ViewVC Help
Powered by ViewVC 1.1.26