/[escript]/branches/schroedinger/escript/src/Data.h
ViewVC logotype

Diff of /branches/schroedinger/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.94  
changed lines
  Added in v.1358

  ViewVC Help
Powered by ViewVC 1.1.26