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

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

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

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

Legend:
Removed from v.121  
changed lines
  Added in v.1693

  ViewVC Help
Powered by ViewVC 1.1.26