/[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 1952 by jfenwick, Thu Oct 30 06:16:00 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      const_Domain_ptr
433    getDomain() const    getDomain() const
434    {    {
435       return getFunctionSpace().getDomain();       return getFunctionSpace().getDomain();
436    }    }
437    
438    
439      /**
440         \brief
441         Return the domain.
442         TODO: For internal use only.   This should be removed.
443      */
444      ESCRIPT_DLL_API
445      inline
446    //   const AbstractDomain&
447      Domain_ptr
448      getDomainPython() const
449      {
450         return getFunctionSpace().getDomainPython();
451      }
452    
453    /**    /**
454       \brief       \brief
455       Return a copy of the domain.       Return a copy of the domain.
456    */    */
457      ESCRIPT_DLL_API
458    const AbstractDomain    const AbstractDomain
459    getCopyOfDomain() const;    getCopyOfDomain() const;
460    
# Line 340  class Data { Line 462  class Data {
462       \brief       \brief
463       Return the rank of the point data.       Return the rank of the point data.
464    */    */
465      ESCRIPT_DLL_API
466    inline    inline
467    int    unsigned int
468    getDataPointRank() const    getDataPointRank() const
469    {    {
470      return m_data->getPointDataView().getRank();      return m_data->getRank();
471    }    }
472    
473    /**    /**
474       \brief       \brief
475         Return the number of data points
476      */
477      ESCRIPT_DLL_API
478      inline
479      int
480      getNumDataPoints() const
481      {
482        return getNumSamples() * getNumDataPointsPerSample();
483      }
484      /**
485         \brief
486       Return the number of samples.       Return the number of samples.
487    */    */
488      ESCRIPT_DLL_API
489    inline    inline
490    int    int
491    getNumSamples() const    getNumSamples() const
# Line 362  class Data { Line 497  class Data {
497       \brief       \brief
498       Return the number of data points per sample.       Return the number of data points per sample.
499    */    */
500      ESCRIPT_DLL_API
501    inline    inline
502    int    int
503    getNumDataPointsPerSample() const    getNumDataPointsPerSample() const
# Line 369  class Data { Line 505  class Data {
505      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
506    }    }
507    
508    
509      /**
510        \brief
511        Return the number of values in the shape for this object.
512      */
513      ESCRIPT_DLL_API
514      int
515      getNoValues() const
516      {
517        return m_data->getNoValues();
518      }
519    
520    
521      /**
522         \brief
523         dumps the object into a netCDF file
524      */
525      ESCRIPT_DLL_API
526      void
527      dump(const std::string fileName) const;
528    /**    /**
529       \brief       \brief
530       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
531       preferred interface but is provided for use by C code.       preferred interface but is provided for use by C code.
532       \param sampleNo - Input - the given sample no.       \param sampleNo - Input - the given sample no.
533    */    */
534      ESCRIPT_DLL_API
535    inline    inline
536    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
537    getSampleData(DataAbstract::ValueType::size_type sampleNo)    getSampleData(DataAbstract::ValueType::size_type sampleNo)
# Line 388  class Data { Line 545  class Data {
545       access data that isn't tagged an exception will be thrown.       access data that isn't tagged an exception will be thrown.
546       \param tag - Input - the tag key.       \param tag - Input - the tag key.
547    */    */
548      ESCRIPT_DLL_API
549    inline    inline
550    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
551    getSampleDataByTag(int tag)    getSampleDataByTag(int tag)
# Line 395  class Data { Line 553  class Data {
553      return m_data->getSampleDataByTag(tag);      return m_data->getSampleDataByTag(tag);
554    }    }
555    
556    //  /**
557    /*     \brief
558         Return a view into the data for the data point specified.
559         NOTE: Construction of the DataArrayView is a relatively expensive
560         operation.
561         \param sampleNo - Input -
562         \param dataPointNo - Input -*/
563    //  */
564    //   ESCRIPT_DLL_API
565    //   inline
566    //   DataArrayView
567    //   getDataPoint(int sampleNo,
568    //                int dataPointNo)
569    //   {
570    //                 return m_data->getDataPoint(sampleNo,dataPointNo);
571    //   }
572    
573    
574    /**    /**
575       \brief       \brief
576       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 579  class Data {
579       \param sampleNo - Input -       \param sampleNo - Input -
580       \param dataPointNo - Input -       \param dataPointNo - Input -
581    */    */
582      ESCRIPT_DLL_API
583      DataTypes::ValueType::const_reference
584      getDataPoint(int sampleNo, int dataPointNo) const;
585    
586    
587      ESCRIPT_DLL_API
588      DataTypes::ValueType::reference
589      getDataPoint(int sampleNo, int dataPointNo);
590    
591    
592    
593      /**
594         \brief
595         Return the offset for the given sample and point within the sample
596      */
597      ESCRIPT_DLL_API
598    inline    inline
599    DataArrayView    DataTypes::ValueType::size_type
600    getDataPoint(int sampleNo,    getDataOffset(int sampleNo,
601                 int dataPointNo)                 int dataPointNo)
602    {    {
603      return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getPointOffset(sampleNo,dataPointNo);
604    }    }
605    
606    /**    /**
607       \brief       \brief
608       Return a reference to the data point shape.       Return a reference to the data point shape.
609    */    */
610    const DataArrayView::ShapeType&    ESCRIPT_DLL_API
611    getDataPointShape() const;    inline
612      const DataTypes::ShapeType&
613      getDataPointShape() const
614      {
615        return m_data->getShape();
616      }
617    
618    /**    /**
619       \brief       \brief
620       Return the data point shape as a tuple of integers.       Return the data point shape as a tuple of integers.
621    */    */
622    boost::python::tuple    ESCRIPT_DLL_API
623      const boost::python::tuple
624    getShapeTuple() const;    getShapeTuple() const;
625    
626    /**    /**
# Line 430  class Data { Line 628  class Data {
628       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
629       data point shape dimensions.       data point shape dimensions.
630    */    */
631      ESCRIPT_DLL_API
632    int    int
633    getDataPointSize() const;    getDataPointSize() const;
634    
# Line 437  class Data { Line 636  class Data {
636       \brief       \brief
637       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
638    */    */
639    DataArrayView::ValueType::size_type    ESCRIPT_DLL_API
640      DataTypes::ValueType::size_type
641    getLength() const;    getLength() const;
642    
643    
644    
645    /**    /**
646       \brief       \brief
647       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag assocciated with name. Implicitly converts this
648       object to type DataTagged. Throws an exception if this object       object to type DataTagged. Throws an exception if this object
649       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
650       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
651       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
652        ==>*
653    */    */
654      ESCRIPT_DLL_API
655    void    void
656    setTaggedValue(int tagKey,    setTaggedValueByName(std::string name,
657                   const boost::python::object& value);                         const boost::python::object& value);
658    
659    /**    /**
660       \brief       \brief
661       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
662       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
663       cannot be converted to a DataTagged object.  
664       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
665       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
666       Note: removed for now - this version not needed, and breaks escript.cpp      ==>*
667    */    */
668    /*    ESCRIPT_DLL_API
669    void    void
670    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
671                   const DataArrayView& value);                   const boost::python::object& value);
672    
673    
674    //  /**
675    //     \brief
676    //     Assign the given value to the tag. Implicitly converts this
677    //     object to type DataTagged if it is constant.
678    //
679    //     \param tagKey - Input - Integer key.
680    //     \param value - Input - Value to associate with given key.
681    //    ==>*
682    //  */
683    //   ESCRIPT_DLL_API
684    //   void
685    //   setTaggedValueFromCPP(int tagKey,
686    //                         const DataArrayView& value);
687    
688      /**
689         \brief
690         Assign the given value to the tag. Implicitly converts this
691         object to type DataTagged if it is constant.
692    
693         \param tagKey - Input - Integer key.
694         \param pointshape - Input - The shape of the value parameter
695         \param value - Input - Value to associate with given key.
696         \param dataOffset - Input - Offset of the begining of the point within the value parameter
697    */    */
698      ESCRIPT_DLL_API
699      void
700      setTaggedValueFromCPP(int tagKey,
701                const DataTypes::ShapeType& pointshape,
702                            const DataTypes::ValueType& value,
703                int dataOffset=0);
704    
705    
706    
707    /**    /**
708      \brief      \brief
709      Copy other Data object into this Data object where mask is positive.      Copy other Data object into this Data object where mask is positive.
710    */    */
711      ESCRIPT_DLL_API
712    void    void
713    copyWithMask(const Data& other,    copyWithMask(const Data& other,
714                 const Data& mask);                 const Data& mask);
# Line 481  class Data { Line 719  class Data {
719    
720    /**    /**
721       \brief       \brief
722         set all values to zero
723         *
724      */
725      ESCRIPT_DLL_API
726      void
727      setToZero();
728    
729      /**
730         \brief
731       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
732       the result as a Data object.       the result as a Data object.
733         *
734    */    */
735      ESCRIPT_DLL_API
736    Data    Data
737    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
738    /**    /**
739       \brief       \brief
740       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
741       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.
742         *
743    */    */
744      ESCRIPT_DLL_API
745    Data    Data
746    gradOn(const FunctionSpace& functionspace) const;    gradOn(const FunctionSpace& functionspace) const;
747    
748      ESCRIPT_DLL_API
749    Data    Data
750    grad() const;    grad() const;
751    
752    /**    /**
753       \brief       \brief
754       Calculate the integral over the function space domain.       Calculate the integral over the function space domain.
755         *
756    */    */
757      ESCRIPT_DLL_API
758    boost::python::numeric::array    boost::python::numeric::array
759    integrate() const;    integrate() const;
760    
761    /**    /**
762       \brief       \brief
763         Returns 1./ Data object
764         *
765      */
766      ESCRIPT_DLL_API
767      Data
768      oneOver() const;
769      /**
770         \brief
771       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.
772         *
773    */    */
774      ESCRIPT_DLL_API
775    Data    Data
776    wherePositive() const;    wherePositive() const;
777    
778    /**    /**
779       \brief       \brief
780       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.
781         *
782    */    */
783      ESCRIPT_DLL_API
784    Data    Data
785    whereNegative() const;    whereNegative() const;
786    
787    /**    /**
788       \brief       \brief
789       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.
790         *
791    */    */
792      ESCRIPT_DLL_API
793    Data    Data
794    whereNonNegative() const;    whereNonNegative() const;
795    
796    /**    /**
797       \brief       \brief
798       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.
799         *
800    */    */
801      ESCRIPT_DLL_API
802    Data    Data
803    whereNonPositive() const;    whereNonPositive() const;
804    
805    /**    /**
806       \brief       \brief
807       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.
808         *
809    */    */
810      ESCRIPT_DLL_API
811    Data    Data
812    whereZero() const;    whereZero(double tol=0.0) const;
813    
814    /**    /**
815       \brief       \brief
816       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.
817         *
818      */
819      ESCRIPT_DLL_API
820      Data
821      whereNonZero(double tol=0.0) const;
822    
823      /**
824         \brief
825         Return the maximum absolute value of this Data object.
826         For Data which contain no samples (or tagged Data for which no tags in use have a value)
827         zero is returned.
828         *
829      */
830      ESCRIPT_DLL_API
831      double
832      Lsup() const;
833    
834      /**
835         \brief
836         Return the maximum value of this Data object.
837         For Data which contain no samples (or tagged Data for which no tags in use have a value)
838         a large negative value is returned.
839      */
840      ESCRIPT_DLL_API
841      double
842      sup() const;
843    
844      /**
845         \brief
846         Return the minimum value of this Data object.
847         For Data which contain no samples (or tagged Data for which no tags in use have a value)
848         a large positive value is returned.
849         *
850      */
851      ESCRIPT_DLL_API
852      double
853      inf() const;
854    
855      /**
856         \brief
857         Return the absolute value of each data point of this Data object.
858         *
859      */
860      ESCRIPT_DLL_API
861      Data
862      abs() const;
863    
864      /**
865         \brief
866         Return the maximum value of each data point of this Data object.
867         *
868      */
869      ESCRIPT_DLL_API
870      Data
871      maxval() const;
872    
873      /**
874         \brief
875         Return the minimum value of each data point of this Data object.
876         *
877    */    */
878      ESCRIPT_DLL_API
879    Data    Data
880    whereNonZero() const;    minval() const;
881    
882      /**
883         \brief
884         Return the (sample number, data-point number) of the data point with
885         the minimum value in this Data object.
886      */
887      ESCRIPT_DLL_API
888      const boost::python::tuple
889      minGlobalDataPoint() const;
890    
891      ESCRIPT_DLL_API
892      void
893      calc_minGlobalDataPoint(int& ProcNo,  int& DataPointNo) const;
894      /**
895         \brief
896         Return the sign of each data point of this Data object.
897         -1 for negative values, zero for zero values, 1 for positive values.
898         *
899      */
900      ESCRIPT_DLL_API
901      Data
902      sign() const;
903    
904      /**
905         \brief
906         Return the symmetric part of a matrix which is half the matrix plus its transpose.
907         *
908      */
909      ESCRIPT_DLL_API
910      Data
911      symmetric() const;
912    
913      /**
914         \brief
915         Return the nonsymmetric part of a matrix which is half the matrix minus its transpose.
916         *
917      */
918      ESCRIPT_DLL_API
919      Data
920      nonsymmetric() const;
921    
922      /**
923         \brief
924         Return the trace of a matrix
925         *
926      */
927      ESCRIPT_DLL_API
928      Data
929      trace(int axis_offset) const;
930    
931      /**
932         \brief
933         Transpose each data point of this Data object around the given axis.
934         *
935      */
936      ESCRIPT_DLL_API
937      Data
938      transpose(int axis_offset) const;
939    
940      /**
941         \brief
942         Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.
943         Currently this function is restricted to rank 2, square shape, and dimension 3.
944         *
945      */
946      ESCRIPT_DLL_API
947      Data
948      eigenvalues() const;
949    
950      /**
951         \brief
952         Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.
953         the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than
954         tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the
955         first non-zero entry is positive.
956         Currently this function is restricted to rank 2, square shape, and dimension 3
957         *
958      */
959      ESCRIPT_DLL_API
960      const boost::python::tuple
961      eigenvalues_and_eigenvectors(const double tol=1.e-12) const;
962    
963      /**
964         \brief
965         swaps the components axis0 and axis1
966         *
967      */
968      ESCRIPT_DLL_API
969      Data
970      swapaxes(const int axis0, const int axis1) const;
971    
972      /**
973         \brief
974         Return the error function erf of each data point of this Data object.
975         *
976      */
977      ESCRIPT_DLL_API
978      Data
979      erf() const;
980    
981    /**    /**
982       \brief       \brief
983       Return the sin of each data point of this Data object.       Return the sin of each data point of this Data object.
984         *
985    */    */
986      ESCRIPT_DLL_API
987    Data    Data
988    sin() const;    sin() const;
989    
990    /**    /**
991       \brief       \brief
992       Return the cos of each data point of this Data object.       Return the cos of each data point of this Data object.
993         *
994    */    */
995      ESCRIPT_DLL_API
996    Data    Data
997    cos() const;    cos() const;
998    
999    /**    /**
1000       \brief       \brief
1001       Return the tan of each data point of this Data object.       Return the tan of each data point of this Data object.
1002         *
1003    */    */
1004      ESCRIPT_DLL_API
1005    Data    Data
1006    tan() const;    tan() const;
1007    
1008    /**    /**
1009       \brief       \brief
1010       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.
1011         *
1012    */    */
1013      ESCRIPT_DLL_API
1014    Data    Data
1015    log() const;    asin() const;
1016    
1017    /**    /**
1018       \brief       \brief
1019       Return the natural log of each data point of this Data object.       Return the acos of each data point of this Data object.
1020         *
1021    */    */
1022      ESCRIPT_DLL_API
1023    Data    Data
1024    ln() const;    acos() const;
1025    
1026    /**    /**
1027       \brief       \brief
1028       Return the maximum absolute value of this Data object.       Return the atan of each data point of this Data object.
1029         *
1030    */    */
1031    double    ESCRIPT_DLL_API
1032    Lsup() const;    Data
1033      atan() const;
1034    
1035    /**    /**
1036       \brief       \brief
1037       Return the maximum value of this Data object.       Return the sinh of each data point of this Data object.
1038         *
1039    */    */
1040    double    ESCRIPT_DLL_API
1041    sup() const;    Data
1042      sinh() const;
1043    
1044    /**    /**
1045       \brief       \brief
1046       Return the minimum value of this Data object.       Return the cosh of each data point of this Data object.
1047         *
1048    */    */
1049    double    ESCRIPT_DLL_API
1050    inf() const;    Data
1051      cosh() const;
1052    
1053    /**    /**
1054       \brief       \brief
1055       Return the absolute value of each data point of this Data object.       Return the tanh of each data point of this Data object.
1056         *
1057    */    */
1058      ESCRIPT_DLL_API
1059    Data    Data
1060    abs() const;    tanh() const;
1061    
1062    /**    /**
1063       \brief       \brief
1064       Return the maximum value of each data point of this Data object.       Return the asinh of each data point of this Data object.
1065         *
1066    */    */
1067      ESCRIPT_DLL_API
1068    Data    Data
1069    maxval() const;    asinh() const;
1070    
1071    /**    /**
1072       \brief       \brief
1073       Return the minimum value of each data point of this Data object.       Return the acosh of each data point of this Data object.
1074         *
1075    */    */
1076      ESCRIPT_DLL_API
1077    Data    Data
1078    minval() const;    acosh() const;
1079    
1080    /**    /**
1081       \brief       \brief
1082       Return the length of each data point of this Data object.       Return the atanh of each data point of this Data object.
1083       sqrt(sum(A[i,j,k,l]^2))       *
1084    */    */
1085      ESCRIPT_DLL_API
1086    Data    Data
1087    length() const;    atanh() const;
1088    
1089    /**    /**
1090       \brief       \brief
1091       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.
1092       -1 for negative values, zero for zero values, 1 for positive values.       *
1093    */    */
1094      ESCRIPT_DLL_API
1095    Data    Data
1096    sign() const;    log10() const;
1097    
1098    /**    /**
1099      \transpose       \brief
1100      Transpose each data point of this Data object around the given axis.       Return the natural log of each data point of this Data object.
1101         *
1102    */    */
1103      ESCRIPT_DLL_API
1104    Data    Data
1105    transpose(int axis) const;    log() const;
1106    
1107    /**    /**
1108      \trace       \brief
1109      Calculate the trace of each data point of this Data object.       Return the exponential function of each data point of this Data object.
1110      sum(A[i,i,i,i])       *
1111    */    */
1112      ESCRIPT_DLL_API
1113    Data    Data
1114    trace() const;    exp() const;
1115    
1116    /**    /**
1117      \exp       \brief
1118      Return the exponential function of each data point of this Data object.       Return the square root of each data point of this Data object.
1119         *
1120    */    */
1121      ESCRIPT_DLL_API
1122    Data    Data
1123    exp() const;    sqrt() const;
1124    
1125    /**    /**
1126      \sqrt       \brief
1127      Return the square root of each data point of this Data object.       Return the negation of each data point of this Data object.
1128         *
1129    */    */
1130      ESCRIPT_DLL_API
1131    Data    Data
1132    sqrt() const;    neg() const;
1133    
1134      /**
1135         \brief
1136         Return the identity of each data point of this Data object.
1137         Simply returns this object unmodified.
1138         *
1139      */
1140      ESCRIPT_DLL_API
1141      Data
1142      pos() const;
1143    
1144    /**    /**
1145       \brief       \brief
1146       Return the given power of each data point of this Data object.       Return the given power of each data point of this Data object.
1147    
1148         \param right Input - the power to raise the object to.
1149         *
1150    */    */
1151      ESCRIPT_DLL_API
1152    Data    Data
1153    powD(const Data& right) const;    powD(const Data& right) const;
1154    
1155      /**
1156         \brief
1157         Return the given power of each data point of this boost python object.
1158    
1159         \param right Input - the power to raise the object to.
1160         *
1161       */
1162      ESCRIPT_DLL_API
1163    Data    Data
1164    powO(const boost::python::object& right) const;    powO(const boost::python::object& right) const;
1165    
1166    /**    /**
1167      \brief       \brief
1168      Return the negation of each data point of this Data object.       Return the given power of each data point of this boost python object.
1169    */  
1170         \param left Input - the bases
1171         *
1172       */
1173    
1174      ESCRIPT_DLL_API
1175    Data    Data
1176    neg() const;    rpowO(const boost::python::object& left) const;
1177    
1178    /**    /**
1179      \brief       \brief
1180      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.  
1181    */    */
1182    Data    ESCRIPT_DLL_API
1183    pos() const;    void
1184      saveDX(std::string fileName) const;
1185    
1186      /**
1187         \brief
1188         writes the object to a file in the VTK file format
1189      */
1190      ESCRIPT_DLL_API
1191      void
1192      saveVTK(std::string fileName) const;
1193    
1194    /**    /**
1195       \brief       \brief
1196       Overloaded operator +=       Overloaded operator +=
1197       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1198         *
1199    */    */
1200      ESCRIPT_DLL_API
1201    Data& operator+=(const Data& right);    Data& operator+=(const Data& right);
1202      ESCRIPT_DLL_API
1203    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1204    
1205      ESCRIPT_DLL_API
1206      Data& operator=(const Data& other);
1207    
1208    /**    /**
1209       \brief       \brief
1210       Overloaded operator -=       Overloaded operator -=
1211       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1212         *
1213    */    */
1214      ESCRIPT_DLL_API
1215    Data& operator-=(const Data& right);    Data& operator-=(const Data& right);
1216      ESCRIPT_DLL_API
1217    Data& operator-=(const boost::python::object& right);    Data& operator-=(const boost::python::object& right);
1218    
1219   /**   /**
1220       \brief       \brief
1221       Overloaded operator *=       Overloaded operator *=
1222       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1223         *
1224    */    */
1225      ESCRIPT_DLL_API
1226    Data& operator*=(const Data& right);    Data& operator*=(const Data& right);
1227      ESCRIPT_DLL_API
1228    Data& operator*=(const boost::python::object& right);    Data& operator*=(const boost::python::object& right);
1229    
1230   /**   /**
1231       \brief       \brief
1232       Overloaded operator /=       Overloaded operator /=
1233       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1234         *
1235    */    */
1236      ESCRIPT_DLL_API
1237    Data& operator/=(const Data& right);    Data& operator/=(const Data& right);
1238      ESCRIPT_DLL_API
1239    Data& operator/=(const boost::python::object& right);    Data& operator/=(const boost::python::object& right);
1240    
1241    /**    /**
1242       \brief       \brief
1243       Returns true if this can be interpolated to functionspace.       Returns true if this can be interpolated to functionspace.
1244    */    */
1245      ESCRIPT_DLL_API
1246    bool    bool
1247    probeInterpolation(const FunctionSpace& functionspace) const;    probeInterpolation(const FunctionSpace& functionspace) const;
1248    
# Line 748  class Data { Line 1261  class Data {
1261       \param key - Input - python slice tuple specifying       \param key - Input - python slice tuple specifying
1262       slice to return.       slice to return.
1263    */    */
1264      ESCRIPT_DLL_API
1265    Data    Data
1266    getItem(const boost::python::object& key) const;    getItem(const boost::python::object& key) const;
1267    
# Line 755  class Data { Line 1269  class Data {
1269       \brief       \brief
1270       Copies slice from value into this Data object.       Copies slice from value into this Data object.
1271    
      \description  
