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

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

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

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

Legend:
Removed from v.698  
changed lines
  Added in v.1430

  ViewVC Help
Powered by ViewVC 1.1.26