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

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

  ViewVC Help
Powered by ViewVC 1.1.26