1272       Implements the [] set operator in python.       Implements the [] set operator in python.
1273       Calls setSlice.       Calls setSlice.
1274    
# Line 763  class Data { Line 1276  class Data {
1276       slice to copy from value.       slice to copy from value.
1277       \param value - Input - Data object to copy from.       \param value - Input - Data object to copy from.
1278    */    */
1279      ESCRIPT_DLL_API
1280    void    void
1281    setItemD(const boost::python::object& key,    setItemD(const boost::python::object& key,
1282             const Data& value);             const Data& value);
1283    
1284      ESCRIPT_DLL_API
1285    void    void
1286    setItemO(const boost::python::object& key,    setItemO(const boost::python::object& key,
1287             const boost::python::object& value);             const boost::python::object& value);
# Line 779  class Data { Line 1294  class Data {
1294       this Data object.       this Data object.
1295    */    */
1296    template <class UnaryFunction>    template <class UnaryFunction>
1297      ESCRIPT_DLL_API
1298    inline    inline
1299    void    void
1300    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1301    
1302    /**    /**
1303       \brief       \brief
1304       Return a Data object containing the specified slice of       Return a Data object containing the specified slice of
1305       this Data object.       this Data object.
1306       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1307         *
1308    */    */
1309      ESCRIPT_DLL_API
1310    Data    Data
1311    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataTypes::RegionType& region) const;
1312    
1313    /**    /**
1314       \brief       \brief
# Line 798  class Data { Line 1316  class Data {
1316       Data object.       Data object.
1317       \param value - Input - Data to copy from.       \param value - Input - Data to copy from.
1318       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1319         *
1320    */    */
1321      ESCRIPT_DLL_API
1322    void    void
1323    setSlice(const Data& value,    setSlice(const Data& value,
1324             const DataArrayView::RegionType& region);             const DataTypes::RegionType& region);
1325    
1326      /**
1327         \brief
1328         print the data values to stdout. Used for debugging
1329      */
1330      ESCRIPT_DLL_API
1331      void
1332            print(void);
1333    
1334      /**
1335         \brief
1336         return the MPI rank number of the local data
1337                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1338                     is returned
1339      */
1340      ESCRIPT_DLL_API
1341            int
1342            get_MPIRank(void) const;
1343    
1344      /**
1345         \brief
1346         return the MPI rank number of the local data
1347                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1348                     is returned
1349      */
1350      ESCRIPT_DLL_API
1351            int
1352            get_MPISize(void) const;
1353    
1354      /**
1355         \brief
1356         return the MPI rank number of the local data
1357                     MPI_COMM_WORLD is assumed and returned.
1358      */
1359      ESCRIPT_DLL_API
1360            MPI_Comm
1361            get_MPIComm(void) const;
1362    
1363      /**
1364         \brief
1365         return the object produced by the factory, which is a DataConstant or DataExpanded
1366        TODO Ownership of this object should be explained in doco.
1367      */
1368      ESCRIPT_DLL_API
1369            DataAbstract*
1370            borrowData(void) const;
1371    
1372    
1373      /**
1374         \brief
1375         Return a pointer to the beginning of the datapoint at the specified offset.
1376         TODO Eventually these should be inlined.
1377         \param i - position(offset) in the underlying datastructure
1378      */
1379      ESCRIPT_DLL_API
1380            DataTypes::ValueType::const_reference
1381            getDataAtOffset(DataTypes::ValueType::size_type i) const;
1382    
1383    
1384      ESCRIPT_DLL_API
1385            DataTypes::ValueType::reference
1386            getDataAtOffset(DataTypes::ValueType::size_type i);
1387    
1388   protected:   protected:
1389    
# Line 823  class Data { Line 1405  class Data {
1405    /**    /**
1406       \brief       \brief
1407       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
1408       this Data object and return the single double value result.       this Data object according to the given function and return the single value result.
1409    */    */
1410    template <class UnaryFunction>    template <class BinaryFunction>
1411    inline    inline
1412    double    double
1413    algorithm(UnaryFunction operation) const;    algorithm(BinaryFunction operation,
1414                double initial_value) const;
1415    
1416    /**    /**
1417       \brief       \brief
1418       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
1419       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
1420       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
1421       is expanded *this will be expanded if necessary.       this Data object
      RHS is a Data object.  
1422    */    */
1423    template <class BinaryFunction>    template <class BinaryFunction>
1424    inline    inline
1425    void    Data
1426    binaryOp(const Data& right,    dp_algorithm(BinaryFunction operation,
1427             BinaryFunction operation);                 double initial_value) const;
1428    
1429    /**    /**
1430       \brief       \brief
1431       Perform the given binary operation on all of the data's elements.       Perform the given binary operation on all of the data's elements.
1432       RHS is a boost::python object.       The underlying type of the right hand side (right) determines the final
1433         type of *this after the operation. For example if the right hand side
1434         is expanded *this will be expanded if necessary.
1435         RHS is a Data object.
1436    */    */
1437    template <class BinaryFunction>    template <class BinaryFunction>
1438    inline    inline
1439    void    void
1440    binaryOp(const boost::python::object& right,    binaryOp(const Data& right,
1441             BinaryFunction operation);             BinaryFunction operation);
1442    
1443    /**    /**
# Line 875  class Data { Line 1460  class Data {
1460       \brief       \brief
1461       Construct a Data object of the appropriate type.       Construct a Data object of the appropriate type.
1462    */    */
1463    template <class IValueType>  
1464    void    void
1465    initialise(const IValueType& value,    initialise(const DataTypes::ValueType& value,
1466             const DataTypes::ShapeType& shape,
1467               const FunctionSpace& what,               const FunctionSpace& what,
1468               bool expanded);               bool expanded);
1469    
   /**  
      \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.  
   */  
