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

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

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

trunk/esys2/escript/src/Data/Data.h revision 97 by jgs, Tue Dec 14 05:39:33 2004 UTC trunk/escript/src/Data.h revision 1803 by jfenwick, Wed Sep 24 06:20:29 2008 UTC
# Line 1  Line 1 
 // $Id$  
 /*=============================================================================  
1    
2   ******************************************************************************  /* $Id$ */
  *                                                                            *  
  *       COPYRIGHT ACcESS 2004 -  All Rights Reserved                         *  
  *                                                                            *  
  * This software is the property of ACcESS.  No part of this code             *  
  * may be copied in any form or by any means without the expressed written    *  
  * consent of ACcESS.  Copying, use or modification of this software          *  
  * by any unauthorised person is illegal unless that                          *  
  * person has a software license agreement with ACcESS.                       *  
  *                                                                            *  
  ******************************************************************************  
3    
4  ******************************************************************************/  /*******************************************************
5     *
6     *           Copyright 2003-2007 by ACceSS MNRF
7     *       Copyright 2007 by University of Queensland
8     *
9     *                http://esscc.uq.edu.au
10     *        Primary Business: Queensland, Australia
11     *  Licensed under the Open Software License version 3.0
12     *     http://www.opensource.org/licenses/osl-3.0.php
13     *
14     *******************************************************/
15    
16    /** \file Data.h */
17    
18  #ifndef DATA_H  #ifndef DATA_H
19  #define DATA_H  #define DATA_H
20    #include "system_dep.h"
21    
22  #include "escript/Data/DataAbstract.h"  #include "DataAbstract.h"
23  #include "escript/Data/DataTagged.h"  #include "DataAlgorithm.h"
24  #include "escript/Data/FunctionSpace.h"  #include "FunctionSpace.h"
25  #include "escript/Data/BinaryOp.h"  #include "BinaryOp.h"
26  #include "escript/Data/UnaryOp.h"  #include "UnaryOp.h"
27    #include "DataException.h"
28    #include "DataTypes.h"
29    
30  extern "C" {  extern "C" {
31  #include "escript/Data/DataC.h"  #include "DataC.h"
32    /* #include "paso/Paso.h" doesn't belong in this file...causes trouble for BruceFactory.cpp */
33  }  }
34    
35  #include <iostream>  #include "esysmpi.h"
36  #include <string>  #include <string>
 #include <memory>  
37  #include <algorithm>  #include <algorithm>
38    #include <sstream>
39    
40    
41  #include <boost/shared_ptr.hpp>  #include <boost/shared_ptr.hpp>
42  #include <boost/python/object.hpp>  #include <boost/python/object.hpp>
 #include <boost/python/list.hpp>  
43  #include <boost/python/tuple.hpp>  #include <boost/python/tuple.hpp>
44  #include <boost/python/numeric.hpp>  #include <boost/python/numeric.hpp>
45    
 /**  
    \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.  
 */  
   
