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

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

  ViewVC Help
Powered by ViewVC 1.1.26