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

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

  ViewVC Help
Powered by ViewVC 1.1.26