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

Legend:
Removed from v.97  
changed lines
  Added in v.1857

  ViewVC Help
Powered by ViewVC 1.1.26