/[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 1327 by matt, Fri Oct 12 07:10:40 2007 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    
29  extern "C" {  extern "C" {
30  #include "escript/Data/DataC.h"  #include "DataC.h"
31    /* #include "paso/Paso.h" doesn't belong in this file...causes trouble for BruceFactory.cpp */
32  }  }
33    
34  #include <iostream>  #include "esysmpi.h"
35  #include <string>  #include <string>
 #include <memory>  
36  #include <algorithm>  #include <algorithm>
37    
38  #include <boost/shared_ptr.hpp>  #include <boost/shared_ptr.hpp>
39  #include <boost/python/object.hpp>  #include <boost/python/object.hpp>
 #include <boost/python/list.hpp>  
40  #include <boost/python/tuple.hpp>  #include <boost/python/tuple.hpp>
41  #include <boost/python/numeric.hpp>  #include <boost/python/numeric.hpp>
42    
43    namespace escript {
44    
45    //
46    // Forward declaration for various implementations of Data.
47    class DataConstant;
48    class DataTagged;
49    class DataExpanded;
50    
51  /**  /**
52     \brief     \brief
53     Data is essentially a factory class which creates the appropriate Data     Data creates the appropriate Data object for the given construction
54     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.  
55    
56     Description:     Description:
57     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 60  extern "C" {
60     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
61     the Data object.     the Data object.
62  */  */
   
 namespace escript {  
   
 //  
 // Forward declaration for various implimentations of Data.  
 class DataEmpty;  
 class DataConstant;  
 class DataTagged;  
 class DataExpanded;  
   
63  class Data {  class Data {
64    
65    public:    public:
66    
67      // These typedefs allow function names to be cast to pointers
68      // to functions of the appropriate type when calling unaryOp etc.
69    typedef double (*UnaryDFunPtr)(double);    typedef double (*UnaryDFunPtr)(double);
70    typedef double (*BinaryDFunPtr)(double,double);    typedef double (*BinaryDFunPtr)(double,double);
71    
72    
73    /**    /**
74       Constructors.       Constructors.
75    */    */
# Line 80  class Data { Line 79  class Data {
79       Default constructor.       Default constructor.
80       Creates a DataEmpty object.       Creates a DataEmpty object.
81    */    */
82      ESCRIPT_DLL_API
83    Data();    Data();
84    
85    /**    /**
# Line 87  class Data { Line 87  class Data {
87       Copy constructor.       Copy constructor.
88       WARNING: Only performs a shallow copy.       WARNING: Only performs a shallow copy.
89    */    */
90      ESCRIPT_DLL_API
91    Data(const Data& inData);    Data(const Data& inData);
92    
93    /**    /**
# Line 95  class Data { Line 96  class Data {
96       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,
97       otherwise a shallow copy of inData is returned.       otherwise a shallow copy of inData is returned.
98    */    */
99      ESCRIPT_DLL_API
100    Data(const Data& inData,    Data(const Data& inData,
101         const FunctionSpace& what);         const FunctionSpace& what);
102    
# Line 108  class Data { Line 110  class Data {
110                         the value. Otherwise a more efficient storage                         the value. Otherwise a more efficient storage
111                         mechanism will be used.                         mechanism will be used.
112    */    */
113      ESCRIPT_DLL_API
114    Data(const DataArrayView& value,    Data(const DataArrayView& value,
115         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
116         bool expanded=false);         bool expanded=false);
# Line 123  class Data { Line 126  class Data {
126                         the given value. Otherwise a more efficient storage                         the given value. Otherwise a more efficient storage
127                         mechanism will be used.                         mechanism will be used.
128    */    */
129      ESCRIPT_DLL_API
130    Data(double value,    Data(double value,
131         const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(),         const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(),
132         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
# Line 135  class Data { Line 139  class Data {
139       \param inData - Input - Input Data object.       \param inData - Input - Input Data object.
140       \param region - Input - Region to copy.       \param region - Input - Region to copy.
141    */    */
142      ESCRIPT_DLL_API
143    Data(const Data& inData,    Data(const Data& inData,
144         const DataArrayView::RegionType& region);         const DataArrayView::RegionType& region);
145    
# Line 150  class Data { Line 155  class Data {
155       \param what - Input - A description of what this data represents.       \param what - Input - A description of what this data represents.
156       \param expanded - Input - Flag, if true fill the entire container with       \param expanded - Input - Flag, if true fill the entire container with
157                         the appropriate values.                         the appropriate values.
158        ==>*
159    */    */
160      ESCRIPT_DLL_API
161    Data(const DataTagged::TagListType& tagKeys,    Data(const DataTagged::TagListType& tagKeys,
162         const DataTagged::ValueListType& values,         const DataTagged::ValueListType& values,
163         const DataArrayView& defaultValue,         const DataArrayView& defaultValue,
# Line 167  class Data { Line 174  class Data {
174                         the value. Otherwise a more efficient storage                         the value. Otherwise a more efficient storage
175                         mechanism will be used.                         mechanism will be used.
176    */    */
177      ESCRIPT_DLL_API
178    Data(const boost::python::numeric::array& value,    Data(const boost::python::numeric::array& value,
179         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
180         bool expanded=false);         bool expanded=false);
# Line 182  class Data { Line 190  class Data {
190                         the value. Otherwise a more efficient storage                         the value. Otherwise a more efficient storage
191                         mechanism will be used.                         mechanism will be used.
192    */    */
193      ESCRIPT_DLL_API
194    Data(const boost::python::object& value,    Data(const boost::python::object& value,
195         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
196         bool expanded=false);         bool expanded=false);
# Line 195  class Data { Line 204  class Data {
204       \param value - Input - Input data.       \param value - Input - Input data.
205       \param other - Input - contains all other parameters.       \param other - Input - contains all other parameters.
206    */    */
207      ESCRIPT_DLL_API
208    Data(const boost::python::object& value,    Data(const boost::python::object& value,
209         const Data& other);         const Data& other);
210    
# Line 202  class Data { Line 212  class Data {
212       \brief       \brief
213       Constructor which creates a DataConstant of "shape" with constant value.       Constructor which creates a DataConstant of "shape" with constant value.
214    */    */
215    Data(double value,    ESCRIPT_DLL_API
216         const boost::python::tuple& shape=boost::python::make_tuple(),    Data(double value,
217           const boost::python::tuple& shape=boost::python::make_tuple(),
218         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
219         bool expanded=false);         bool expanded=false);
220      /**
221         \brief
222         Destructor
223      */
224      ESCRIPT_DLL_API
225      ~Data();
226    
227    /**    /**
228       \brief       \brief
229       Perform a deep copy.       Perform a deep copy.
230    */    */
231      ESCRIPT_DLL_API
232    void    void
233    copy(const Data& other);    copy(const Data& other);
234    
# Line 220  class Data { Line 238  class Data {
238    
239    /**    /**
240       \brief       \brief
241         switches on update protection
242    
243      */
244      ESCRIPT_DLL_API
245      void
246      setProtection();
247    
248      /**
249         \brief
250         Returns trueif the data object is protected against update
251    
252      */
253      ESCRIPT_DLL_API
254      bool
255      isProtected() const;
256    
257      /**
258         \brief
259         Return the values of a data point on this process
260      */
261      ESCRIPT_DLL_API
262      const boost::python::numeric::array
263      getValueOfDataPoint(int dataPointNo);
264    
265      /**
266         \brief
267         sets the values of a data-point from a python object on this process
268      */
269      ESCRIPT_DLL_API
270      void
271      setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
272    
273      /**
274         \brief
275         sets the values of a data-point from a numarray object on this process
276      */
277      ESCRIPT_DLL_API
278      void
279      setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
280    
281      /**
282         \brief
283         sets the values of a data-point on this process
284      */
285      ESCRIPT_DLL_API
286      void
287      setValueOfDataPoint(int dataPointNo, const double);
288    
289      /**
290         \brief
291         Return the value of the specified data-point across all processors
292      */
293      ESCRIPT_DLL_API
294      const boost::python::numeric::array
295      getValueOfGlobalDataPoint(int procNo, int dataPointNo);
296    
297      /**
298         \brief
299         Return the tag number associated with the given data-point.
300    
301         The data-point number here corresponds to the data-point number in the
302         numarray returned by convertToNumArray.
303      */
304      ESCRIPT_DLL_API
305      int
306      getTagNumber(int dpno);
307    
308      /**
309         \brief
310       Return the C wrapper for the Data object.       Return the C wrapper for the Data object.
311    */    */
312      ESCRIPT_DLL_API
313    escriptDataC    escriptDataC
314    getDataC();    getDataC();
315    
# Line 229  class Data { Line 317  class Data {
317       \brief       \brief
318       Return the C wrapper for the Data object - const version.       Return the C wrapper for the Data object - const version.
319    */    */
320      ESCRIPT_DLL_API
321    escriptDataC    escriptDataC
322    getDataC() const;    getDataC() const;
323    
# Line 236  class Data { Line 325  class Data {
325       \brief       \brief
326       Write the data as a string.       Write the data as a string.
327    */    */
328      ESCRIPT_DLL_API
329    inline    inline
330    std::string    std::string
331    toString() const    toString() const
# Line 249  class Data { Line 339  class Data {
339       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
340       to manipulate the point data.       to manipulate the point data.
341    */    */
342      ESCRIPT_DLL_API
343    inline    inline
344    const DataArrayView&    const DataArrayView&
345    getPointDataView() const    getPointDataView() const
# Line 260  class Data { Line 351  class Data {
351       \brief       \brief
352       Whatever the current Data type make this into a DataExpanded.       Whatever the current Data type make this into a DataExpanded.
353    */    */
354      ESCRIPT_DLL_API
355    void    void
356    expand();    expand();
357    
# Line 268  class Data { Line 360  class Data {
360       If possible convert this Data to DataTagged. This will only allow       If possible convert this Data to DataTagged. This will only allow
361       Constant data to be converted to tagged. An attempt to convert       Constant data to be converted to tagged. An attempt to convert
362       Expanded data to tagged will throw an exception.       Expanded data to tagged will throw an exception.
363        ==>*
364    */    */
365      ESCRIPT_DLL_API
366    void    void
367    tag();    tag();
368    
# Line 276  class Data { Line 370  class Data {
370       \brief       \brief
371       Return true if this Data is expanded.       Return true if this Data is expanded.
372    */    */
373      ESCRIPT_DLL_API
374    bool    bool
375    isExpanded() const;    isExpanded() const;
376    
# Line 283  class Data { Line 378  class Data {
378       \brief       \brief
379       Return true if this Data is tagged.       Return true if this Data is tagged.
380    */    */
381      ESCRIPT_DLL_API
382    bool    bool
383    isTagged() const;    isTagged() const;
384    
# Line 290  class Data { Line 386  class Data {
386       \brief       \brief
387       Return true if this Data is constant.       Return true if this Data is constant.
388    */    */
389      ESCRIPT_DLL_API
390    bool    bool
391    isConstant() const;    isConstant() const;
392    
# Line 297  class Data { Line 394  class Data {
394       \brief       \brief
395       Return true if this Data is empty.       Return true if this Data is empty.
396    */    */
397      ESCRIPT_DLL_API
398    bool    bool
399    isEmpty() const;    isEmpty() const;
400    
# Line 304  class Data { Line 402  class Data {
402       \brief       \brief
403       Return the function space.       Return the function space.
404    */    */
405      ESCRIPT_DLL_API
406    inline    inline
407    const FunctionSpace&    const FunctionSpace&
408    getFunctionSpace() const    getFunctionSpace() const
# Line 315  class Data { Line 414  class Data {
414       \brief       \brief
415       Return a copy of the function space.       Return a copy of the function space.
416    */    */
417      ESCRIPT_DLL_API
418    const FunctionSpace    const FunctionSpace
419    getCopyOfFunctionSpace() const;    getCopyOfFunctionSpace() const;
420    
# Line 322  class Data { Line 422  class Data {
422       \brief       \brief
423       Return the domain.       Return the domain.
424    */    */
425      ESCRIPT_DLL_API
426    inline    inline
427    const AbstractDomain&    const AbstractDomain&
428    getDomain() const    getDomain() const
# Line 333  class Data { Line 434  class Data {
434       \brief       \brief
435       Return a copy of the domain.       Return a copy of the domain.
436    */    */
437      ESCRIPT_DLL_API
438    const AbstractDomain    const AbstractDomain
439    getCopyOfDomain() const;    getCopyOfDomain() const;
440    
# Line 340  class Data { Line 442  class Data {
442       \brief       \brief
443       Return the rank of the point data.       Return the rank of the point data.
444    */    */
445      ESCRIPT_DLL_API
446    inline    inline
447    int    int
448    getDataPointRank() const    getDataPointRank() const
# Line 349  class Data { Line 452  class Data {
452    
453    /**    /**
454       \brief       \brief
455         Return the number of data points
456      */
457      ESCRIPT_DLL_API
458      inline
459      int
460      getNumDataPoints() const
461      {
462        return getNumSamples() * getNumDataPointsPerSample();
463      }
464      /**
465         \brief
466       Return the number of samples.       Return the number of samples.
467    */    */
468      ESCRIPT_DLL_API
469    inline    inline
470    int    int
471    getNumSamples() const    getNumSamples() const
# Line 362  class Data { Line 477  class Data {
477       \brief       \brief
478       Return the number of data points per sample.       Return the number of data points per sample.
479    */    */
480      ESCRIPT_DLL_API
481    inline    inline
482    int    int
483    getNumDataPointsPerSample() const    getNumDataPointsPerSample() const
484    {    {
485      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
486    }    }
487      /**
488         \brief
489         dumps the object into a netCDF file
490      */
491      ESCRIPT_DLL_API
492      void
493      dump(const std::string fileName) const;
494    /**    /**
495       \brief       \brief
496       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
497       preferred interface but is provided for use by C code.       preferred interface but is provided for use by C code.
498       \param sampleNo - Input - the given sample no.       \param sampleNo - Input - the given sample no.
499    */    */
500      ESCRIPT_DLL_API
501    inline    inline
502    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
503    getSampleData(DataAbstract::ValueType::size_type sampleNo)    getSampleData(DataAbstract::ValueType::size_type sampleNo)
# Line 388  class Data { Line 511  class Data {
511       access data that isn't tagged an exception will be thrown.       access data that isn't tagged an exception will be thrown.
512       \param tag - Input - the tag key.       \param tag - Input - the tag key.
513    */    */
514      ESCRIPT_DLL_API
515    inline    inline
516    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
517    getSampleDataByTag(int tag)    getSampleDataByTag(int tag)
# Line 403  class Data { Line 527  class Data {
527       \param sampleNo - Input -       \param sampleNo - Input -
528       \param dataPointNo - Input -       \param dataPointNo - Input -
529    */    */
530      ESCRIPT_DLL_API
531    inline    inline
532    DataArrayView    DataArrayView
533    getDataPoint(int sampleNo,    getDataPoint(int sampleNo,
534                 int dataPointNo)                 int dataPointNo)
535    {    {
536      return m_data->getDataPoint(sampleNo,dataPointNo);          return m_data->getDataPoint(sampleNo,dataPointNo);
537    }    }
538    
539    /**    /**
540       \brief       \brief
541       Return a reference to the data point shape.       Return a reference to the data point shape.
542    */    */
543      ESCRIPT_DLL_API
544    const DataArrayView::ShapeType&    const DataArrayView::ShapeType&
545    getDataPointShape() const;    getDataPointShape() const;
546    
# Line 422  class Data { Line 548  class Data {
548       \brief       \brief
549       Return the data point shape as a tuple of integers.       Return the data point shape as a tuple of integers.
550    */    */
551    boost::python::tuple    ESCRIPT_DLL_API
552      const boost::python::tuple
553    getShapeTuple() const;    getShapeTuple() const;
554    
555    /**    /**
# Line 430  class Data { Line 557  class Data {
557       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
558       data point shape dimensions.       data point shape dimensions.
559    */    */
560      ESCRIPT_DLL_API
561    int    int
562    getDataPointSize() const;    getDataPointSize() const;
563    
# Line 437  class Data { Line 565  class Data {
565       \brief       \brief
566       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
567    */    */
568      ESCRIPT_DLL_API
569    DataArrayView::ValueType::size_type    DataArrayView::ValueType::size_type
570    getLength() const;    getLength() const;
571    
572    
573    
574      /**
575         \brief
576         Assign the given value to the tag assocciated with name. Implicitly converts this
577         object to type DataTagged. Throws an exception if this object
578         cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
579         \param tagKey - Input - Integer key.
580         \param value - Input - Value to associate with given key.
581        ==>*
582      */
583      ESCRIPT_DLL_API
584      void
585      setTaggedValueByName(std::string name,
586                           const boost::python::object& value);
587    
588    /**    /**
589       \brief       \brief
590       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
# Line 447  class Data { Line 592  class Data {
592       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object.
593       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
594       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
595        ==>*
596    */    */
597      ESCRIPT_DLL_API
598    void    void
599    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
600                   const boost::python::object& value);                   const boost::python::object& value);
# Line 459  class Data { Line 606  class Data {
606       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object.
607       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
608       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
609       Note: removed for now - this version not needed, and breaks escript.cpp      ==>*
610    */    */
611    /*    ESCRIPT_DLL_API
612    void    void
613    setTaggedValue(int tagKey,    setTaggedValueFromCPP(int tagKey,
614                   const DataArrayView& value);                          const DataArrayView& value);
   */  
615    
616    /**    /**
617      \brief      \brief
618      Copy other Data object into this Data object where mask is positive.      Copy other Data object into this Data object where mask is positive.
619    */    */
620      ESCRIPT_DLL_API
621    void    void
622    copyWithMask(const Data& other,    copyWithMask(const Data& other,
623                 const Data& mask);                 const Data& mask);
# Line 481  class Data { Line 628  class Data {
628    
629    /**    /**
630       \brief       \brief
631         set all values to zero
632         *
633      */
634      ESCRIPT_DLL_API
635      void
636      setToZero();
637    
638      /**
639         \brief
640       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
641       the result as a Data object.       the result as a Data object.
642         *
643    */    */
644      ESCRIPT_DLL_API
645    Data    Data
646    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
647    /**    /**
648       \brief       \brief
649       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
650       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.
651         *
652    */    */
653      ESCRIPT_DLL_API
654    Data    Data
655    gradOn(const FunctionSpace& functionspace) const;    gradOn(const FunctionSpace& functionspace) const;
656    
657      ESCRIPT_DLL_API
658    Data    Data
659    grad() const;    grad() const;
660    
661    /**    /**
662       \brief       \brief
663       Calculate the integral over the function space domain.       Calculate the integral over the function space domain.
664         *
665    */    */
666      ESCRIPT_DLL_API
667    boost::python::numeric::array    boost::python::numeric::array
668    integrate() const;    integrate() const;
669    
670    /**    /**
671       \brief       \brief
672         Returns 1./ Data object
673         *
674      */
675      ESCRIPT_DLL_API
676      Data
677      oneOver() const;
678      /**
679         \brief
680       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.
681         *
682    */    */
683      ESCRIPT_DLL_API
684    Data    Data
685    wherePositive() const;    wherePositive() const;
686    
687    /**    /**
688       \brief       \brief
689       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.
690         *
691    */    */
692      ESCRIPT_DLL_API
693    Data    Data
694    whereNegative() const;    whereNegative() const;
695    
696    /**    /**
697       \brief       \brief
698       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.
699         *
700    */    */
701      ESCRIPT_DLL_API
702    Data    Data
703    whereNonNegative() const;    whereNonNegative() const;
704    
705    /**    /**
706       \brief       \brief
707       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.
708         *
709    */    */
710      ESCRIPT_DLL_API
711    Data    Data
712    whereNonPositive() const;    whereNonPositive() const;
713    
714    /**    /**
715       \brief       \brief
716       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.
717         *
718    */    */
719      ESCRIPT_DLL_API
720    Data    Data
721    whereZero() const;    whereZero(double tol=0.0) const;
722    
723    /**    /**
724       \brief       \brief
725       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.
726         *
727      */
728      ESCRIPT_DLL_API
729      Data
730      whereNonZero(double tol=0.0) const;
731    
732      /**
733         \brief
734         Return the maximum absolute value of this Data object.
735         *
736      */
737      ESCRIPT_DLL_API
738      double
739      Lsup() const;
740    
741      /**
742         \brief
743         Return the maximum value of this Data object.
744         *
745      */
746      ESCRIPT_DLL_API
747      double
748      sup() const;
749    
750      /**
751         \brief
752         Return the minimum value of this Data object.
753         *
754      */
755      ESCRIPT_DLL_API
756      double
757      inf() const;
758    
759      /**
760         \brief
761         Return the absolute value of each data point of this Data object.
762         *
763      */
764      ESCRIPT_DLL_API
765      Data
766      abs() const;
767    
768      /**
769         \brief
770         Return the maximum value of each data point of this Data object.
771         *
772      */
773      ESCRIPT_DLL_API
774      Data
775      maxval() const;
776    
777      /**
778         \brief
779         Return the minimum value of each data point of this Data object.
780         *
781      */
782      ESCRIPT_DLL_API
783      Data
784      minval() const;
785    
786      /**
787         \brief
788         Return the (sample number, data-point number) of the data point with
789         the minimum value in this Data object.
790      */
791      ESCRIPT_DLL_API
792      const boost::python::tuple
793      minGlobalDataPoint() const;
794    
795      ESCRIPT_DLL_API
796      void
797      calc_minGlobalDataPoint(int& ProcNo,  int& DataPointNo) const;
798      /**
799         \brief
800         Return the sign of each data point of this Data object.
801         -1 for negative values, zero for zero values, 1 for positive values.
802         *
803      */
804      ESCRIPT_DLL_API
805      Data
806      sign() const;
807    
808      /**
809         \brief
810         Return the symmetric part of a matrix which is half the matrix plus its transpose.
811         *
812      */
813      ESCRIPT_DLL_API
814      Data
815      symmetric() const;
816    
817      /**
818         \brief
819         Return the nonsymmetric part of a matrix which is half the matrix minus its transpose.
820         *
821      */
822      ESCRIPT_DLL_API
823      Data
824      nonsymmetric() const;
825    
826      /**
827         \brief
828         Return the trace of a matrix
829         *
830      */
831      ESCRIPT_DLL_API
832      Data
833      trace(int axis_offset) const;
834    
835      /**
836         \brief
837         Transpose each data point of this Data object around the given axis.
838         *
839      */
840      ESCRIPT_DLL_API
841      Data
842      transpose(int axis_offset) const;
843    
844      /**
845         \brief
846         Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.
847         Currently this function is restricted to rank 2, square shape, and dimension 3.
848         *
849      */
850      ESCRIPT_DLL_API
851      Data
852      eigenvalues() const;
853    
854      /**
855         \brief
856         Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.
857         the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than
858         tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the
859         first non-zero entry is positive.
860         Currently this function is restricted to rank 2, square shape, and dimension 3
861         *
862      */
863      ESCRIPT_DLL_API
864      const boost::python::tuple
865      eigenvalues_and_eigenvectors(const double tol=1.e-12) const;
866    
867      /**
868         \brief
869         swaps the components axis0 and axis1
870         *
871    */    */
872      ESCRIPT_DLL_API
873    Data    Data
874    whereNonZero() const;    swapaxes(const int axis0, const int axis1) const;
875    
876      /**
877         \brief
878         Return the error function erf of each data point of this Data object.
879         *
880      */
881      ESCRIPT_DLL_API
882      Data
883      erf() const;
884    
885    /**    /**
886       \brief       \brief
887       Return the sin of each data point of this Data object.       Return the sin of each data point of this Data object.
888         *
889    */    */
890      ESCRIPT_DLL_API
891    Data    Data
892    sin() const;    sin() const;
893    
894    /**    /**
895       \brief       \brief
896       Return the cos of each data point of this Data object.       Return the cos of each data point of this Data object.
897         *
898    */    */
899      ESCRIPT_DLL_API
900    Data    Data
901    cos() const;    cos() const;
902    
903    /**    /**
904       \brief       \brief
905       Return the tan of each data point of this Data object.       Return the tan of each data point of this Data object.
906         *
907    */    */
908      ESCRIPT_DLL_API
909    Data    Data
910    tan() const;    tan() const;
911    
912    /**    /**
913       \brief       \brief
914       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.
915         *
916    */    */
917      ESCRIPT_DLL_API
918    Data    Data
919    log() const;    asin() const;
920    
921    /**    /**
922       \brief       \brief
923       Return the natural log of each data point of this Data object.       Return the acos of each data point of this Data object.
924         *
925    */    */
926      ESCRIPT_DLL_API
927    Data    Data
928    ln() const;    acos() const;
929    
930    /**    /**
931       \brief       \brief
932       Return the maximum absolute value of this Data object.       Return the atan of each data point of this Data object.
933         *
934    */    */
935    double    ESCRIPT_DLL_API
936    Lsup() const;    Data
937      atan() const;
938    
939    /**    /**
940       \brief       \brief
941       Return the maximum value of this Data object.       Return the sinh of each data point of this Data object.
942         *
943    */    */
944    double    ESCRIPT_DLL_API
945    sup() const;    Data
946      sinh() const;
947    
948    /**    /**
949       \brief       \brief
950       Return the minimum value of this Data object.       Return the cosh of each data point of this Data object.
951         *
952    */    */
953    double    ESCRIPT_DLL_API
954    inf() const;    Data
955      cosh() const;
956    
957    /**    /**
958       \brief       \brief
959       Return the absolute value of each data point of this Data object.       Return the tanh of each data point of this Data object.
960         *
961    */    */
962      ESCRIPT_DLL_API
963    Data    Data
964    abs() const;    tanh() const;
965    
966    /**    /**
967       \brief       \brief
968       Return the maximum value of each data point of this Data object.       Return the asinh of each data point of this Data object.
969         *
970    */    */
971      ESCRIPT_DLL_API
972    Data    Data
973    maxval() const;    asinh() const;
974    
975    /**    /**
976       \brief       \brief
977       Return the minimum value of each data point of this Data object.       Return the acosh of each data point of this Data object.
978         *
979    */    */
980      ESCRIPT_DLL_API
981    Data    Data
982    minval() const;    acosh() const;
983    
984    /**    /**
985       \brief       \brief
986       Return the length of each data point of this Data object.       Return the atanh of each data point of this Data object.
987       sqrt(sum(A[i,j,k,l]^2))       *
988    */    */
989      ESCRIPT_DLL_API
990    Data    Data
991    length() const;    atanh() const;
992    
993    /**    /**
994       \brief       \brief
995       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.
996       -1 for negative values, zero for zero values, 1 for positive values.       *
997    */    */
998      ESCRIPT_DLL_API
999    Data    Data
1000    sign() const;    log10() const;
1001    
1002    /**    /**
1003      \transpose       \brief
1004      Transpose each data point of this Data object around the given axis.       Return the natural log of each data point of this Data object.
1005         *
1006    */    */
1007      ESCRIPT_DLL_API
1008    Data    Data
1009    transpose(int axis) const;    log() const;
1010    
1011    /**    /**
1012      \trace       \brief
1013      Calculate the trace of each data point of this Data object.       Return the exponential function of each data point of this Data object.
1014      sum(A[i,i,i,i])       *
1015    */    */
1016      ESCRIPT_DLL_API
1017    Data    Data
1018    trace() const;    exp() const;
1019    
1020    /**    /**
1021      \exp       \brief
1022      Return the exponential function of each data point of this Data object.       Return the square root of each data point of this Data object.
1023         *
1024    */    */
1025      ESCRIPT_DLL_API
1026    Data    Data
1027    exp() const;    sqrt() const;
1028    
1029    /**    /**
1030      \sqrt       \brief
1031      Return the square root of each data point of this Data object.       Return the negation of each data point of this Data object.
1032         *
1033    */    */
1034      ESCRIPT_DLL_API
1035    Data    Data
1036    sqrt() const;    neg() const;
1037    
1038      /**
1039         \brief
1040         Return the identity of each data point of this Data object.
1041         Simply returns this object unmodified.
1042         *
1043      */
1044      ESCRIPT_DLL_API
1045      Data
1046      pos() const;
1047    
1048    /**    /**
1049       \brief       \brief
1050       Return the given power of each data point of this Data object.       Return the given power of each data point of this Data object.
1051    
1052         \param right Input - the power to raise the object to.
1053         *
1054    */    */
1055      ESCRIPT_DLL_API
1056    Data    Data
1057    powD(const Data& right) const;    powD(const Data& right) const;
1058    
1059      /**
1060         \brief
1061         Return the given power of each data point of this boost python object.
1062    
1063         \param right Input - the power to raise the object to.
1064         *
1065       */
1066      ESCRIPT_DLL_API
1067    Data    Data
1068    powO(const boost::python::object& right) const;    powO(const boost::python::object& right) const;
1069    
1070    /**    /**
1071      \brief       \brief
1072      Return the negation of each data point of this Data object.       Return the given power of each data point of this boost python object.
1073    */  
1074         \param left Input - the bases
1075         *
1076       */
1077    
1078      ESCRIPT_DLL_API
1079    Data    Data
1080    neg() const;    rpowO(const boost::python::object& left) const;
1081    
1082    /**    /**
1083      \brief       \brief
1084      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.  
1085    */    */
1086    Data    ESCRIPT_DLL_API
1087    pos() const;    void
1088      saveDX(std::string fileName) const;
1089    
1090      /**
1091         \brief
1092         writes the object to a file in the VTK file format
1093      */
1094      ESCRIPT_DLL_API
1095      void
1096      saveVTK(std::string fileName) const;
1097    
1098    /**    /**
1099       \brief       \brief
1100       Overloaded operator +=       Overloaded operator +=
1101       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1102         *
1103    */    */
1104      ESCRIPT_DLL_API
1105    Data& operator+=(const Data& right);    Data& operator+=(const Data& right);
1106      ESCRIPT_DLL_API
1107    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1108    
1109      ESCRIPT_DLL_API
1110      Data& operator=(const Data& other);
1111    
1112    /**    /**
1113       \brief       \brief
1114       Overloaded operator -=       Overloaded operator -=
1115       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1116         *
1117    */    */
1118      ESCRIPT_DLL_API
1119    Data& operator-=(const Data& right);    Data& operator-=(const Data& right);
1120      ESCRIPT_DLL_API
1121    Data& operator-=(const boost::python::object& right);    Data& operator-=(const boost::python::object& right);
1122    
1123   /**   /**
1124       \brief       \brief
1125       Overloaded operator *=       Overloaded operator *=
1126       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1127         *
1128    */    */
1129      ESCRIPT_DLL_API
1130    Data& operator*=(const Data& right);    Data& operator*=(const Data& right);
1131      ESCRIPT_DLL_API
1132    Data& operator*=(const boost::python::object& right);    Data& operator*=(const boost::python::object& right);
1133    
1134   /**   /**
1135       \brief       \brief
1136       Overloaded operator /=       Overloaded operator /=
1137       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1138         *
1139    */    */
1140      ESCRIPT_DLL_API
1141    Data& operator/=(const Data& right);    Data& operator/=(const Data& right);
1142      ESCRIPT_DLL_API
1143    Data& operator/=(const boost::python::object& right);    Data& operator/=(const boost::python::object& right);
1144    
1145    /**    /**
1146       \brief       \brief
1147       Returns true if this can be interpolated to functionspace.       Returns true if this can be interpolated to functionspace.
1148    */    */
1149      ESCRIPT_DLL_API
1150    bool    bool
1151    probeInterpolation(const FunctionSpace& functionspace) const;    probeInterpolation(const FunctionSpace& functionspace) const;
1152    
# Line 748  class Data { Line 1165  class Data {
1165       \param key - Input - python slice tuple specifying       \param key - Input - python slice tuple specifying
1166       slice to return.       slice to return.
1167    */    */
1168      ESCRIPT_DLL_API
1169    Data    Data
1170    getItem(const boost::python::object& key) const;    getItem(const boost::python::object& key) const;
1171    
# Line 755  class Data { Line 1173  class Data {
1173       \brief       \brief
1174       Copies slice from value into this Data object.       Copies slice from value into this Data object.
1175    
      \description  
1176       Implements the [] set operator in python.       Implements the [] set operator in python.
1177       Calls setSlice.       Calls setSlice.
1178    
# Line 763  class Data { Line 1180  class Data {
1180       slice to copy from value.       slice to copy from value.
1181       \param value - Input - Data object to copy from.       \param value - Input - Data object to copy from.
1182    */    */
1183      ESCRIPT_DLL_API
1184    void    void
1185    setItemD(const boost::python::object& key,    setItemD(const boost::python::object& key,
1186             const Data& value);             const Data& value);
1187    
1188      ESCRIPT_DLL_API
1189    void    void
1190    setItemO(const boost::python::object& key,    setItemO(const boost::python::object& key,
1191             const boost::python::object& value);             const boost::python::object& value);
# Line 779  class Data { Line 1198  class Data {
1198       this Data object.       this Data object.
1199    */    */
1200    template <class UnaryFunction>    template <class UnaryFunction>
1201      ESCRIPT_DLL_API
1202    inline    inline
1203    void    void
1204    unaryOp(UnaryFunction operation);    unaryOp(UnaryFunction operation);
# Line 788  class Data { Line 1208  class Data {
1208       Return a Data object containing the specified slice of       Return a Data object containing the specified slice of
1209       this Data object.       this Data object.
1210       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1211         *
1212    */    */
1213      ESCRIPT_DLL_API
1214    Data    Data
1215    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataArrayView::RegionType& region) const;
1216    
# Line 798  class Data { Line 1220  class Data {
1220       Data object.       Data object.
1221       \param value - Input - Data to copy from.       \param value - Input - Data to copy from.
1222       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1223         *
1224    */    */
1225      ESCRIPT_DLL_API
1226    void    void
1227    setSlice(const Data& value,    setSlice(const Data& value,
1228             const DataArrayView::RegionType& region);             const DataArrayView::RegionType& region);
1229    
1230      /**
1231         \brief
1232         Archive the current Data object to the given file.
1233         \param fileName - Input - file to archive to.
1234      */
1235      ESCRIPT_DLL_API
1236      void
1237      archiveData(const std::string fileName);
1238    
1239      /**
1240         \brief
1241         Extract the Data object archived in the given file, overwriting
1242         the current Data object.
1243         Note - the current object must be of type DataEmpty.
1244         \param fileName - Input - file to extract from.
1245         \param fspace - Input - a suitable FunctionSpace descibing the data.
1246      */
1247      ESCRIPT_DLL_API
1248      void
1249      extractData(const std::string fileName,
1250                  const FunctionSpace& fspace);
1251    
1252    
1253      /**
1254         \brief
1255         print the data values to stdout. Used for debugging
1256      */
1257      ESCRIPT_DLL_API
1258      void
1259        print(void);
1260    
1261      /**
1262         \brief
1263         return the MPI rank number of the local data
1264             MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1265             is returned
1266      */
1267      ESCRIPT_DLL_API
1268        int
1269        get_MPIRank(void) const;
1270    
1271      /**
1272         \brief
1273         return the MPI rank number of the local data
1274             MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1275             is returned
1276      */
1277      ESCRIPT_DLL_API
1278        int
1279        get_MPISize(void) const;
1280    
1281      /**
1282         \brief
1283         return the MPI rank number of the local data
1284             MPI_COMM_WORLD is assumed and returned.
1285      */
1286      ESCRIPT_DLL_API
1287        MPI_Comm
1288        get_MPIComm(void) const;
1289    
1290      /**
1291         \brief
1292         return the object produced by the factory, which is a DataConstant or DataExpanded
1293      */
1294      ESCRIPT_DLL_API
1295        DataAbstract*
1296        borrowData(void) const;
1297    
1298   protected:   protected:
1299    
1300   private:   private:
# Line 823  class Data { Line 1315  class Data {
1315    /**    /**
1316       \brief       \brief
1317       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
1318       this Data object and return the single double value result.       this Data object according to the given function and return the single value result.
1319    */    */
1320    template <class UnaryFunction>    template <class BinaryFunction>
1321    inline    inline
1322    double    double
1323    algorithm(UnaryFunction operation) const;    algorithm(BinaryFunction operation,
1324                double initial_value) const;
1325    
1326    /**    /**
1327       \brief       \brief
1328       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
1329       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
1330       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
1331       is expanded *this will be expanded if necessary.       this Data object
      RHS is a Data object.  
1332    */    */
1333    template <class BinaryFunction>    template <class BinaryFunction>
1334    inline    inline
1335    void    Data
1336    binaryOp(const Data& right,    dp_algorithm(BinaryFunction operation,
1337             BinaryFunction operation);                 double initial_value) const;
1338    
1339    /**    /**
1340       \brief       \brief
1341       Perform the given binary operation on all of the data's elements.       Perform the given binary operation on all of the data's elements.
1342       RHS is a boost::python object.       The underlying type of the right hand side (right) determines the final
1343         type of *this after the operation. For example if the right hand side
1344         is expanded *this will be expanded if necessary.
1345         RHS is a Data object.
1346    */    */
1347    template <class BinaryFunction>    template <class BinaryFunction>
1348    inline    inline
1349    void    void
1350    binaryOp(const boost::python::object& right,    binaryOp(const Data& right,
1351             BinaryFunction operation);             BinaryFunction operation);
1352    
1353    /**    /**
# Line 881  class Data { Line 1376  class Data {
1376               const FunctionSpace& what,               const FunctionSpace& what,
1377               bool expanded);               bool expanded);
1378    
1379    /**    //
1380       \brief    // flag to protect the data object against any update
1381       Reshape the data point if the data point is currently rank 0.    bool m_protected;
      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.  
   */  
   void  
   reshapeDataPoint(const DataArrayView::ShapeType& shape);  
1382    
1383    //    //
1384    // pointer to the actual data object    // pointer to the actual data object
# Line 922  Data::initialise(const IValueType& value Line 1411  Data::initialise(const IValueType& value
1411  /**  /**
1412     Binary Data object operators.     Binary Data object operators.
1413  */  */
1414    inline double rpow(double x,double y)
1415    {
1416        return pow(y,x);
1417    }
1418    
1419  /**  /**
1420    \brief    \brief
1421    Operator+    Operator+
1422    Takes two Data objects.    Takes two Data objects.
1423  */  */
1424  Data operator+(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1425    
1426  /**  /**
1427    \brief    \brief
1428    Operator-    Operator-
1429    Takes two Data objects.    Takes two Data objects.
1430  */  */
1431  Data operator-(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1432    
1433  /**  /**
1434    \brief    \brief
1435    Operator*    Operator*
1436    Takes two Data objects.    Takes two Data objects.
1437  */  */
1438  Data operator*(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1439    
1440  /**  /**
1441    \brief    \brief
1442    Operator/    Operator/
1443    Takes two Data objects.    Takes two Data objects.
1444  */  */
1445  Data operator/(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1446    
1447  /**  /**
1448    \brief    \brief
# Line 957  Data operator/(const Data& left, const D Line 1450  Data operator/(const Data& left, const D
1450    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1451    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1452  */  */
1453  Data operator+(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const boost::python::object& right);
1454    
1455  /**  /**
1456    \brief    \brief
# Line 965  Data operator+(const Data& left, const b Line 1458  Data operator+(const Data& left, const b
1458    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1459    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1460  */  */
1461  Data operator-(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const boost::python::object& right);
1462    
1463  /**  /**
1464    \brief    \brief
# Line 973  Data operator-(const Data& left, const b Line 1466  Data operator-(const Data& left, const b
1466    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1467    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1468  */  */
1469  Data operator*(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const boost::python::object& right);
1470    
1471  /**  /**
1472    \brief    \brief
# Line 981  Data operator*(const Data& left, const b Line 1474  Data operator*(const Data& left, const b
1474    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1475    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1476  */  */
1477  Data operator/(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const boost::python::object& right);
1478    
1479  /**  /**
1480    \brief    \brief
# Line 989  Data operator/(const Data& left, const b Line 1482  Data operator/(const Data& left, const b
1482    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1483    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1484  */  */
1485  Data operator+(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const boost::python::object& left, const Data& right);
1486    
1487  /**  /**
1488    \brief    \brief
# Line 997  Data operator+(const boost::python::obje Line 1490  Data operator+(const boost::python::obje
1490    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1491    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1492  */  */
1493  Data operator-(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const boost::python::object& left, const Data& right);
1494    
1495  /**  /**
1496    \brief    \brief
# Line 1005  Data operator-(const boost::python::obje Line 1498  Data operator-(const boost::python::obje
1498    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1499    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1500  */  */
1501  Data operator*(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const boost::python::object& left, const Data& right);
1502    
1503  /**  /**
1504    \brief    \brief
# Line 1013  Data operator*(const boost::python::obje Line 1506  Data operator*(const boost::python::obje
1506    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1507    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1508  */  */
1509  Data operator/(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1510    
1511    
1512    
1513  /**  /**
1514    \brief    \brief
1515    Output operator    Output operator
1516  */  */
1517  std::ostream& operator<<(std::ostream& o, const Data& data);  ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1518    
1519    /**
1520      \brief
1521      Compute a tensor product of two Data objects
1522      \param arg0 - Input - Data object
1523      \param arg1 - Input - Data object
1524      \param axis_offset - Input - axis offset
1525      \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1526    */
1527    ESCRIPT_DLL_API
1528    Data
1529    C_GeneralTensorProduct(Data& arg0,
1530                         Data& arg1,
1531                         int axis_offset=0,
1532                         int transpose=0);
1533    
1534    
1535    /**
1536      \brief
1537      Compute a tensor operation with two Data objects
1538      \param arg0 - Input - Data object
1539      \param arg1 - Input - Data object
1540      \param operation - Input - Binary op functor
1541    */
1542    template <typename BinaryFunction>
1543    ESCRIPT_DLL_API
1544    Data
1545    C_TensorBinaryOperation(Data const &arg0,
1546                Data const &arg1,
1547                BinaryFunction operation);
1548    
1549  /**  /**
1550    \brief    \brief
1551    Return true if operands are equivalent, else return false.    Return true if operands are equivalent, else return false.
1552    NB: this operator does very little at this point, and isn't to    NB: this operator does very little at this point, and isn't to
1553    be relied on. Requires further implementation.    be relied on. Requires further implementation.
1554  */  */
1555  //bool operator==(const Data& left, const Data& right);  // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1556    
1557  /**  /**
1558    \brief    \brief
# Line 1043  Data::binaryOp(const Data& right, Line 1568  Data::binaryOp(const Data& right,
1568     //     //
1569     // 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
1570     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {
1571       reshapeDataPoint(right.getPointDataView().getShape());       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1572     }     }
1573     //     //
1574     // initially make the temporary a shallow copy     // initially make the temporary a shallow copy
# Line 1051  Data::binaryOp(const Data& right, Line 1576  Data::binaryOp(const Data& right,
1576     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1577       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1578         //         //
1579         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1580         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1581       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1582         //         //
# Line 1099  Data::binaryOp(const Data& right, Line 1624  Data::binaryOp(const Data& right,
1624    
1625  /**  /**
1626    \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  
1627    Perform the given unary operation on other and return the result.    Perform the given unary operation on other and return the result.
1628    Given operation is performed on each element of each data point, thus    Given operation is performed on each element of each data point, thus
1629    argument object is a rank n Data object, and returned object is a rank n    argument object is a rank n Data object, and returned object is a rank n
# Line 1190  Data::unaryOp(UnaryFunction operation) Line 1675  Data::unaryOp(UnaryFunction operation)
1675    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.
1676    Calls escript::algorithm.    Calls escript::algorithm.
1677  */  */
1678  template <class UnaryFunction>  template <class BinaryFunction>
1679  inline  inline
1680  double  double
1681  Data::algorithm(UnaryFunction operation) const  Data::algorithm(BinaryFunction operation, double initial_value) const
1682  {  {
1683    if (isExpanded()) {    if (isExpanded()) {
1684      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1685      EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");      EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1686      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1687    } else if (isTagged()) {    } else if (isTagged()) {
1688      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());      DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1689      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");      EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1690      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1691    } else if (isConstant()) {    } else if (isConstant()) {
1692      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1693      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1694      return escript::algorithm(*leftC,operation);      return escript::algorithm(*leftC,operation,initial_value);
1695    }    }
1696    return 0;    return 0;
1697  }  }
# Line 1215  Data::algorithm(UnaryFunction operation) Line 1700  Data::algorithm(UnaryFunction operation)
1700    \brief    \brief
1701    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.
1702    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1703    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
1704    rank 0 Data object.    rank 0 Data object.
1705    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1706  */  */
1707  template <class UnaryFunction>  template <class BinaryFunction>
1708  inline  inline
1709  Data  Data
1710  dp_algorithm(const Data& data,  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
              UnaryFunction operation)  
1711  {  {
1712    Data result(0,DataArrayView::ShapeType(),data.getFunctionSpace(),data.isExpanded());    if (isExpanded()) {
1713    if (data.isExpanded()) {      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());
1714      DataExpanded* dataE=dynamic_cast<DataExpanded*>(data.m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1715      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1716      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1717      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1718      escript::dp_algorithm(*dataE,*resultE,operation);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1719    } else if (data.isTagged()) {      return result;
1720      DataTagged* dataT=dynamic_cast<DataTagged*>(data.m_data.get());    } else if (isTagged()) {
1721        DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
1722        DataArrayView::ShapeType viewShape;
1723        DataArrayView::ValueType viewData(1);
1724        viewData[0]=0;
1725        DataArrayView defaultValue(viewData,viewShape);
1726        DataTagged::TagListType keys;
1727        DataTagged::ValueListType values;
1728        DataTagged::DataMapType::const_iterator i;
1729        for (i=dataT->getTagLookup().begin();i!=dataT->getTagLookup().end();i++) {
1730          keys.push_back(i->first);
1731          values.push_back(defaultValue);
1732        }
1733        Data result(keys,values,defaultValue,getFunctionSpace());
1734      DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());      DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());
1735      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1736      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");
1737      escript::dp_algorithm(*dataT,*resultT,operation);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1738    } else if (data.isConstant()) {      return result;
1739      DataConstant* dataC=dynamic_cast<DataConstant*>(data.m_data.get());    } else if (isConstant()) {
1740        Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());
1741        DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1742      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1743      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1744      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1745      escript::dp_algorithm(*dataC,*resultC,operation);      escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1746        return result;
1747    }    }
1748    return result;    Data falseRetVal; // to keep compiler quiet
1749      return falseRetVal;
1750    }
1751    
1752    template <typename BinaryFunction>
1753    Data
1754    C_TensorBinaryOperation(Data const &arg_0,
1755                Data const &arg_1,
1756                BinaryFunction operation)
1757    {
1758      // Interpolate if necessary and find an appropriate function space
1759      Data arg_0_Z, arg_1_Z;
1760      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1761        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1762          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1763          arg_1_Z = Data(arg_1);
1764        }
1765        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1766          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1767          arg_0_Z =Data(arg_0);
1768        }
1769        else {
1770          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1771        }
1772      } else {
1773          arg_0_Z = Data(arg_0);
1774          arg_1_Z = Data(arg_1);
1775      }
1776      // Get rank and shape of inputs
1777      int rank0 = arg_0_Z.getDataPointRank();
1778      int rank1 = arg_1_Z.getDataPointRank();
1779      DataArrayView::ShapeType shape0 = arg_0_Z.getDataPointShape();
1780      DataArrayView::ShapeType shape1 = arg_1_Z.getDataPointShape();
1781      int size0 = arg_0_Z.getDataPointSize();
1782      int size1 = arg_1_Z.getDataPointSize();
1783    
1784      // Declare output Data object
1785      Data res;
1786    
1787      if (shape0 == shape1) {
1788    
1789        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1790          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());  // DataConstant output
1791          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1792          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1793          double *ptr_2 = &((res.getPointDataView().getData())[0]);
1794          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1795        }
1796        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1797    
1798          // Prepare the DataConstant input
1799          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1800    
1801          // Borrow DataTagged input from Data object
1802          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1803    
1804          // Prepare a DataTagged output 2
1805          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());  // DataTagged output
1806          res.tag();
1807          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1808    
1809          // Prepare offset into DataConstant
1810          int offset_0 = tmp_0->getPointOffset(0,0);
1811          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1812          // Get the views
1813          DataArrayView view_1 = tmp_1->getDefaultValue();
1814          DataArrayView view_2 = tmp_2->getDefaultValue();
1815          // Get the pointers to the actual data
1816          double *ptr_1 = &((view_1.getData())[0]);
1817          double *ptr_2 = &((view_2.getData())[0]);
1818          // Compute a result for the default
1819          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1820          // Compute a result for each tag
1821          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1822          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1823          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1824        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
1825        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1826        DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1827        double *ptr_1 = &view_1.getData(0);
1828        double *ptr_2 = &view_2.getData(0);
1829        tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1830          }
1831    
1832        }
1833        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1834    
1835          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1836          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1837          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1838          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1839    
1840          int sampleNo_1,dataPointNo_1;
1841          int numSamples_1 = arg_1_Z.getNumSamples();
1842          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1843          int offset_0 = tmp_0->getPointOffset(0,0);
1844          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1845          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1846        for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1847          int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1848          int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1849          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1850          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1851          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1852          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1853        }
1854          }
1855    
1856        }
1857        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1858    
1859          // Borrow DataTagged input from Data object
1860          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1861    
1862          // Prepare the DataConstant input
1863          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1864    
1865          // Prepare a DataTagged output 2
1866          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());  // DataTagged output
1867          res.tag();
1868          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1869    
1870          // Prepare offset into DataConstant
1871          int offset_1 = tmp_1->getPointOffset(0,0);
1872          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1873          // Get the views
1874          DataArrayView view_0 = tmp_0->getDefaultValue();
1875          DataArrayView view_2 = tmp_2->getDefaultValue();
1876          // Get the pointers to the actual data
1877          double *ptr_0 = &((view_0.getData())[0]);
1878          double *ptr_2 = &((view_2.getData())[0]);
1879          // Compute a result for the default
1880          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1881          // Compute a result for each tag
1882          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1883          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1884          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1885        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
1886        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1887        DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1888        double *ptr_0 = &view_0.getData(0);
1889        double *ptr_2 = &view_2.getData(0);
1890        tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1891          }
1892    
1893        }
1894        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1895    
1896          // Borrow DataTagged input from Data object
1897          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1898    
1899          // Borrow DataTagged input from Data object
1900          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1901    
1902          // Prepare a DataTagged output 2
1903          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1904          res.tag();    // DataTagged output
1905          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1906    
1907          // Get the views
1908          DataArrayView view_0 = tmp_0->getDefaultValue();
1909          DataArrayView view_1 = tmp_1->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_1 = &((view_1.getData())[0]);
1914          double *ptr_2 = &((view_2.getData())[0]);
1915          // Compute a result for the default
1916          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1917          // Merge the tags
1918          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1919          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1920          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1921          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1922        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue()); // use tmp_2 to get correct shape
1923          }
1924          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1925        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
1926          }
1927          // Compute a result for each tag
1928          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1929          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1930        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1931        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1932        DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1933        double *ptr_0 = &view_0.getData(0);
1934        double *ptr_1 = &view_1.getData(0);
1935        double *ptr_2 = &view_2.getData(0);
1936        tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1937          }
1938    
1939        }
1940        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
1941    
1942          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1943          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1944          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1945          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1946          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1947    
1948          int sampleNo_0,dataPointNo_0;
1949          int numSamples_0 = arg_0_Z.getNumSamples();
1950          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1951          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1952          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1953        int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
1954        double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1955        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1956          int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
1957          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1958          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1959          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1960          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1961        }
1962          }
1963    
1964        }
1965        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
1966    
1967          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1968          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
1969          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1970          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1971    
1972          int sampleNo_0,dataPointNo_0;
1973          int numSamples_0 = arg_0_Z.getNumSamples();
1974          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1975          int offset_1 = tmp_1->getPointOffset(0,0);
1976          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1977          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1978        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1979          int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
1980          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1981          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1982          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1983          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1984          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1985        }
1986          }
1987    
1988        }
1989        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
1990    
1991          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1992          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1993          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
1994          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1995          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1996    
1997          int sampleNo_0,dataPointNo_0;
1998          int numSamples_0 = arg_0_Z.getNumSamples();
1999          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2000          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2001          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2002        int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2003        double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2004        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2005          int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2006          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2007          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2008          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2009          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2010        }
2011          }
2012    
2013        }
2014        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2015    
2016          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2017          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2018          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2019          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2020          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2021    
2022          int sampleNo_0,dataPointNo_0;
2023          int numSamples_0 = arg_0_Z.getNumSamples();
2024          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2025          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2026          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2027        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2028          int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2029          int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2030          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2031          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2032          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2033          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2034          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2035        }
2036          }
2037    
2038        }
2039        else {
2040          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2041        }
2042    
2043      } else if (0 == rank0) {
2044    
2045        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2046          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());  // DataConstant output
2047          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2048          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
2049          double *ptr_2 = &((res.getPointDataView().getData())[0]);
2050          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2051        }
2052        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2053    
2054          // Prepare the DataConstant input
2055          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2056    
2057          // Borrow DataTagged input from Data object
2058          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2059    
2060          // Prepare a DataTagged output 2
2061          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());  // DataTagged output
2062          res.tag();
2063          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2064    
2065          // Prepare offset into DataConstant
2066          int offset_0 = tmp_0->getPointOffset(0,0);
2067          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2068          // Get the views
2069          DataArrayView view_1 = tmp_1->getDefaultValue();
2070          DataArrayView view_2 = tmp_2->getDefaultValue();
2071          // Get the pointers to the actual data
2072          double *ptr_1 = &((view_1.getData())[0]);
2073          double *ptr_2 = &((view_2.getData())[0]);
2074          // Compute a result for the default
2075          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2076          // Compute a result for each tag
2077          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2078          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2079          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2080        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2081        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2082        DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2083        double *ptr_1 = &view_1.getData(0);
2084        double *ptr_2 = &view_2.getData(0);
2085        tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2086          }
2087    
2088        }
2089        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2090    
2091          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2092          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2093          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2094          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2095    
2096          int sampleNo_1,dataPointNo_1;
2097          int numSamples_1 = arg_1_Z.getNumSamples();
2098          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2099          int offset_0 = tmp_0->getPointOffset(0,0);
2100          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2101          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2102        for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2103          int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2104          int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2105          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2106          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2107          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2108          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2109    
2110        }
2111          }
2112    
2113        }
2114        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2115    
2116          // Borrow DataTagged input from Data object
2117          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2118    
2119          // Prepare the DataConstant input
2120          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2121    
2122          // Prepare a DataTagged output 2
2123          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());  // DataTagged output
2124          res.tag();
2125          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2126    
2127          // Prepare offset into DataConstant
2128          int offset_1 = tmp_1->getPointOffset(0,0);
2129          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2130          // Get the views
2131          DataArrayView view_0 = tmp_0->getDefaultValue();
2132          DataArrayView view_2 = tmp_2->getDefaultValue();
2133          // Get the pointers to the actual data
2134          double *ptr_0 = &((view_0.getData())[0]);
2135          double *ptr_2 = &((view_2.getData())[0]);
2136          // Compute a result for the default
2137          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2138          // Compute a result for each tag
2139          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2140          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2141          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2142        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2143        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2144        DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2145        double *ptr_0 = &view_0.getData(0);
2146        double *ptr_2 = &view_2.getData(0);
2147        tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2148          }
2149    
2150        }
2151        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2152    
2153          // Borrow DataTagged input from Data object
2154          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2155    
2156          // Borrow DataTagged input from Data object
2157          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2158    
2159          // Prepare a DataTagged output 2
2160          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2161          res.tag();    // DataTagged output
2162          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2163    
2164          // Get the views
2165          DataArrayView view_0 = tmp_0->getDefaultValue();
2166          DataArrayView view_1 = tmp_1->getDefaultValue();
2167          DataArrayView view_2 = tmp_2->getDefaultValue();
2168          // Get the pointers to the actual data
2169          double *ptr_0 = &((view_0.getData())[0]);
2170          double *ptr_1 = &((view_1.getData())[0]);
2171          double *ptr_2 = &((view_2.getData())[0]);
2172          // Compute a result for the default
2173          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2174          // Merge the tags
2175          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2176          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2177          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2178          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2179        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue()); // use tmp_2 to get correct shape
2180          }
2181          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2182        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2183          }
2184          // Compute a result for each tag
2185          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2186          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2187        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2188        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2189        DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2190        double *ptr_0 = &view_0.getData(0);
2191        double *ptr_1 = &view_1.getData(0);
2192        double *ptr_2 = &view_2.getData(0);
2193        tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2194          }
2195    
2196        }
2197        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2198    
2199          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2200          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2201          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2202          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2203          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2204    
2205          int sampleNo_0,dataPointNo_0;
2206          int numSamples_0 = arg_0_Z.getNumSamples();
2207          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2208          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2209          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2210        int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2211        double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2212        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2213          int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2214          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2215          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2216          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2217          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2218        }
2219          }
2220    
2221        }
2222        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2223    
2224          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2225          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2226          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2227          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2228    
2229          int sampleNo_0,dataPointNo_0;
2230          int numSamples_0 = arg_0_Z.getNumSamples();
2231          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2232          int offset_1 = tmp_1->getPointOffset(0,0);
2233          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2234          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2235        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2236          int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2237          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2238          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2239          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2240          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2241          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2242        }
2243          }
2244    
2245    
2246        }
2247        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2248    
2249          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2250          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2251          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2252          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2253          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2254    
2255          int sampleNo_0,dataPointNo_0;
2256          int numSamples_0 = arg_0_Z.getNumSamples();
2257          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2258          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2259          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2260        int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2261        double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2262        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2263          int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2264          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2265          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2266          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2267          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2268        }
2269          }
2270    
2271        }
2272        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2273    
2274          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2275          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2276          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2277          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2278          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2279    
2280          int sampleNo_0,dataPointNo_0;
2281          int numSamples_0 = arg_0_Z.getNumSamples();
2282          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2283          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2284          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2285        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2286          int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2287          int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2288          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2289          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2290          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2291          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2292          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2293        }
2294          }
2295    
2296        }
2297        else {
2298          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2299        }
2300    
2301      } else if (0 == rank1) {
2302    
2303        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2304          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());  // DataConstant output
2305          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2306          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
2307          double *ptr_2 = &((res.getPointDataView().getData())[0]);
2308          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2309        }
2310        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2311    
2312          // Prepare the DataConstant input
2313          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2314    
2315          // Borrow DataTagged input from Data object
2316          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2317    
2318          // Prepare a DataTagged output 2
2319          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());  // DataTagged output
2320          res.tag();
2321          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2322    
2323          // Prepare offset into DataConstant
2324          int offset_0 = tmp_0->getPointOffset(0,0);
2325          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2326          // Get the views
2327          DataArrayView view_1 = tmp_1->getDefaultValue();
2328          DataArrayView view_2 = tmp_2->getDefaultValue();
2329          // Get the pointers to the actual data
2330          double *ptr_1 = &((view_1.getData())[0]);
2331          double *ptr_2 = &((view_2.getData())[0]);
2332          // Compute a result for the default
2333          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2334          // Compute a result for each tag
2335          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2336          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2337          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2338        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2339        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2340        DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2341        double *ptr_1 = &view_1.getData(0);
2342        double *ptr_2 = &view_2.getData(0);
2343        tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2344          }
2345    
2346        }
2347        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2348    
2349          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2350          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2351          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2352          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2353    
2354          int sampleNo_1,dataPointNo_1;
2355          int numSamples_1 = arg_1_Z.getNumSamples();
2356          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2357          int offset_0 = tmp_0->getPointOffset(0,0);
2358          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2359          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2360        for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2361          int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2362          int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2363          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2364          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2365          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2366          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2367        }
2368          }
2369    
2370        }
2371        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2372    
2373          // Borrow DataTagged input from Data object
2374          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2375    
2376          // Prepare the DataConstant input
2377          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2378    
2379          // Prepare a DataTagged output 2
2380          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());  // DataTagged output
2381          res.tag();
2382          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2383    
2384          // Prepare offset into DataConstant
2385          int offset_1 = tmp_1->getPointOffset(0,0);
2386          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2387          // Get the views
2388          DataArrayView view_0 = tmp_0->getDefaultValue();
2389          DataArrayView view_2 = tmp_2->getDefaultValue();
2390          // Get the pointers to the actual data
2391          double *ptr_0 = &((view_0.getData())[0]);
2392          double *ptr_2 = &((view_2.getData())[0]);
2393          // Compute a result for the default
2394          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2395          // Compute a result for each tag
2396          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2397          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2398          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2399        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2400        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2401        DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2402        double *ptr_0 = &view_0.getData(0);
2403        double *ptr_2 = &view_2.getData(0);
2404        tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2405          }
2406    
2407        }
2408        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2409    
2410          // Borrow DataTagged input from Data object
2411          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2412    
2413          // Borrow DataTagged input from Data object
2414          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2415    
2416          // Prepare a DataTagged output 2
2417          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2418          res.tag();    // DataTagged output
2419          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2420    
2421          // Get the views
2422          DataArrayView view_0 = tmp_0->getDefaultValue();
2423          DataArrayView view_1 = tmp_1->getDefaultValue();
2424          DataArrayView view_2 = tmp_2->getDefaultValue();
2425          // Get the pointers to the actual data
2426          double *ptr_0 = &((view_0.getData())[0]);
2427          double *ptr_1 = &((view_1.getData())[0]);
2428          double *ptr_2 = &((view_2.getData())[0]);
2429          // Compute a result for the default
2430          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2431          // Merge the tags
2432          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2433          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2434          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2435          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2436        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue()); // use tmp_2 to get correct shape
2437          }
2438          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2439        tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2440          }
2441          // Compute a result for each tag
2442          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2443          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2444        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2445        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2446        DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2447        double *ptr_0 = &view_0.getData(0);
2448        double *ptr_1 = &view_1.getData(0);
2449        double *ptr_2 = &view_2.getData(0);
2450        tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2451          }
2452    
2453        }
2454        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2455    
2456          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2457          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2458          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2459          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2460          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2461    
2462          int sampleNo_0,dataPointNo_0;
2463          int numSamples_0 = arg_0_Z.getNumSamples();
2464          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2465          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2466          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2467        int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2468        double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2469        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2470          int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2471          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2472          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2473          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2474          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2475        }
2476          }
2477    
2478        }
2479        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2480    
2481          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2482          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2483          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2484          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2485    
2486          int sampleNo_0,dataPointNo_0;
2487          int numSamples_0 = arg_0_Z.getNumSamples();
2488          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2489          int offset_1 = tmp_1->getPointOffset(0,0);
2490          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2491          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2492        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2493          int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2494          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2495          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2496          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2497          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2498          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2499        }
2500          }
2501    
2502    
2503        }
2504        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2505    
2506          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2507          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2508          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2509          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2510          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2511    
2512          int sampleNo_0,dataPointNo_0;
2513          int numSamples_0 = arg_0_Z.getNumSamples();
2514          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2515          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2516          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2517        int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2518        double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2519        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2520          int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2521          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2522          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2523          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2524          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2525        }
2526          }
2527    
2528        }
2529        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2530    
2531          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2532          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2533          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2534          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2535          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2536    
2537          int sampleNo_0,dataPointNo_0;
2538          int numSamples_0 = arg_0_Z.getNumSamples();
2539          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2540          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2541          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2542        for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2543          int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2544          int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2545          int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2546          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2547          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2548          double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2549          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2550        }
2551          }
2552    
2553        }
2554        else {
2555          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2556        }
2557    
2558      } else {
2559        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2560      }
2561    
2562      return res;
2563  }  }
2564    
2565  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26