46  namespace escript {  namespace escript {
47    
48  //  //
49  // Forward declaration for various implimentations of Data.  // Forward declaration for various implementations of Data.
 class DataEmpty;  
50  class DataConstant;  class DataConstant;
51  class DataTagged;  class DataTagged;
52  class DataExpanded;  class DataExpanded;
53    
54    /**
55       \brief
56       Data represents a collection of datapoints.
57    
58       Description:
59       Internally, the datapoints are actually stored by a DataAbstract object.
60       The specific instance of DataAbstract used may vary over the lifetime
61       of the Data object.
62       Some methods on this class return references (eg getShape()).
63       These references should not be used after an operation which changes the underlying DataAbstract object.
64       Doing so will lead to invalid memory access.
65       This should not affect any methods exposed via boost::python.
66    */
67  class Data {  class Data {
68    
69    public:    public:
70    
71      // These typedefs allow function names to be cast to pointers
72      // to functions of the appropriate type when calling unaryOp etc.
73    typedef double (*UnaryDFunPtr)(double);    typedef double (*UnaryDFunPtr)(double);
74    typedef double (*BinaryDFunPtr)(double,double);    typedef double (*BinaryDFunPtr)(double,double);
75    
76    
77    /**    /**
78       Constructors.       Constructors.
79    */    */
# Line 80  class Data { Line 83  class Data {
83       Default constructor.       Default constructor.
84       Creates a DataEmpty object.       Creates a DataEmpty object.
85    */    */
86      ESCRIPT_DLL_API
87    Data();    Data();
88    
89    /**    /**
# Line 87  class Data { Line 91  class Data {
91       Copy constructor.       Copy constructor.
92       WARNING: Only performs a shallow copy.       WARNING: Only performs a shallow copy.
93    */    */
94      ESCRIPT_DLL_API
95    Data(const Data& inData);    Data(const Data& inData);
96    
97    /**    /**
# Line 95  class Data { Line 100  class Data {
100       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,
101       otherwise a shallow copy of inData is returned.       otherwise a shallow copy of inData is returned.
102    */    */
103      ESCRIPT_DLL_API
104    Data(const Data& inData,    Data(const Data& inData,
105         const FunctionSpace& what);         const FunctionSpace& what);
106    
107    /**    /**
108       \brief      \brief Copy Data from an existing vector
109       Constructor which copies data from a DataArrayView.    */
110    
111       \param value - Input - Data value for a single point.    ESCRIPT_DLL_API
112       \param what - Input - A description of what this data represents.    Data(const DataTypes::ValueType& value,
113       \param expanded - Input - Flag, if true fill the entire container with           const DataTypes::ShapeType& shape,
114                         the value. Otherwise a more efficient storage                   const FunctionSpace& what=FunctionSpace(),
115                         mechanism will be used.                   bool expanded=false);
   */  
   Data(const DataArrayView& value,  
        const FunctionSpace& what=FunctionSpace(),  
        bool expanded=false);  
116    
117    /**    /**
118       \brief       \brief
# Line 123  class Data { Line 125  class Data {
125                         the given value. Otherwise a more efficient storage                         the given value. Otherwise a more efficient storage
126                         mechanism will be used.                         mechanism will be used.
127    */    */
128      ESCRIPT_DLL_API
129    Data(double value,    Data(double value,
130         const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(),         const DataTypes::ShapeType& dataPointShape=DataTypes::ShapeType(),
131         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
132         bool expanded=false);         bool expanded=false);
133    
# Line 135  class Data { Line 138  class Data {
138       \param inData - Input - Input Data object.       \param inData - Input - Input Data object.
139       \param region - Input - Region to copy.       \param region - Input - Region to copy.
140    */    */
141      ESCRIPT_DLL_API
142    Data(const Data& inData,    Data(const Data& inData,
143         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);  
144    
145    /**    /**
146       \brief       \brief
# Line 167  class Data { Line 152  class Data {
152                         the value. Otherwise a more efficient storage                         the value. Otherwise a more efficient storage
153                         mechanism will be used.                         mechanism will be used.
154    */    */
155      ESCRIPT_DLL_API
156    Data(const boost::python::numeric::array& value,    Data(const boost::python::numeric::array& value,
157         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
158         bool expanded=false);         bool expanded=false);
# Line 182  class Data { Line 168  class Data {
168                         the value. Otherwise a more efficient storage                         the value. Otherwise a more efficient storage
169                         mechanism will be used.                         mechanism will be used.
170    */    */
171      ESCRIPT_DLL_API
172    Data(const boost::python::object& value,    Data(const boost::python::object& value,
173         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
174         bool expanded=false);         bool expanded=false);
# Line 195  class Data { Line 182  class Data {
182       \param value - Input - Input data.       \param value - Input - Input data.
183       \param other - Input - contains all other parameters.       \param other - Input - contains all other parameters.
184    */    */
185      ESCRIPT_DLL_API
186    Data(const boost::python::object& value,    Data(const boost::python::object& value,
187         const Data& other);         const Data& other);
188    
# Line 202  class Data { Line 190  class Data {
190       \brief       \brief
191       Constructor which creates a DataConstant of "shape" with constant value.       Constructor which creates a DataConstant of "shape" with constant value.
192    */    */
193    Data(double value,    ESCRIPT_DLL_API
194         const boost::python::tuple& shape=boost::python::make_tuple(),    Data(double value,
195           const boost::python::tuple& shape=boost::python::make_tuple(),
196         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
197         bool expanded=false);         bool expanded=false);
198    
199    
200    
201      /**
202        \brief Create a Data using an existing DataAbstract. Warning: The new object assumes ownership of the pointer!
203        Once you have passed the pointer, do not delete it.
204      */
205      ESCRIPT_DLL_API
206      Data(DataAbstract* underlyingdata);
207    
208    
209    /**    /**
210       \brief       \brief
211       Perform a deep copy.       Destructor
212    */    */
213      ESCRIPT_DLL_API
214      ~Data();
215    
216      /**
217         \brief Make this object a deep copy of "other".
218      */
219      ESCRIPT_DLL_API
220    void    void
221    copy(const Data& other);    copy(const Data& other);
222    
223    /**    /**
224         \brief Return a pointer to a deep copy of this object.
225      */
226      ESCRIPT_DLL_API
227      Data*
228      copySelf();
229    
230    
231    
232    
233      /**
234       Member access methods.       Member access methods.
235    */    */
236    
237    /**    /**
238       \brief       \brief
239         switches on update protection
240    
241      */
242      ESCRIPT_DLL_API
243      void
244      setProtection();
245    
246      /**
247         \brief
248         Returns trueif the data object is protected against update
249    
250      */
251      ESCRIPT_DLL_API
252      bool
253      isProtected() const;
254    
255      /**
256         \brief
257         Return the values of a data point on this process
258      */
259      ESCRIPT_DLL_API
260      const boost::python::numeric::array
261      getValueOfDataPoint(int dataPointNo);
262    
263      /**
264         \brief
265         sets the values of a data-point from a python object on this process
266      */
267      ESCRIPT_DLL_API
268      void
269      setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
270    
271      /**
272         \brief
273         sets the values of a data-point from a numarray object on this process
274      */
275      ESCRIPT_DLL_API
276      void
277      setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
278    
279      /**
280         \brief
281         sets the values of a data-point on this process
282      */
283      ESCRIPT_DLL_API
284      void
285      setValueOfDataPoint(int dataPointNo, const double);
286    
287      /**
288         \brief
289         Return the value of the specified data-point across all processors
290      */
291      ESCRIPT_DLL_API
292      const boost::python::numeric::array
293      getValueOfGlobalDataPoint(int procNo, int dataPointNo);
294    
295      /**
296         \brief
297         Return the tag number associated with the given data-point.
298    
299      */
300      ESCRIPT_DLL_API
301      int
302      getTagNumber(int dpno);
303    
304      /**
305         \brief
306       Return the C wrapper for the Data object.       Return the C wrapper for the Data object.
307    */    */
308      ESCRIPT_DLL_API
309    escriptDataC    escriptDataC
310    getDataC();    getDataC();
311    
312    
313    
314    
315    
316    
317    // REMOVE ME
318    // ESCRIPT_DLL_API
319    // void
320    // CompareDebug(const Data& rd);
321    
322    
323    /**    /**
324       \brief       \brief
325       Return the C wrapper for the Data object - const version.       Return the C wrapper for the Data object - const version.
326    */    */
327      ESCRIPT_DLL_API
328    escriptDataC    escriptDataC
329    getDataC() const;    getDataC() const;
330    
331    /**    /**
332       \brief       \brief
333       Write the data as a string.       Write the data as a string. For large amounts of data, a summary is printed.
334    */    */
335    inline    ESCRIPT_DLL_API
336    std::string    std::string
337    toString() const    toString() const;
   {  
     return m_data->toString();  
   }  
338    
339    /**  
340       \brief  //  /**
341    /*     \brief
342       Return the DataArrayView of the point data. This essentially contains       Return the DataArrayView of the point data. This essentially contains
343       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
344       to manipulate the point data.       to manipulate the point data.*/
345    */  //  */
346    inline  //   ESCRIPT_DLL_API
347    const DataArrayView&  //   inline
348    getPointDataView() const  //   const DataArrayView&
349    {  //   getPointDataView() const
350       return m_data->getPointDataView();  //   {
351    }  //      return m_data->getPointDataView();
352    //   }
353    
354    /**    /**
355       \brief       \brief
356       Whatever the current Data type make this into a DataExpanded.       Whatever the current Data type make this into a DataExpanded.
357    */    */
358      ESCRIPT_DLL_API
359    void    void
360    expand();    expand();
361    
# Line 268  class Data { Line 364  class Data {
364       If possible convert this Data to DataTagged. This will only allow       If possible convert this Data to DataTagged. This will only allow
365       Constant data to be converted to tagged. An attempt to convert       Constant data to be converted to tagged. An attempt to convert
366       Expanded data to tagged will throw an exception.       Expanded data to tagged will throw an exception.
367        ==>*
368    */    */
369      ESCRIPT_DLL_API
370    void    void
371    tag();    tag();
372    
# Line 276  class Data { Line 374  class Data {
374       \brief       \brief
375       Return true if this Data is expanded.       Return true if this Data is expanded.
376    */    */
377      ESCRIPT_DLL_API
378    bool    bool
379    isExpanded() const;    isExpanded() const;
380    
# Line 283  class Data { Line 382  class Data {
382       \brief       \brief
383       Return true if this Data is tagged.       Return true if this Data is tagged.
384    */    */
385      ESCRIPT_DLL_API
386    bool    bool
387    isTagged() const;    isTagged() const;
388    
# Line 290  class Data { Line 390  class Data {
390       \brief       \brief
391       Return true if this Data is constant.       Return true if this Data is constant.
392    */    */
393      ESCRIPT_DLL_API
394    bool    bool
395    isConstant() const;    isConstant() const;
396    
397    /**    /**
398       \brief       \brief
399       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
400    contains datapoints.
401    */    */
402      ESCRIPT_DLL_API
403    bool    bool
404    isEmpty() const;    isEmpty() const;
405    
# Line 304  class Data { Line 407  class Data {
407       \brief       \brief
408       Return the function space.       Return the function space.
409    */    */
410      ESCRIPT_DLL_API
411    inline    inline
412    const FunctionSpace&    const FunctionSpace&
413    getFunctionSpace() const    getFunctionSpace() const
# Line 315  class Data { Line 419  class Data {
419       \brief       \brief
420       Return a copy of the function space.       Return a copy of the function space.
421    */    */
422      ESCRIPT_DLL_API
423    const FunctionSpace    const FunctionSpace
424    getCopyOfFunctionSpace() const;    getCopyOfFunctionSpace() const;
425    
# Line 322  class Data { Line 427  class Data {
427       \brief       \brief
428       Return the domain.       Return the domain.
429    */    */
430      ESCRIPT_DLL_API
431    inline    inline
432    const AbstractDomain&    const AbstractDomain&
433    getDomain() const    getDomain() const
# Line 333  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 340  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 362  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 369  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 388  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 395  class Data { Line 539  class Data {
539      return m_data->getSampleDataByTag(tag);      return m_data->getSampleDataByTag(tag);
540    }    }
541    
542    //  /**
543    /*     \brief
544         Return a view into the data for the data point specified.
545         NOTE: Construction of the DataArrayView is a relatively expensive
546         operation.
547         \param sampleNo - Input -
548         \param dataPointNo - Input -*/
549    //  */
550    //   ESCRIPT_DLL_API
551    //   inline
552    //   DataArrayView
553    //   getDataPoint(int sampleNo,
554    //                int dataPointNo)
555    //   {
556    //                 return m_data->getDataPoint(sampleNo,dataPointNo);
557    //   }
558    
559    
560    /**    /**
561       \brief       \brief
562       Return a view into the data for the data point specified.       Return a view into the data for the data point specified.
# Line 403  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 430  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 437  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 481  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
807      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    Data
843    whereNonZero() const;    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 maximum value of this Data object.       Return the sinh of each data point of this Data object.
1019         *
1020    */    */
1021    double    ESCRIPT_DLL_API
1022    sup() const;    Data
1023      sinh() const;
1024    
1025    /**    /**
1026       \brief       \brief
1027       Return the minimum value of this Data object.       Return the cosh of each data point of this Data object.
1028         *
1029    */    */
1030    double    ESCRIPT_DLL_API
1031    inf() const;    Data
1032      cosh() const;
1033    
1034    /**    /**
1035       \brief       \brief
1036       Return the absolute value of each data point of this Data object.       Return the tanh of each data point of this Data object.
1037         *
1038    */    */
1039      ESCRIPT_DLL_API
1040    Data    Data
1041    abs() const;    tanh() const;
1042    
1043    /**    /**
1044       \brief       \brief
1045       Return the maximum 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    maxval() const;    asinh() const;
1051    
1052    /**    /**
1053       \brief       \brief
1054       Return the minimum 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    minval() const;    acosh() const;
1060    
1061    /**    /**
1062       \brief       \brief
1063       Return the length of each data point of this Data object.       Return the atanh of each data point of this Data object.
1064       sqrt(sum(A[i,j,k,l]^2))       *
1065    */    */
1066      ESCRIPT_DLL_API
1067    Data    Data
1068    length() const;    atanh() const;
1069    
1070    /**    /**
1071       \brief       \brief
1072       Return the sign of each data point of this Data object.       Return the log to base 10 of each data point of this Data object.
1073       -1 for negative values, zero for zero values, 1 for positive values.       *
1074    */    */
1075      ESCRIPT_DLL_API
1076    Data    Data
1077    sign() const;    log10() const;
1078    
1079    /**    /**
1080      \transpose       \brief
1081      Transpose each data point of this Data object around the given axis.       Return the natural log of each data point of this Data object.
1082         *
1083    */    */
1084      ESCRIPT_DLL_API
1085    Data    Data
1086    transpose(int axis) const;    log() const;
1087    
1088    /**    /**
1089      \trace       \brief
1090      Calculate the trace of each data point of this Data object.       Return the exponential function of each data point of this Data object.
1091      sum(A[i,i,i,i])       *
1092    */    */
1093      ESCRIPT_DLL_API
1094    Data    Data
1095    trace() const;    exp() const;
1096    
1097    /**    /**
1098      \exp       \brief
1099      Return the exponential function of each data point of this Data object.       Return the square root of each data point of this Data object.
1100         *
1101    */    */
1102      ESCRIPT_DLL_API
1103    Data    Data
1104    exp() const;    sqrt() const;
1105    
1106    /**    /**
1107      \sqrt       \brief
1108      Return the square root 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    sqrt() const;    neg() const;
1114    
1115      /**
1116         \brief
1117         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
1123      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      Return the negation of each data point of this Data object.       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    Data
1157    neg() const;    rpowO(const boost::python::object& left) const;
1158    
1159    /**    /**
1160      \brief       \brief
1161      Return the identity of each data point of this Data object.       writes the object to a file in the DX file format
     Simply returns this object unmodified.  
1162    */    */
1163    Data    ESCRIPT_DLL_API
1164    pos() const;    void
1165      saveDX(std::string fileName) const;
1166    
1167      /**
1168         \brief
1169         writes the object to a file in the VTK file format
1170      */
1171      ESCRIPT_DLL_API
1172      void
1173      saveVTK(std::string fileName) const;
1174    
1175    /**    /**
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 748  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 755  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 763  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 779  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 798  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 823  class Data { Line 1386  class Data {
1386    /**    /**
1387       \brief       \brief
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 and return the single double 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
1399       Perform the given binary operation on all of the data's elements.       Reduce each data-point in this Data object using the given operation. Return a Data
1400       The underlying type of the right hand side (right) determines the final       object with the same number of data-points, but with each data-point containing only
1401       type of *this after the operation. For example if the right hand side       one value - the result of the reduction operation on the corresponding data-point in
1402       is expanded *this will be expanded if necessary.       this Data object
      RHS is a Data object.  
1403    */    */
1404    template <class BinaryFunction>    template <class BinaryFunction>
1405    inline    inline
1406    void    Data
1407    binaryOp(const Data& right,    dp_algorithm(BinaryFunction operation,
1408             BinaryFunction operation);                 double initial_value) const;
1409    
1410    /**    /**
1411       \brief       \brief
1412       Perform the given binary operation on all of the data's elements.       Perform the given binary operation on all of the data's elements.
1413       RHS is a boost::python object.       The underlying type of the right hand side (right) determines the final
1414         type of *this after the operation. For example if the right hand side
1415         is expanded *this will be expanded if necessary.
1416         RHS is a Data object.
1417    */    */
1418    template <class BinaryFunction>    template <class BinaryFunction>
1419    inline    inline
1420    void    void
1421    binaryOp(const boost::python::object& right,    binaryOp(const Data& right,
1422             BinaryFunction operation);             BinaryFunction operation);
1423    
1424    /**    /**
# Line 875  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 897  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 957  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 965  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 973  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 981  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 989  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 997  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 1005  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 1013  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 1042  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 1051  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 1099  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 1215  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  dp_algorithm(const Data& data,  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
              UnaryFunction operation)  
1716  {  {
1717    Data result(0,DataArrayView::ShapeType(),data.getFunctionSpace(),data.isExpanded());    if (isEmpty()) {
1718    if (data.isExpanded()) {      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1719      DataExpanded* dataE=dynamic_cast<DataExpanded*>(data.m_data.get());    }
1720      else if (isExpanded()) {
1721        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1722        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 (data.isTagged()) {      return result;
1728      DataTagged* dataT=dynamic_cast<DataTagged*>(data.m_data.get());    }
1729      DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());    else if (isTagged()) {
1730        DataTagged* dataT=dynamic_cast<DataTagged*>(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 (data.isConstant()) {      DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1735      DataConstant* dataC=dynamic_cast<DataConstant*>(data.m_data.get());      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());
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      // 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    return result;  
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.97  
changed lines
  Added in v.1803

  ViewVC Help
Powered by ViewVC 1.1.26