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

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

  ViewVC Help
Powered by ViewVC 1.1.26