1470    void    void
1471    reshapeDataPoint(const DataArrayView::ShapeType& shape);    initialise(const boost::python::numeric::array& value,
1472                     const FunctionSpace& what,
1473                     bool expanded);
1474    
1475      //
1476      // flag to protect the data object against any update
1477      bool m_protected;
1478    
1479    //    //
1480    // pointer to the actual data object    // pointer to the actual data object
1481    boost::shared_ptr<DataAbstract> m_data;  //   boost::shared_ptr<DataAbstract> m_data;
1482      DataAbstract_ptr m_data;
1483    
1484  };  };
1485    
1486  template <class IValueType>  
1487  void  
1488  Data::initialise(const IValueType& value,  /**
1489                   const FunctionSpace& what,     Modify a filename for MPI parallel output to multiple files
1490                   bool expanded)  */
1491  {  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;  
   }  
 }  
1492    
1493  /**  /**
1494     Binary Data object operators.     Binary Data object operators.
1495  */  */
1496    inline double rpow(double x,double y)
1497    {
1498        return pow(y,x);
1499    }
1500    
1501  /**  /**
1502    \brief    \brief
1503    Operator+    Operator+
1504    Takes two Data objects.    Takes two Data objects.
1505  */  */
1506  Data operator+(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1507    
1508  /**  /**
1509    \brief    \brief
1510    Operator-    Operator-
1511    Takes two Data objects.    Takes two Data objects.
1512  */  */
1513  Data operator-(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1514    
1515  /**  /**
1516    \brief    \brief
1517    Operator*    Operator*
1518    Takes two Data objects.    Takes two Data objects.
1519  */  */
1520  Data operator*(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1521    
1522  /**  /**
1523    \brief    \brief
1524    Operator/    Operator/
1525    Takes two Data objects.    Takes two Data objects.
1526  */  */
1527  Data operator/(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1528    
1529  /**  /**
1530    \brief    \brief
# Line 957  Data operator/(const Data& left, const D Line 1532  Data operator/(const Data& left, const D
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 965  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 973  Data operator-(const Data& left, const b Line 1548  Data operator-(const Data& left, const b
1548    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1549    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1550  */  */
1551  Data operator*(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const boost::python::object& right);
1552    
1553  /**  /**
1554    \brief    \brief
# Line 981  Data operator*(const Data& left, const b Line 1556  Data operator*(const Data& left, const b
1556    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1557    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1558  */  */
1559  Data operator/(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const boost::python::object& right);
1560    
1561  /**  /**
1562    \brief    \brief
# Line 989  Data operator/(const Data& left, const b Line 1564  Data operator/(const Data& left, const b
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 997  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    \brief    \brief
# Line 1005  Data operator-(const boost::python::obje Line 1580  Data operator-(const boost::python::obje
1580    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1581    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1582  */  */
1583  Data operator*(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const boost::python::object& left, const Data& right);
1584    
1585  /**  /**
1586    \brief    \brief
# Line 1013  Data operator*(const boost::python::obje Line 1588  Data operator*(const boost::python::obje
1588    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1589    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1590  */  */
1591  Data operator/(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1592    
1593    
1594    
1595  /**  /**
1596    \brief    \brief
1597    Output operator    Output operator
1598  */  */
1599  std::ostream& operator<<(std::ostream& o, const Data& data);  ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1600    
1601  /**  /**
1602    \brief    \brief
1603    Return true if operands are equivalent, else return false.    Compute a tensor product of two Data objects
1604    NB: this operator does very little at this point, and isn't to    \param arg0 - Input - Data object
1605    be relied on. Requires further implementation.    \param arg1 - Input - Data object
1606      \param axis_offset - Input - axis offset
1607      \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1608  */  */
1609  //bool operator==(const Data& left, const Data& right);  ESCRIPT_DLL_API
1610    Data
1611    C_GeneralTensorProduct(Data& arg0,
1612                         Data& arg1,
1613                         int axis_offset=0,
1614                         int transpose=0);
1615    
1616    
1617    
1618    // /**
1619    /*  \brief
1620      Return true if operands are equivalent, else return false.
1621      NB: this operator does very little at this point, and isn't to
1622      be relied on. Requires further implementation.*/
1623    //*/
1624    // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1625    
1626  /**  /**
1627    \brief    \brief
# Line 1042  Data::binaryOp(const Data& right, Line 1636  Data::binaryOp(const Data& right,
1636  {  {
1637     //     //
1638     // 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
1639     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1640       reshapeDataPoint(right.getPointDataView().getShape());       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1641     }     }
1642     //     //
1643     // initially make the temporary a shallow copy     // initially make the temporary a shallow copy
# Line 1051  Data::binaryOp(const Data& right, Line 1645  Data::binaryOp(const Data& right,
1645     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1646       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1647         //         //
1648         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1649         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1650       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1651         //         //
# Line 1099  Data::binaryOp(const Data& right, Line 1693  Data::binaryOp(const Data& right,
1693    
1694  /**  /**
1695    \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  
1696    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.
1697    Given operation combines each element of each data point, thus argument    Given operation combines each element of each data point, thus argument
1698    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.
1699    Calls escript::algorithm.    Calls escript::algorithm.
1700  */  */
1701  template <class UnaryFunction>  template <class BinaryFunction>
1702  inline  inline
1703  double  double
1704  Data::algorithm(UnaryFunction operation) const  Data::algorithm(BinaryFunction operation, double initial_value) const
1705  {  {
1706    if (isExpanded()) {    if (isExpanded()) {
1707      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1708      EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");      EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1709      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1710    } else if (isTagged()) {    } else if (isTagged()) {
1711      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1712      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1713      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1714    } else if (isConstant()) {    } else if (isConstant()) {
1715      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1716      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1717      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1718      } else if (isEmpty()) {
1719        throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1720    }    }
1721    return 0;    return 0;
1722  }  }
# Line 1215  Data::algorithm(UnaryFunction operation) Line 1725  Data::algorithm(UnaryFunction operation)
1725    \brief    \brief
1726    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.
1727    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1728    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
1729    rank 0 Data object.    rank 0 Data object.
1730    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1731  */  */
1732  template <class UnaryFunction>  template <class BinaryFunction>
1733  inline  inline
1734  Data  Data
1735  dp_algorithm(const Data& data,  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
              UnaryFunction operation)  
1736  {  {
1737    Data result(0,DataArrayView::ShapeType(),data.getFunctionSpace(),data.isExpanded());    if (isEmpty()) {
1738    if (data.isExpanded()) {      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1739      DataExpanded* dataE=dynamic_cast<DataExpanded*>(data.m_data.get());    }
1740      else if (isExpanded()) {
1741        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1742        DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1743      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1744      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1745      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1746      escript::dp_algorithm(*dataE,*resultE,operation);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1747    } else if (data.isTagged()) {      return result;
1748      DataTagged* dataT=dynamic_cast<DataTagged*>(data.m_data.get());    }
1749      DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());    else if (isTagged()) {
1750        DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
1751      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1752      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      DataTypes::ValueType defval(1);
1753      escript::dp_algorithm(*dataT,*resultT,operation);      defval[0]=0;
1754    } else if (data.isConstant()) {      DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1755      DataConstant* dataC=dynamic_cast<DataConstant*>(data.m_data.get());      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1756        return Data(resultT);   // note: the Data object now owns the resultT pointer
1757      }
1758      else if (isConstant()) {
1759        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1760        DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1761      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1762      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1763      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1764      escript::dp_algorithm(*dataC,*resultC,operation);      escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1765        return result;
1766      }
1767      Data falseRetVal; // to keep compiler quiet
1768      return falseRetVal;
1769    }
1770    
1771    /**
1772      \brief
1773      Compute a tensor operation with two Data objects
1774      \param arg0 - Input - Data object
1775      \param arg1 - Input - Data object
1776      \param operation - Input - Binary op functor
1777    */
1778    template <typename BinaryFunction>
1779    inline
1780    Data
1781    C_TensorBinaryOperation(Data const &arg_0,
1782                            Data const &arg_1,
1783                            BinaryFunction operation)
1784    {
1785      if (arg_0.isEmpty() || arg_1.isEmpty())
1786      {
1787         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1788    }    }
1789    return result;    // Interpolate if necessary and find an appropriate function space
1790      Data arg_0_Z, arg_1_Z;
1791      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1792        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1793          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1794          arg_1_Z = Data(arg_1);
1795        }
1796        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1797          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1798          arg_0_Z =Data(arg_0);
1799        }
1800        else {
1801          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1802        }
1803      } else {
1804          arg_0_Z = Data(arg_0);
1805          arg_1_Z = Data(arg_1);
1806      }
1807      // Get rank and shape of inputs
1808      int rank0 = arg_0_Z.getDataPointRank();
1809      int rank1 = arg_1_Z.getDataPointRank();
1810      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1811      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1812      int size0 = arg_0_Z.getDataPointSize();
1813      int size1 = arg_1_Z.getDataPointSize();
1814    
1815      // Declare output Data object
1816      Data res;
1817    
1818      if (shape0 == shape1) {
1819    
1820        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1821          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1822    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1823          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1824          double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1825          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1826          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1827          double *ptr_2 = &(res.getDataAtOffset(0));
1828    
1829          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1830        }
1831        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1832    
1833          // Prepare the DataConstant input
1834          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1835    
1836          // Borrow DataTagged input from Data object
1837          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1838    
1839          // Prepare a DataTagged output 2
1840          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1841          res.tag();
1842          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1843    
1844          // Prepare offset into DataConstant
1845          int offset_0 = tmp_0->getPointOffset(0,0);
1846          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1847          // Get the views
1848    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1849    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1850    //       // Get the pointers to the actual data
1851    //       double *ptr_1 = &((view_1.getData())[0]);
1852    //       double *ptr_2 = &((view_2.getData())[0]);
1853    
1854          // Get the pointers to the actual data
1855          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1856          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1857    
1858          // Compute a result for the default
1859          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1860          // Compute a result for each tag
1861          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1862          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1863          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1864            tmp_2->addTag(i->first);
1865    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1866            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1867            double *ptr_1 = &view_1.getData(0);
1868            double *ptr_2 = &view_2.getData(0);*/
1869            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1870            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1871    
1872            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1873          }
1874    
1875        }
1876        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1877    
1878          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1879          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1880          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1881          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1882    
1883          int sampleNo_1,dataPointNo_1;
1884          int numSamples_1 = arg_1_Z.getNumSamples();
1885          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1886          int offset_0 = tmp_0->getPointOffset(0,0);
1887          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1888          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1889            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1890              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1891              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1892    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1893    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1894    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1895    
1896              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1897              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1898              double *ptr_2 = &(res.getDataAtOffset(offset_2));
1899              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1900            }
1901          }
1902    
1903        }
1904        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1905    
1906          // Borrow DataTagged input from Data object
1907          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1908    
1909          // Prepare the DataConstant input
1910          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1911    
1912          // Prepare a DataTagged output 2
1913          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1914          res.tag();
1915          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1916    
1917          // Prepare offset into DataConstant
1918          int offset_1 = tmp_1->getPointOffset(0,0);
1919    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1920          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1921          // Get the views
1922    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1923    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1924    //       // Get the pointers to the actual data
1925    //       double *ptr_0 = &((view_0.getData())[0]);
1926    //       double *ptr_2 = &((view_2.getData())[0]);
1927          // Get the pointers to the actual data
1928          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1929          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1930          // Compute a result for the default
1931          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1932          // Compute a result for each tag
1933          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1934          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1935          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1936            tmp_2->addTag(i->first);
1937    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1938    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1939    //         double *ptr_0 = &view_0.getData(0);
1940    //         double *ptr_2 = &view_2.getData(0);
1941            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1942            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1943            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1944          }
1945    
1946        }
1947        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1948    
1949          // Borrow DataTagged input from Data object
1950          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1951    
1952          // Borrow DataTagged input from Data object
1953          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1954    
1955          // Prepare a DataTagged output 2
1956          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1957          res.tag();        // DataTagged output
1958          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1959    
1960    //       // Get the views
1961    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1962    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1963    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1964    //       // Get the pointers to the actual data
1965    //       double *ptr_0 = &((view_0.getData())[0]);
1966    //       double *ptr_1 = &((view_1.getData())[0]);
1967    //       double *ptr_2 = &((view_2.getData())[0]);
1968    
1969          // Get the pointers to the actual data
1970          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1971          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1972          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1973    
1974          // Compute a result for the default
1975          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1976          // Merge the tags
1977          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1978          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1979          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1980          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1981            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
1982          }
1983          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1984            tmp_2->addTag(i->first);
1985          }
1986          // Compute a result for each tag
1987          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1988          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1989    
1990    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1991    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1992    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1993    //         double *ptr_0 = &view_0.getData(0);
1994    //         double *ptr_1 = &view_1.getData(0);
1995    //         double *ptr_2 = &view_2.getData(0);
1996    
1997            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1998            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1999            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2000    
2001            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2002          }
2003    
2004        }
2005        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2006    
2007          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2008          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2009          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2010          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2011          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2012    
2013          int sampleNo_0,dataPointNo_0;
2014          int numSamples_0 = arg_0_Z.getNumSamples();
2015          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2016          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2017          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2018            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2019            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2020            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2021              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2022              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2023    
2024    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2025    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2026              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2027              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2028    
2029    
2030              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2031            }
2032          }
2033    
2034        }
2035        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2036    
2037          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2038          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2039          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2040          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2041    
2042          int sampleNo_0,dataPointNo_0;
2043          int numSamples_0 = arg_0_Z.getNumSamples();
2044          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2045          int offset_1 = tmp_1->getPointOffset(0,0);
2046          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2047          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2048            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2049              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2050              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2051    
2052    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2053    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2054    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2055    
2056              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2057              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2058              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2059    
2060    
2061              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2062            }
2063          }
2064    
2065        }
2066        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2067    
2068          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2069          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2070          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2071          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2072          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2073    
2074          int sampleNo_0,dataPointNo_0;
2075          int numSamples_0 = arg_0_Z.getNumSamples();
2076          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2077          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2078          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2079            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2080            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2081            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2082              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2083              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2084              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2085              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2086              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2087            }
2088          }
2089    
2090        }
2091        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2092    
2093          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2094          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2095          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2096          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2097          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2098    
2099          int sampleNo_0,dataPointNo_0;
2100          int numSamples_0 = arg_0_Z.getNumSamples();
2101          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2102          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2103          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2104            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2105              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2106              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2107              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2108              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2109              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2110              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2111              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2112            }
2113          }
2114    
2115        }
2116        else {
2117          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2118        }
2119    
2120      } else if (0 == rank0) {
2121    
2122        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2123          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2124          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2125          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2126          double *ptr_2 = &(res.getDataAtOffset(0));
2127          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2128        }
2129        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2130    
2131          // Prepare the DataConstant input
2132          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2133    
2134          // Borrow DataTagged input from Data object
2135          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2136    
2137          // Prepare a DataTagged output 2
2138          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2139          res.tag();
2140          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2141    
2142          // Prepare offset into DataConstant
2143          int offset_0 = tmp_0->getPointOffset(0,0);
2144          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2145          // Get the views
2146    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2147    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2148    //       // Get the pointers to the actual data
2149    //       double *ptr_1 = &((view_1.getData())[0]);
2150    //       double *ptr_2 = &((view_2.getData())[0]);
2151           double *ptr_1 = &(tmp_1->getDefaultValue(0));
2152           double *ptr_2 = &(tmp_2->getDefaultValue(0));
2153    
2154          // Compute a result for the default
2155          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2156          // Compute a result for each tag
2157          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2158          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2159          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2160            tmp_2->addTag(i->first);
2161    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2162    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2163    //         double *ptr_1 = &view_1.getData(0);
2164    //         double *ptr_2 = &view_2.getData(0);
2165            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2166            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2167            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2168          }
2169    
2170        }
2171        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2172    
2173          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2174          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2175          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2176          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2177    
2178          int sampleNo_1,dataPointNo_1;
2179          int numSamples_1 = arg_1_Z.getNumSamples();
2180          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2181          int offset_0 = tmp_0->getPointOffset(0,0);
2182          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2183          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2184            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2185              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2186              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2187              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2188              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2189              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2190              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2191    
2192            }
2193          }
2194    
2195        }
2196        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2197    
2198          // Borrow DataTagged input from Data object
2199          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2200    
2201          // Prepare the DataConstant input
2202          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2203    
2204          // Prepare a DataTagged output 2
2205          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2206          res.tag();
2207          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2208    
2209          // Prepare offset into DataConstant
2210          int offset_1 = tmp_1->getPointOffset(0,0);
2211    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2212          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2213          // Get the views
2214    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2215          DataArrayView view_2 = tmp_2->getDefaultValue();
2216          // Get the pointers to the actual data
2217          double *ptr_0 = &((view_0.getData())[0]);
2218          double *ptr_2 = &((view_2.getData())[0]);*/
2219    
2220          // Get the pointers to the actual data
2221          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2222          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2223    
2224    
2225          // Compute a result for the default
2226          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2227          // Compute a result for each tag
2228          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2229          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2230          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2231            tmp_2->addTag(i->first);
2232    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2233            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2234            double *ptr_0 = &view_0.getData(0);
2235            double *ptr_2 = &view_2.getData(0);*/
2236            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2237            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2238    
2239            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2240          }
2241    
2242        }
2243        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2244    
2245          // Borrow DataTagged input from Data object
2246          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2247    
2248          // Borrow DataTagged input from Data object
2249          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2250    
2251          // Prepare a DataTagged output 2
2252          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2253          res.tag();        // DataTagged output
2254          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2255    
2256          // Get the views
2257    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2258          DataArrayView view_1 = tmp_1->getDefaultValue();
2259          DataArrayView view_2 = tmp_2->getDefaultValue();
2260          // Get the pointers to the actual data
2261          double *ptr_0 = &((view_0.getData())[0]);
2262          double *ptr_1 = &((view_1.getData())[0]);
2263          double *ptr_2 = &((view_2.getData())[0]);*/
2264    
2265          // Get the pointers to the actual data
2266          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2267          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2268          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2269    
2270    
2271          // Compute a result for the default
2272          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2273          // Merge the tags
2274          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2275          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2276          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2277          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2278            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2279          }
2280          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2281            tmp_2->addTag(i->first);
2282          }
2283          // Compute a result for each tag
2284          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2285          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2286    
2287    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2288            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2289            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2290            double *ptr_0 = &view_0.getData(0);
2291            double *ptr_1 = &view_1.getData(0);
2292            double *ptr_2 = &view_2.getData(0);*/
2293    
2294            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2295            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2296            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2297    
2298            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2299          }
2300    
2301        }
2302        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2303    
2304          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2305          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2306          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2307          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2308          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2309    
2310          int sampleNo_0,dataPointNo_0;
2311          int numSamples_0 = arg_0_Z.getNumSamples();
2312          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2313          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2314          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2315            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2316            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2317            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2318              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2319              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2320              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2321              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2322              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2323            }
2324          }
2325    
2326        }
2327        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2328    
2329          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2330          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2331          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2332          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2333    
2334          int sampleNo_0,dataPointNo_0;
2335          int numSamples_0 = arg_0_Z.getNumSamples();
2336          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2337          int offset_1 = tmp_1->getPointOffset(0,0);
2338          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2339          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2340            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2341              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2342              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2343              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2344              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2345              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2346              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2347            }
2348          }
2349    
2350    
2351        }
2352        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2353    
2354          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2355          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2356          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2357          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2358          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2359    
2360          int sampleNo_0,dataPointNo_0;
2361          int numSamples_0 = arg_0_Z.getNumSamples();
2362          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2363          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2364          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2365            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2366            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2367            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2368              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2369              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2370              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2371              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2372              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2373            }
2374          }
2375    
2376        }
2377        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2378    
2379          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2380          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2381          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2382          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2383          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2384    
2385          int sampleNo_0,dataPointNo_0;
2386          int numSamples_0 = arg_0_Z.getNumSamples();
2387          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2388          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2389          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2390            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2391              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2392              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2393              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2394              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2395              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2396              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2397              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2398            }
2399          }
2400    
2401        }
2402        else {
2403          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2404        }
2405    
2406      } else if (0 == rank1) {
2407    
2408        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2409          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2410          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2411          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2412          double *ptr_2 = &(res.getDataAtOffset(0));
2413          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2414        }
2415        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2416    
2417          // Prepare the DataConstant input
2418          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2419    
2420          // Borrow DataTagged input from Data object
2421          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2422    
2423          // Prepare a DataTagged output 2
2424          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2425          res.tag();
2426          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2427    
2428          // Prepare offset into DataConstant
2429          int offset_0 = tmp_0->getPointOffset(0,0);
2430          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2431          // Get the views
2432    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2433          DataArrayView view_2 = tmp_2->getDefaultValue();
2434          // Get the pointers to the actual data
2435          double *ptr_1 = &((view_1.getData())[0]);
2436          double *ptr_2 = &((view_2.getData())[0]);*/
2437          //Get the pointers to the actual data
2438          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2439          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2440    
2441          // Compute a result for the default
2442          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2443          // Compute a result for each tag
2444          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2445          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2446          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2447            tmp_2->addTag(i->first);
2448    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2449    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2450    //         double *ptr_1 = &view_1.getData(0);
2451    //         double *ptr_2 = &view_2.getData(0);
2452            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2453            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2454    
2455    
2456            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2457          }
2458    
2459        }
2460        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2461    
2462          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2463          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2464          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2465          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2466    
2467          int sampleNo_1,dataPointNo_1;
2468          int numSamples_1 = arg_1_Z.getNumSamples();
2469          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2470          int offset_0 = tmp_0->getPointOffset(0,0);
2471          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2472          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2473            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2474              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2475              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2476              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2477              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2478              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2479              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2480            }
2481          }
2482    
2483        }
2484        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2485    
2486          // Borrow DataTagged input from Data object
2487          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2488    
2489          // Prepare the DataConstant input
2490          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2491    
2492          // Prepare a DataTagged output 2
2493          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2494          res.tag();
2495          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2496    
2497          // Prepare offset into DataConstant
2498          int offset_1 = tmp_1->getPointOffset(0,0);
2499          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2500          // Get the views
2501    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2502    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2503    //       // Get the pointers to the actual data
2504    //       double *ptr_0 = &((view_0.getData())[0]);
2505    //       double *ptr_2 = &((view_2.getData())[0]);
2506          // Get the pointers to the actual data
2507          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2508          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2509          // Compute a result for the default
2510          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2511          // Compute a result for each tag
2512          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2513          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2514          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2515            tmp_2->addTag(i->first);
2516    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2517            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2518            double *ptr_0 = &view_0.getData(0);
2519            double *ptr_2 = &view_2.getData(0);*/
2520            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2521            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2522            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2523          }
2524    
2525        }
2526        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2527    
2528          // Borrow DataTagged input from Data object
2529          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2530    
2531          // Borrow DataTagged input from Data object
2532          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2533    
2534          // Prepare a DataTagged output 2
2535          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2536          res.tag();        // DataTagged output
2537          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2538    
2539          // Get the views
2540    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2541    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2542    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2543    //       // Get the pointers to the actual data
2544    //       double *ptr_0 = &((view_0.getData())[0]);
2545    //       double *ptr_1 = &((view_1.getData())[0]);
2546    //       double *ptr_2 = &((view_2.getData())[0]);
2547    
2548          // Get the pointers to the actual data
2549          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2550          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2551          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2552    
2553          // Compute a result for the default
2554          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2555          // Merge the tags
2556          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2557          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2558          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2559          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2560            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2561          }
2562          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2563            tmp_2->addTag(i->first);
2564          }
2565          // Compute a result for each tag
2566          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2567          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2568    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2569    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2570    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2571    //         double *ptr_0 = &view_0.getData(0);
2572    //         double *ptr_1 = &view_1.getData(0);
2573    //         double *ptr_2 = &view_2.getData(0);
2574    
2575            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2576            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2577            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2578            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2579          }
2580    
2581        }
2582        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2583    
2584          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2585          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2586          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2587          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2588          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2589    
2590          int sampleNo_0,dataPointNo_0;
2591          int numSamples_0 = arg_0_Z.getNumSamples();
2592          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2593          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2594          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2595            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2596            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2597            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2598              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2599              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2600              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2601              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2602              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2603            }
2604          }
2605    
2606        }
2607        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2608    
2609          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2610          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2611          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2612          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2613    
2614          int sampleNo_0,dataPointNo_0;
2615          int numSamples_0 = arg_0_Z.getNumSamples();
2616          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2617          int offset_1 = tmp_1->getPointOffset(0,0);
2618          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2619          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2620            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2621              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2622              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2623              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2624              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2625              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2626              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2627            }
2628          }
2629    
2630    
2631        }
2632        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2633    
2634          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2635          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2636          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2637          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2638          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2639    
2640          int sampleNo_0,dataPointNo_0;
2641          int numSamples_0 = arg_0_Z.getNumSamples();
2642          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2643          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2644          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2645            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2646            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2647            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2648              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2649              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2650              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2651              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2652              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2653            }
2654          }
2655    
2656        }
2657        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2658    
2659          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2660          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2661          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2662          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2663          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2664    
2665          int sampleNo_0,dataPointNo_0;
2666          int numSamples_0 = arg_0_Z.getNumSamples();
2667          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2668          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2669          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2670            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2671              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2672              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2673              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2674              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2675              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2676              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2677              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2678            }
2679          }
2680    
2681        }
2682        else {
2683          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2684        }
2685    
2686      } else {
2687        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2688      }
2689    
2690      return res;
2691    }
2692    
2693    template <typename UnaryFunction>
2694    Data
2695    C_TensorUnaryOperation(Data const &arg_0,
2696                           UnaryFunction operation)
2697    {
2698      if (arg_0.isEmpty())  // do this before we attempt to interpolate
2699      {
2700         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2701      }
2702    
2703      // Interpolate if necessary and find an appropriate function space
2704      Data arg_0_Z = Data(arg_0);
2705    
2706      // Get rank and shape of inputs
2707    //  int rank0 = arg_0_Z.getDataPointRank();
2708      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2709      int size0 = arg_0_Z.getDataPointSize();
2710    
2711      // Declare output Data object
2712      Data res;
2713    
2714      if (arg_0_Z.isConstant()) {
2715        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2716    //     double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2717    //     double *ptr_2 = &((res.getPointDataView().getData())[0]);
2718        double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2719        double *ptr_2 = &(res.getDataAtOffset(0));
2720        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2721      }
2722      else if (arg_0_Z.isTagged()) {
2723    
2724        // Borrow DataTagged input from Data object
2725        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2726    
2727        // Prepare a DataTagged output 2
2728        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2729        res.tag();
2730        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2731    
2732    //     // Get the views
2733    //     DataArrayView view_0 = tmp_0->getDefaultValue();
2734    //     DataArrayView view_2 = tmp_2->getDefaultValue();
2735    //     // Get the pointers to the actual data
2736    //     double *ptr_0 = &((view_0.getData())[0]);
2737    //     double *ptr_2 = &((view_2.getData())[0]);
2738        // Get the pointers to the actual data
2739        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2740        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2741        // Compute a result for the default
2742        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2743        // Compute a result for each tag
2744        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2745        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2746        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2747          tmp_2->addTag(i->first);
2748    //       DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2749    //       DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2750    //       double *ptr_0 = &view_0.getData(0);
2751    //       double *ptr_2 = &view_2.getData(0);
2752          double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2753          double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2754          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2755        }
2756    
2757      }
2758      else if (arg_0_Z.isExpanded()) {
2759    
2760        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2761        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2762        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2763    
2764        int sampleNo_0,dataPointNo_0;
2765        int numSamples_0 = arg_0_Z.getNumSamples();
2766        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2767        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2768        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2769          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2770    //         int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2771    //         int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2772    //         double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2773    //         double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2774            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2775            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2776            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2777            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2778            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2779          }
2780        }
2781      }
2782      else {
2783        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2784      }
2785    
2786      return res;
2787  }  }
2788    
2789  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26