/[escript]/trunk/escript/src/Data.h
ViewVC logotype

Diff of /trunk/escript/src/Data.h

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

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

Legend:
Removed from v.106  
changed lines
  Added in v.1748

  ViewVC Help
Powered by ViewVC 1.1.26