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

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

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

trunk/escript/src/Data.h revision 698 by gross, Fri Mar 31 04:52:55 2006 UTC branches/more_shared_ptrs_from_1812/escript/src/Data.h revision 1822 by jfenwick, Wed Oct 1 05:42:31 2008 UTC
# Line 1  Line 1 
1  // $Id$  
2  /*  /*******************************************************
3   ************************************************************  *
4   *          Copyright 2006 by ACcESS MNRF                   *  * Copyright (c) 2003-2008 by University of Queensland
5   *                                                          *  * Earth Systems Science Computational Center (ESSCC)
6   *              http://www.access.edu.au                    *  * http://www.uq.edu.au/esscc
7   *       Primary Business: Queensland, Australia            *  *
8   *  Licensed under the Open Software License version 3.0    *  * Primary Business: Queensland, Australia
9   *     http://www.opensource.org/licenses/osl-3.0.php       *  * Licensed under the Open Software License version 3.0
10   *                                                          *  * http://www.opensource.org/licenses/osl-3.0.php
11   ************************************************************  *
12  */  *******************************************************/
13    
14    
15  /** \file Data.h */  /** \file Data.h */
16    
17  #ifndef DATA_H  #ifndef DATA_H
18  #define DATA_H  #define DATA_H
19    #include "system_dep.h"
20    
21  #include "DataAbstract.h"  #include "DataAbstract.h"
22  #include "DataAlgorithm.h"  #include "DataAlgorithm.h"
# Line 22  Line 24 
24  #include "BinaryOp.h"  #include "BinaryOp.h"
25  #include "UnaryOp.h"  #include "UnaryOp.h"
26  #include "DataException.h"  #include "DataException.h"
27    #include "DataTypes.h"
28    
29  extern "C" {  extern "C" {
30  #include "DataC.h"  #include "DataC.h"
31    /* #include "paso/Paso.h" doesn't belong in this file...causes trouble for BruceFactory.cpp */
32  }  }
33    
34    #include "esysmpi.h"
35  #include <string>  #include <string>
36  #include <algorithm>  #include <algorithm>
37    #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>
# Line 45  class DataExpanded; Line 52  class DataExpanded;
52    
53  /**  /**
54     \brief     \brief
55     Data creates the appropriate Data object for the given construction     Data represents a collection of datapoints.
    arguments.  
56    
57     Description:     Description:
58     Data is essentially a factory class which creates the appropriate Data     Internally, the datapoints are actually stored by a DataAbstract object.
59     object for the given construction arguments. It retains control over     The specific instance of DataAbstract used may vary over the lifetime
60     the object created for the lifetime of the object.     of the Data object.
61     The type of Data object referred to may change during the lifetime of     Some methods on this class return references (eg getShape()).
62     the Data object.     These references should not be used after an operation which changes the underlying DataAbstract object.
63       Doing so will lead to invalid memory access.
64       This should not affect any methods exposed via boost::python.
65  */  */
66  class Data {  class Data {
67    
# Line 64  class Data { Line 72  class Data {
72    typedef double (*UnaryDFunPtr)(double);    typedef double (*UnaryDFunPtr)(double);
73    typedef double (*BinaryDFunPtr)(double,double);    typedef double (*BinaryDFunPtr)(double,double);
74    
75    
76    /**    /**
77       Constructors.       Constructors.
78    */    */
# Line 73  class Data { Line 82  class Data {
82       Default constructor.       Default constructor.
83       Creates a DataEmpty object.       Creates a DataEmpty object.
84    */    */
85      ESCRIPT_DLL_API
86    Data();    Data();
87    
88    /**    /**
# Line 80  class Data { Line 90  class Data {
90       Copy constructor.       Copy constructor.
91       WARNING: Only performs a shallow copy.       WARNING: Only performs a shallow copy.
92    */    */
93      ESCRIPT_DLL_API
94    Data(const Data& inData);    Data(const Data& inData);
95    
96    /**    /**
# Line 88  class Data { Line 99  class Data {
99       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,
100       otherwise a shallow copy of inData is returned.       otherwise a shallow copy of inData is returned.
101    */    */
102      ESCRIPT_DLL_API
103    Data(const Data& inData,    Data(const Data& inData,
104         const FunctionSpace& what);         const FunctionSpace& what);
105    
106    /**    /**
107       \brief      \brief Copy Data from an existing vector
108       Constructor which copies data from a DataArrayView.    */
109    
110       \param value - Input - Data value for a single point.    ESCRIPT_DLL_API
111       \param what - Input - A description of what this data represents.    Data(const DataTypes::ValueType& value,
112       \param expanded - Input - Flag, if true fill the entire container with           const DataTypes::ShapeType& shape,
113                         the value. Otherwise a more efficient storage                   const FunctionSpace& what=FunctionSpace(),
114                         mechanism will be used.                   bool expanded=false);
   */  
   Data(const DataArrayView& value,  
        const FunctionSpace& what=FunctionSpace(),  
        bool expanded=false);  
115    
116    /**    /**
117       \brief       \brief
# Line 116  class Data { Line 124  class Data {
124                         the given value. Otherwise a more efficient storage                         the given value. Otherwise a more efficient storage
125                         mechanism will be used.                         mechanism will be used.
126    */    */
127      ESCRIPT_DLL_API
128    Data(double value,    Data(double value,
129         const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(),         const DataTypes::ShapeType& dataPointShape=DataTypes::ShapeType(),
130         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
131         bool expanded=false);         bool expanded=false);
132    
# Line 128  class Data { Line 137  class Data {
137       \param inData - Input - Input Data object.       \param inData - Input - Input Data object.
138       \param region - Input - Region to copy.       \param region - Input - Region to copy.
139    */    */
140      ESCRIPT_DLL_API
141    Data(const Data& inData,    Data(const Data& inData,
142         const DataArrayView::RegionType& region);         const DataTypes::RegionType& region);
   
   /**  
      \brief  
      Constructor which will create Tagged data if expanded is false.  
      No attempt is made to ensure the tag keys match the tag keys  
      within the function space.  
   
      \param tagKeys - Input - List of tag values.  
      \param values - Input - List of values, one for each tag.  
      \param defaultValue - Input - A default value, used if tag doesn't exist.  
      \param what - Input - A description of what this data represents.  
      \param expanded - Input - Flag, if true fill the entire container with  
                        the appropriate values.  
     ==>*  
   */  
   Data(const DataTagged::TagListType& tagKeys,  
        const DataTagged::ValueListType& values,  
        const DataArrayView& defaultValue,  
        const FunctionSpace& what=FunctionSpace(),  
        bool expanded=false);  
143    
144    /**    /**
145       \brief       \brief
# Line 161  class Data { Line 151  class Data {
151                         the value. Otherwise a more efficient storage                         the value. Otherwise a more efficient storage
152                         mechanism will be used.                         mechanism will be used.
153    */    */
154      ESCRIPT_DLL_API
155    Data(const boost::python::numeric::array& value,    Data(const boost::python::numeric::array& value,
156         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
157         bool expanded=false);         bool expanded=false);
# Line 176  class Data { Line 167  class Data {
167                         the value. Otherwise a more efficient storage                         the value. Otherwise a more efficient storage
168                         mechanism will be used.                         mechanism will be used.
169    */    */
170      ESCRIPT_DLL_API
171    Data(const boost::python::object& value,    Data(const boost::python::object& value,
172         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
173         bool expanded=false);         bool expanded=false);
# Line 189  class Data { Line 181  class Data {
181       \param value - Input - Input data.       \param value - Input - Input data.
182       \param other - Input - contains all other parameters.       \param other - Input - contains all other parameters.
183    */    */
184      ESCRIPT_DLL_API
185    Data(const boost::python::object& value,    Data(const boost::python::object& value,
186         const Data& other);         const Data& other);
187    
# Line 196  class Data { Line 189  class Data {
189       \brief       \brief
190       Constructor which creates a DataConstant of "shape" with constant value.       Constructor which creates a DataConstant of "shape" with constant value.
191    */    */
192    Data(double value,    ESCRIPT_DLL_API
193         const boost::python::tuple& shape=boost::python::make_tuple(),    Data(double value,
194           const boost::python::tuple& shape=boost::python::make_tuple(),
195         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
196         bool expanded=false);         bool expanded=false);
197    
198    
199    
200      /**
201        \brief Create a Data using an existing DataAbstract. Warning: The new object assumes ownership of the pointer!
202        Once you have passed the pointer, do not delete it.
203      */
204      ESCRIPT_DLL_API
205      Data(DataAbstract* underlyingdata);
206    
207    
208    /**    /**
209       \brief       \brief
210       Destructor       Destructor
211    */    */
212      ESCRIPT_DLL_API
213    ~Data();    ~Data();
214    
215    /**    /**
216       \brief       \brief Make this object a deep copy of "other".
      Perform a deep copy.  
217    */    */
218      ESCRIPT_DLL_API
219    void    void
220    copy(const Data& other);    copy(const Data& other);
221    
222    /**    /**
223         \brief Return a pointer to a deep copy of this object.
224      */
225      ESCRIPT_DLL_API
226      Data*
227      copySelf();
228    
229    
230    
231    
232      /**
233       Member access methods.       Member access methods.
234    */    */
235    
236    /**    /**
237       \brief       \brief
238       Return the values of all data-points as a single python numarray object.       switches on update protection
239    
240    */    */
241    const boost::python::numeric::array    ESCRIPT_DLL_API
242    convertToNumArray();    void
243      setProtection();
244    
245    /**    /**
246       \brief       \brief
247       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
248    
249    */    */
250    const boost::python::numeric::array    ESCRIPT_DLL_API
251    convertToNumArrayFromSampleNo(int sampleNo);    bool
252      isProtected() const;
253    
254    /**    /**
255       \brief       \brief
256       Return the value of the specified data-point as a single python numarray object.       Return the values of a data point on this process
257    */    */
258      ESCRIPT_DLL_API
259    const boost::python::numeric::array    const boost::python::numeric::array
260    convertToNumArrayFromDPNo(int sampleNo,    getValueOfDataPoint(int dataPointNo);
                             int dataPointNo);  
261    
262    /**    /**
263       \brief       \brief
264       Fills the expanded Data object from values of a python numarray object.       sets the values of a data-point from a python object on this process
265    */    */
266      ESCRIPT_DLL_API
267    void    void
268    fillFromNumArray(const boost::python::numeric::array);    setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
269    
270      /**
271         \brief
272         sets the values of a data-point from a numarray object on this process
273      */
274      ESCRIPT_DLL_API
275      void
276      setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
277    
278      /**
279         \brief
280         sets the values of a data-point on this process
281      */
282      ESCRIPT_DLL_API
283      void
284      setValueOfDataPoint(int dataPointNo, const double);
285    
286      /**
287         \brief
288         Return the value of the specified data-point across all processors
289      */
290      ESCRIPT_DLL_API
291      const boost::python::numeric::array
292      getValueOfGlobalDataPoint(int procNo, int dataPointNo);
293    
294    /**    /**
295       \brief       \brief
296       Return the tag number associated with the given data-point.       Return the tag number associated with the given data-point.
297    
      The data-point number here corresponds to the data-point number in the  
      numarray returned by convertToNumArray.  
298    */    */
299      ESCRIPT_DLL_API
300    int    int
301    getTagNumber(int dpno);    getTagNumber(int dpno);
302    
# Line 260  class Data { Line 304  class Data {
304       \brief       \brief
305       Return the C wrapper for the Data object.       Return the C wrapper for the Data object.
306    */    */
307      ESCRIPT_DLL_API
308    escriptDataC    escriptDataC
309    getDataC();    getDataC();
310    
311    
312    
313    
314    
315    
316    // REMOVE ME
317    // ESCRIPT_DLL_API
318    // void
319    // CompareDebug(const Data& rd);
320    
321    
322    /**    /**
323       \brief       \brief
324       Return the C wrapper for the Data object - const version.       Return the C wrapper for the Data object - const version.
325    */    */
326      ESCRIPT_DLL_API
327    escriptDataC    escriptDataC
328    getDataC() const;    getDataC() const;
329    
330    /**    /**
331       \brief       \brief
332       Write the data as a string.       Write the data as a string. For large amounts of data, a summary is printed.
333    */    */
334    inline    ESCRIPT_DLL_API
335    std::string    std::string
336    toString() const    toString() const;
   {  
     return m_data->toString();  
   }  
337    
338    /**  
339       \brief  //  /**
340    /*     \brief
341       Return the DataArrayView of the point data. This essentially contains       Return the DataArrayView of the point data. This essentially contains
342       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
343       to manipulate the point data.       to manipulate the point data.*/
344    */  //  */
345    inline  //   ESCRIPT_DLL_API
346    const DataArrayView&  //   inline
347    getPointDataView() const  //   const DataArrayView&
348    {  //   getPointDataView() const
349       return m_data->getPointDataView();  //   {
350    }  //      return m_data->getPointDataView();
351    //   }
352    
353    /**    /**
354       \brief       \brief
355       Whatever the current Data type make this into a DataExpanded.       Whatever the current Data type make this into a DataExpanded.
356    */    */
357      ESCRIPT_DLL_API
358    void    void
359    expand();    expand();
360    
# Line 308  class Data { Line 365  class Data {
365       Expanded data to tagged will throw an exception.       Expanded data to tagged will throw an exception.
366      ==>*      ==>*
367    */    */
368      ESCRIPT_DLL_API
369    void    void
370    tag();    tag();
371    
# Line 315  class Data { Line 373  class Data {
373       \brief       \brief
374       Return true if this Data is expanded.       Return true if this Data is expanded.
375    */    */
376      ESCRIPT_DLL_API
377    bool    bool
378    isExpanded() const;    isExpanded() const;
379    
# Line 322  class Data { Line 381  class Data {
381       \brief       \brief
382       Return true if this Data is tagged.       Return true if this Data is tagged.
383    */    */
384      ESCRIPT_DLL_API
385    bool    bool
386    isTagged() const;    isTagged() const;
387    
# Line 329  class Data { Line 389  class Data {
389       \brief       \brief
390       Return true if this Data is constant.       Return true if this Data is constant.
391    */    */
392      ESCRIPT_DLL_API
393    bool    bool
394    isConstant() const;    isConstant() const;
395    
396    /**    /**
397       \brief       \brief
398       Return true if this Data is empty.       Return true if this Data holds an instance of DataEmpty. This is _not_ the same as asking if the object
399    contains datapoints.
400    */    */
401      ESCRIPT_DLL_API
402    bool    bool
403    isEmpty() const;    isEmpty() const;
404    
# Line 343  class Data { Line 406  class Data {
406       \brief       \brief
407       Return the function space.       Return the function space.
408    */    */
409      ESCRIPT_DLL_API
410    inline    inline
411    const FunctionSpace&    const FunctionSpace&
412    getFunctionSpace() const    getFunctionSpace() const
# Line 354  class Data { Line 418  class Data {
418       \brief       \brief
419       Return a copy of the function space.       Return a copy of the function space.
420    */    */
421      ESCRIPT_DLL_API
422    const FunctionSpace    const FunctionSpace
423    getCopyOfFunctionSpace() const;    getCopyOfFunctionSpace() const;
424    
# Line 361  class Data { Line 426  class Data {
426       \brief       \brief
427       Return the domain.       Return the domain.
428    */    */
429      ESCRIPT_DLL_API
430    inline    inline
431    const AbstractDomain&  //   const AbstractDomain&
432      const_Domain_ptr
433    getDomain() const    getDomain() const
434    {    {
435       return getFunctionSpace().getDomain();       return getFunctionSpace().getDomain();
436    }    }
437    
438    
439      /**
440         \brief
441         Return the domain.
442         TODO: For internal use only.   This should be removed.
443      */
444      ESCRIPT_DLL_API
445      inline
446    //   const AbstractDomain&
447      Domain_ptr
448      getDomainPython() const
449      {
450         return getFunctionSpace().getDomainPython();
451      }
452    
453    /**    /**
454       \brief       \brief
455       Return a copy of the domain.       Return a copy of the domain.
456    */    */
457      ESCRIPT_DLL_API
458    const AbstractDomain    const AbstractDomain
459    getCopyOfDomain() const;    getCopyOfDomain() const;
460    
# Line 379  class Data { Line 462  class Data {
462       \brief       \brief
463       Return the rank of the point data.       Return the rank of the point data.
464    */    */
465      ESCRIPT_DLL_API
466    inline    inline
467    int    int
468    getDataPointRank() const    getDataPointRank() const
469    {    {
470      return m_data->getPointDataView().getRank();  //    return m_data->getPointDataView().getRank();
471        return m_data->getRank();
472    }    }
473    
474    /**    /**
475       \brief       \brief
476         Return the number of data points
477      */
478      ESCRIPT_DLL_API
479      inline
480      int
481      getNumDataPoints() const
482      {
483        return getNumSamples() * getNumDataPointsPerSample();
484      }
485      /**
486         \brief
487       Return the number of samples.       Return the number of samples.
488    */    */
489      ESCRIPT_DLL_API
490    inline    inline
491    int    int
492    getNumSamples() const    getNumSamples() const
# Line 401  class Data { Line 498  class Data {
498       \brief       \brief
499       Return the number of data points per sample.       Return the number of data points per sample.
500    */    */
501      ESCRIPT_DLL_API
502    inline    inline
503    int    int
504    getNumDataPointsPerSample() const    getNumDataPointsPerSample() const
# Line 408  class Data { Line 506  class Data {
506      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
507    }    }
508    
509    
510      /**
511        \brief
512        Return the number of values in the shape for this object.
513      */
514      ESCRIPT_DLL_API
515      int
516      getNoValues() const
517      {
518        return m_data->getNoValues();
519      }
520    
521    
522      /**
523         \brief
524         dumps the object into a netCDF file
525      */
526      ESCRIPT_DLL_API
527      void
528      dump(const std::string fileName) const;
529    /**    /**
530       \brief       \brief
531       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
532       preferred interface but is provided for use by C code.       preferred interface but is provided for use by C code.
533       \param sampleNo - Input - the given sample no.       \param sampleNo - Input - the given sample no.
534    */    */
535      ESCRIPT_DLL_API
536    inline    inline
537    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
538    getSampleData(DataAbstract::ValueType::size_type sampleNo)    getSampleData(DataAbstract::ValueType::size_type sampleNo)
# Line 427  class Data { Line 546  class Data {
546       access data that isn't tagged an exception will be thrown.       access data that isn't tagged an exception will be thrown.
547       \param tag - Input - the tag key.       \param tag - Input - the tag key.
548    */    */
549      ESCRIPT_DLL_API
550    inline    inline
551    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
552    getSampleDataByTag(int tag)    getSampleDataByTag(int tag)
# Line 434  class Data { Line 554  class Data {
554      return m_data->getSampleDataByTag(tag);      return m_data->getSampleDataByTag(tag);
555    }    }
556    
557    /**  //  /**
558       \brief  /*     \brief
559       Assign the given value to the data-points referenced by the given       Return a view into the data for the data point specified.
560       reference number.       NOTE: Construction of the DataArrayView is a relatively expensive
561         operation.
562       The value supplied is a python numarray object.  The data from this numarray       \param sampleNo - Input -
563       is unpacked into a DataArray, and this is used to set the corresponding       \param dataPointNo - Input -*/
564       data-points in the underlying Data object.  //  */
565    //   ESCRIPT_DLL_API
566       If the underlying Data object cannot be accessed via reference numbers, an  //   inline
567       exception will be thrown.  //   DataArrayView
568    //   getDataPoint(int sampleNo,
569       \param ref - Input - reference number.  //                int dataPointNo)
570       \param value - Input - value to assign to data-points associated with  //   {
571                              the given reference number.  //                 return m_data->getDataPoint(sampleNo,dataPointNo);
572    */  //   }
   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.  
573    
      \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);  
574    
575    /**    /**
576       \brief       \brief
# Line 481  class Data { Line 580  class Data {
580       \param sampleNo - Input -       \param sampleNo - Input -
581       \param dataPointNo - Input -       \param dataPointNo - Input -
582    */    */
583      ESCRIPT_DLL_API
584      DataTypes::ValueType::const_reference
585      getDataPoint(int sampleNo, int dataPointNo) const;
586    
587    
588      ESCRIPT_DLL_API
589      DataTypes::ValueType::reference
590      getDataPoint(int sampleNo, int dataPointNo);
591    
592    
593    
594      /**
595         \brief
596         Return the offset for the given sample and point within the sample
597      */
598      ESCRIPT_DLL_API
599    inline    inline
600    DataArrayView    DataTypes::ValueType::size_type
601    getDataPoint(int sampleNo,    getDataOffset(int sampleNo,
602                 int dataPointNo)                 int dataPointNo)
603    {    {
604      return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getPointOffset(sampleNo,dataPointNo);
605    }    }
606    
607    /**    /**
608       \brief       \brief
609       Return a reference to the data point shape.       Return a reference to the data point shape.
610    */    */
611    const DataArrayView::ShapeType&    ESCRIPT_DLL_API
612    getDataPointShape() const;    inline
613      const DataTypes::ShapeType&
614      getDataPointShape() const
615      {
616        return m_data->getShape();
617      }
618    
619    /**    /**
620       \brief       \brief
621       Return the data point shape as a tuple of integers.       Return the data point shape as a tuple of integers.
622    */    */
623      ESCRIPT_DLL_API
624    const boost::python::tuple    const boost::python::tuple
625    getShapeTuple() const;    getShapeTuple() const;
626    
# Line 508  class Data { Line 629  class Data {
629       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
630       data point shape dimensions.       data point shape dimensions.
631    */    */
632      ESCRIPT_DLL_API
633    int    int
634    getDataPointSize() const;    getDataPointSize() const;
635    
# Line 515  class Data { Line 637  class Data {
637       \brief       \brief
638       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
639    */    */
640    DataArrayView::ValueType::size_type    ESCRIPT_DLL_API
641      DataTypes::ValueType::size_type
642    getLength() const;    getLength() const;
643    
644    
645    
646    /**    /**
647       \brief       \brief
648       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag assocciated with name. Implicitly converts this
649       object to type DataTagged. Throws an exception if this object       object to type DataTagged. Throws an exception if this object
650       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
651       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
652       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
653      ==>*      ==>*
654    */    */
655      ESCRIPT_DLL_API
656      void
657      setTaggedValueByName(std::string name,
658                           const boost::python::object& value);
659    
660      /**
661         \brief
662         Assign the given value to the tag. Implicitly converts this
663         object to type DataTagged if it is constant.
664    
665         \param tagKey - Input - Integer key.
666         \param value - Input - Value to associate with given key.
667        ==>*
668      */
669      ESCRIPT_DLL_API
670    void    void
671    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
672                   const boost::python::object& value);                   const boost::python::object& value);
673    
674    
675    //  /**
676    //     \brief
677    //     Assign the given value to the tag. Implicitly converts this
678    //     object to type DataTagged if it is constant.
679    //
680    //     \param tagKey - Input - Integer key.
681    //     \param value - Input - Value to associate with given key.
682    //    ==>*
683    //  */
684    //   ESCRIPT_DLL_API
685    //   void
686    //   setTaggedValueFromCPP(int tagKey,
687    //                         const DataArrayView& value);
688    
689    /**    /**
690       \brief       \brief
691       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
692       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
693       cannot be converted to a DataTagged object.  
694       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
695         \param pointshape - Input - The shape of the value parameter
696       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
697      ==>*       \param dataOffset - Input - Offset of the begining of the point within the value parameter
698    */    */
699      ESCRIPT_DLL_API
700    void    void
701    setTaggedValueFromCPP(int tagKey,    setTaggedValueFromCPP(int tagKey,
702                          const DataArrayView& value);              const DataTypes::ShapeType& pointshape,
703                            const DataTypes::ValueType& value,
704                int dataOffset=0);
705    
706    
707    
708    /**    /**
709      \brief      \brief
710      Copy other Data object into this Data object where mask is positive.      Copy other Data object into this Data object where mask is positive.
711    */    */
712      ESCRIPT_DLL_API
713    void    void
714    copyWithMask(const Data& other,    copyWithMask(const Data& other,
715                 const Data& mask);                 const Data& mask);
# Line 558  class Data { Line 720  class Data {
720    
721    /**    /**
722       \brief       \brief
723         set all values to zero
724         *
725      */
726      ESCRIPT_DLL_API
727      void
728      setToZero();
729    
730      /**
731         \brief
732       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
733       the result as a Data object.       the result as a Data object.
734       *       *
735    */    */
736      ESCRIPT_DLL_API
737    Data    Data
738    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
739    /**    /**
740       \brief       \brief
741       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
742       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.
743       *       *
744    */    */
745      ESCRIPT_DLL_API
746    Data    Data
747    gradOn(const FunctionSpace& functionspace) const;    gradOn(const FunctionSpace& functionspace) const;
748    
749      ESCRIPT_DLL_API
750    Data    Data
751    grad() const;    grad() const;
752    
# Line 582  class Data { Line 755  class Data {
755       Calculate the integral over the function space domain.       Calculate the integral over the function space domain.
756       *       *
757    */    */
758      ESCRIPT_DLL_API
759    boost::python::numeric::array    boost::python::numeric::array
760    integrate() const;    integrate() const;
761    
762    /**    /**
763       \brief       \brief
764         Returns 1./ Data object
765         *
766      */
767      ESCRIPT_DLL_API
768      Data
769      oneOver() const;
770      /**
771         \brief
772       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.
773       *       *
774    */    */
775      ESCRIPT_DLL_API
776    Data    Data
777    wherePositive() const;    wherePositive() const;
778    
# Line 598  class Data { Line 781  class Data {
781       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.
782       *       *
783    */    */
784      ESCRIPT_DLL_API
785    Data    Data
786    whereNegative() const;    whereNegative() const;
787    
# Line 606  class Data { Line 790  class Data {
790       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.
791       *       *
792    */    */
793      ESCRIPT_DLL_API
794    Data    Data
795    whereNonNegative() const;    whereNonNegative() const;
796    
# Line 614  class Data { Line 799  class Data {
799       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.
800       *       *
801    */    */
802      ESCRIPT_DLL_API
803    Data    Data
804    whereNonPositive() const;    whereNonPositive() const;
805    
# Line 622  class Data { Line 808  class Data {
808       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.
809       *       *
810    */    */
811      ESCRIPT_DLL_API
812    Data    Data
813    whereZero(double tol=0.0) const;    whereZero(double tol=0.0) const;
814    
# Line 630  class Data { Line 817  class Data {
817       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.
818       *       *
819    */    */
820      ESCRIPT_DLL_API
821    Data    Data
822    whereNonZero(double tol=0.0) const;    whereNonZero(double tol=0.0) const;
823    
# Line 638  class Data { Line 826  class Data {
826       Return the maximum absolute value of this Data object.       Return the maximum absolute value of this Data object.
827       *       *
828    */    */
829      ESCRIPT_DLL_API
830    double    double
831    Lsup() const;    Lsup() const;
832    
833    /**    /**
834       \brief       \brief
      Return the minimum absolute value of this Data object.  
      *  
   */  
   double  
   Linf() const;  
   
   /**  
      \brief  
835       Return the maximum value of this Data object.       Return the maximum value of this Data object.
836       *       *
837    */    */
838      ESCRIPT_DLL_API
839    double    double
840    sup() const;    sup() const;
841    
# Line 662  class Data { Line 844  class Data {
844       Return the minimum value of this Data object.       Return the minimum value of this Data object.
845       *       *
846    */    */
847      ESCRIPT_DLL_API
848    double    double
849    inf() const;    inf() const;
850    
# Line 670  class Data { Line 853  class Data {
853       Return the absolute value of each data point of this Data object.       Return the absolute value of each data point of this Data object.
854       *       *
855    */    */
856      ESCRIPT_DLL_API
857    Data    Data
858    abs() const;    abs() const;
859    
# Line 678  class Data { Line 862  class Data {
862       Return the maximum value of each data point of this Data object.       Return the maximum value of each data point of this Data object.
863       *       *
864    */    */
865      ESCRIPT_DLL_API
866    Data    Data
867    maxval() const;    maxval() const;
868    
# Line 686  class Data { Line 871  class Data {
871       Return the minimum value of each data point of this Data object.       Return the minimum value of each data point of this Data object.
872       *       *
873    */    */
874      ESCRIPT_DLL_API
875    Data    Data
876    minval() const;    minval() const;
877    
# Line 694  class Data { Line 880  class Data {
880       Return the (sample number, data-point number) of the data point with       Return the (sample number, data-point number) of the data point with
881       the minimum value in this Data object.       the minimum value in this Data object.
882    */    */
883      ESCRIPT_DLL_API
884    const boost::python::tuple    const boost::python::tuple
885    mindp() const;    minGlobalDataPoint() const;
886    
887      ESCRIPT_DLL_API
888    void    void
889    calc_mindp(int& SampleNo,    calc_minGlobalDataPoint(int& ProcNo,  int& DataPointNo) const;
              int& DataPointNo) const;  
   
890    /**    /**
891       \brief       \brief
892       Return the sign of each data point of this Data object.       Return the sign of each data point of this Data object.
893       -1 for negative values, zero for zero values, 1 for positive values.       -1 for negative values, zero for zero values, 1 for positive values.
894       *       *
895    */    */
896      ESCRIPT_DLL_API
897    Data    Data
898    sign() const;    sign() const;
899    
900    /**    /**
901       \brief       \brief
902         Return the symmetric part of a matrix which is half the matrix plus its transpose.
903         *
904      */
905      ESCRIPT_DLL_API
906      Data
907      symmetric() const;
908    
909      /**
910         \brief
911         Return the nonsymmetric part of a matrix which is half the matrix minus its transpose.
912         *
913      */
914      ESCRIPT_DLL_API
915      Data
916      nonsymmetric() const;
917    
918      /**
919         \brief
920         Return the trace of a matrix
921         *
922      */
923      ESCRIPT_DLL_API
924      Data
925      trace(int axis_offset) const;
926    
927      /**
928         \brief
929         Transpose each data point of this Data object around the given axis.
930         *
931      */
932      ESCRIPT_DLL_API
933      Data
934      transpose(int axis_offset) const;
935    
936      /**
937         \brief
938       Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.       Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.
939       Currently this function is restricted to rank 2, square shape, and dimension 3.       Currently this function is restricted to rank 2, square shape, and dimension 3.
940       *       *
941    */    */
942      ESCRIPT_DLL_API
943    Data    Data
944    eigenvalues() const;    eigenvalues() const;
945    
946    /**    /**
947       \brief       \brief
948       Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.       Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.
949       the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than       the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than
950       tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the       tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the
951       first non-zero entry is positive.       first non-zero entry is positive.
952       Currently this function is restricted to rank 2, square shape, and dimension 3       Currently this function is restricted to rank 2, square shape, and dimension 3
953       *       *
954    */    */
955      ESCRIPT_DLL_API
956    const boost::python::tuple    const boost::python::tuple
957    eigenvalues_and_eigenvectors(const double tol=1.e-12) const;    eigenvalues_and_eigenvectors(const double tol=1.e-12) const;
958    
959    /**    /**
960       \brief       \brief
961       Transpose each data point of this Data object around the given axis.       swaps the components axis0 and axis1
      --* not implemented yet *--  
962       *       *
963    */    */
964      ESCRIPT_DLL_API
965    Data    Data
966    transpose(int axis) const;    swapaxes(const int axis0, const int axis1) const;
967    
968    /**    /**
969       \brief       \brief
970       Calculate the trace of each data point of this Data object.       Return the error function erf of each data point of this Data object.
971       *       *
972    */    */
973      ESCRIPT_DLL_API
974    Data    Data
975    trace() const;    erf() const;
976    
977    /**    /**
978       \brief       \brief
979       Return the sin of each data point of this Data object.       Return the sin of each data point of this Data object.
980       *       *
981    */    */
982      ESCRIPT_DLL_API
983    Data    Data
984    sin() const;    sin() const;
985    
# Line 761  class Data { Line 988  class Data {
988       Return the cos of each data point of this Data object.       Return the cos of each data point of this Data object.
989       *       *
990    */    */
991      ESCRIPT_DLL_API
992    Data    Data
993    cos() const;    cos() const;
994    
# Line 769  class Data { Line 997  class Data {
997       Return the tan of each data point of this Data object.       Return the tan of each data point of this Data object.
998       *       *
999    */    */
1000      ESCRIPT_DLL_API
1001    Data    Data
1002    tan() const;    tan() const;
1003    
# Line 777  class Data { Line 1006  class Data {
1006       Return the asin of each data point of this Data object.       Return the asin of each data point of this Data object.
1007       *       *
1008    */    */
1009      ESCRIPT_DLL_API
1010    Data    Data
1011    asin() const;    asin() const;
1012    
# Line 785  class Data { Line 1015  class Data {
1015       Return the acos of each data point of this Data object.       Return the acos of each data point of this Data object.
1016       *       *
1017    */    */
1018      ESCRIPT_DLL_API
1019    Data    Data
1020    acos() const;    acos() const;
1021    
# Line 793  class Data { Line 1024  class Data {
1024       Return the atan of each data point of this Data object.       Return the atan of each data point of this Data object.
1025       *       *
1026    */    */
1027      ESCRIPT_DLL_API
1028    Data    Data
1029    atan() const;    atan() const;
1030    
# Line 801  class Data { Line 1033  class Data {
1033       Return the sinh of each data point of this Data object.       Return the sinh of each data point of this Data object.
1034       *       *
1035    */    */
1036      ESCRIPT_DLL_API
1037    Data    Data
1038    sinh() const;    sinh() const;
1039    
# Line 809  class Data { Line 1042  class Data {
1042       Return the cosh of each data point of this Data object.       Return the cosh of each data point of this Data object.
1043       *       *
1044    */    */
1045      ESCRIPT_DLL_API
1046    Data    Data
1047    cosh() const;    cosh() const;
1048    
# Line 817  class Data { Line 1051  class Data {
1051       Return the tanh of each data point of this Data object.       Return the tanh of each data point of this Data object.
1052       *       *
1053    */    */
1054      ESCRIPT_DLL_API
1055    Data    Data
1056    tanh() const;    tanh() const;
1057    
# Line 825  class Data { Line 1060  class Data {
1060       Return the asinh of each data point of this Data object.       Return the asinh of each data point of this Data object.
1061       *       *
1062    */    */
1063      ESCRIPT_DLL_API
1064    Data    Data
1065    asinh() const;    asinh() const;
1066    
# Line 833  class Data { Line 1069  class Data {
1069       Return the acosh of each data point of this Data object.       Return the acosh of each data point of this Data object.
1070       *       *
1071    */    */
1072      ESCRIPT_DLL_API
1073    Data    Data
1074    acosh() const;    acosh() const;
1075    
# Line 841  class Data { Line 1078  class Data {
1078       Return the atanh of each data point of this Data object.       Return the atanh of each data point of this Data object.
1079       *       *
1080    */    */
1081      ESCRIPT_DLL_API
1082    Data    Data
1083    atanh() const;    atanh() const;
1084    
# Line 849  class Data { Line 1087  class Data {
1087       Return the log to base 10 of each data point of this Data object.       Return the log to base 10 of each data point of this Data object.
1088       *       *
1089    */    */
1090      ESCRIPT_DLL_API
1091    Data    Data
1092    log10() const;    log10() const;
1093    
# Line 857  class Data { Line 1096  class Data {
1096       Return the natural log of each data point of this Data object.       Return the natural log of each data point of this Data object.
1097       *       *
1098    */    */
1099      ESCRIPT_DLL_API
1100    Data    Data
1101    log() const;    log() const;
1102    
# Line 865  class Data { Line 1105  class Data {
1105       Return the exponential function of each data point of this Data object.       Return the exponential function of each data point of this Data object.
1106       *       *
1107    */    */
1108      ESCRIPT_DLL_API
1109    Data    Data
1110    exp() const;    exp() const;
1111    
# Line 873  class Data { Line 1114  class Data {
1114       Return the square root of each data point of this Data object.       Return the square root of each data point of this Data object.
1115       *       *
1116    */    */
1117      ESCRIPT_DLL_API
1118    Data    Data
1119    sqrt() const;    sqrt() const;
1120    
# Line 881  class Data { Line 1123  class Data {
1123       Return the negation of each data point of this Data object.       Return the negation of each data point of this Data object.
1124       *       *
1125    */    */
1126      ESCRIPT_DLL_API
1127    Data    Data
1128    neg() const;    neg() const;
1129    
# Line 890  class Data { Line 1133  class Data {
1133       Simply returns this object unmodified.       Simply returns this object unmodified.
1134       *       *
1135    */    */
1136      ESCRIPT_DLL_API
1137    Data    Data
1138    pos() const;    pos() const;
1139    
# Line 900  class Data { Line 1144  class Data {
1144       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1145       *       *
1146    */    */
1147      ESCRIPT_DLL_API
1148    Data    Data
1149    powD(const Data& right) const;    powD(const Data& right) const;
1150    
1151    /**    /**
1152       \brief       \brief
1153       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.
1154        
1155       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1156       *       *
1157     */     */
1158      ESCRIPT_DLL_API
1159    Data    Data
1160    powO(const boost::python::object& right) const;    powO(const boost::python::object& right) const;
1161    
1162    /**    /**
1163       \brief       \brief
1164         Return the given power of each data point of this boost python object.
1165    
1166         \param left Input - the bases
1167         *
1168       */
1169    
1170      ESCRIPT_DLL_API
1171      Data
1172      rpowO(const boost::python::object& left) const;
1173    
1174      /**
1175         \brief
1176       writes the object to a file in the DX file format       writes the object to a file in the DX file format
1177    */    */
1178      ESCRIPT_DLL_API
1179    void    void
1180    saveDX(std::string fileName) const;    saveDX(std::string fileName) const;
1181    
# Line 924  class Data { Line 1183  class Data {
1183       \brief       \brief
1184       writes the object to a file in the VTK file format       writes the object to a file in the VTK file format
1185    */    */
1186      ESCRIPT_DLL_API
1187    void    void
1188    saveVTK(std::string fileName) const;    saveVTK(std::string fileName) const;
1189    
# Line 933  class Data { Line 1193  class Data {
1193       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1194       *       *
1195    */    */
1196      ESCRIPT_DLL_API
1197    Data& operator+=(const Data& right);    Data& operator+=(const Data& right);
1198      ESCRIPT_DLL_API
1199    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1200    
1201      ESCRIPT_DLL_API
1202      Data& operator=(const Data& other);
1203    
1204    /**    /**
1205       \brief       \brief
1206       Overloaded operator -=       Overloaded operator -=
1207       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1208       *       *
1209    */    */
1210      ESCRIPT_DLL_API
1211    Data& operator-=(const Data& right);    Data& operator-=(const Data& right);
1212      ESCRIPT_DLL_API
1213    Data& operator-=(const boost::python::object& right);    Data& operator-=(const boost::python::object& right);
1214    
1215   /**   /**
# Line 951  class Data { Line 1218  class Data {
1218       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1219       *       *
1220    */    */
1221      ESCRIPT_DLL_API
1222    Data& operator*=(const Data& right);    Data& operator*=(const Data& right);
1223      ESCRIPT_DLL_API
1224    Data& operator*=(const boost::python::object& right);    Data& operator*=(const boost::python::object& right);
1225    
1226   /**   /**
# Line 960  class Data { Line 1229  class Data {
1229       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1230       *       *
1231    */    */
1232      ESCRIPT_DLL_API
1233    Data& operator/=(const Data& right);    Data& operator/=(const Data& right);
1234      ESCRIPT_DLL_API
1235    Data& operator/=(const boost::python::object& right);    Data& operator/=(const boost::python::object& right);
1236    
1237    /**    /**
1238       \brief       \brief
1239       Returns true if this can be interpolated to functionspace.       Returns true if this can be interpolated to functionspace.
1240    */    */
1241      ESCRIPT_DLL_API
1242    bool    bool
1243    probeInterpolation(const FunctionSpace& functionspace) const;    probeInterpolation(const FunctionSpace& functionspace) const;
1244    
# Line 985  class Data { Line 1257  class Data {
1257       \param key - Input - python slice tuple specifying       \param key - Input - python slice tuple specifying
1258       slice to return.       slice to return.
1259    */    */
1260      ESCRIPT_DLL_API
1261    Data    Data
1262    getItem(const boost::python::object& key) const;    getItem(const boost::python::object& key) const;
1263    
# Line 999  class Data { Line 1272  class Data {
1272       slice to copy from value.       slice to copy from value.
1273       \param value - Input - Data object to copy from.       \param value - Input - Data object to copy from.
1274    */    */
1275      ESCRIPT_DLL_API
1276    void    void
1277    setItemD(const boost::python::object& key,    setItemD(const boost::python::object& key,
1278             const Data& value);             const Data& value);
1279    
1280      ESCRIPT_DLL_API
1281    void    void
1282    setItemO(const boost::python::object& key,    setItemO(const boost::python::object& key,
1283             const boost::python::object& value);             const boost::python::object& value);
# Line 1015  class Data { Line 1290  class Data {
1290       this Data object.       this Data object.
1291    */    */
1292    template <class UnaryFunction>    template <class UnaryFunction>
1293      ESCRIPT_DLL_API
1294    inline    inline
1295    void    void
1296    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1297    
1298    /**    /**
1299       \brief       \brief
# Line 1026  class Data { Line 1302  class Data {
1302       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1303       *       *
1304    */    */
1305      ESCRIPT_DLL_API
1306    Data    Data
1307    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataTypes::RegionType& region) const;
1308    
1309    /**    /**
1310       \brief       \brief
# Line 1037  class Data { Line 1314  class Data {
1314       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1315       *       *
1316    */    */
1317      ESCRIPT_DLL_API
1318    void    void
1319    setSlice(const Data& value,    setSlice(const Data& value,
1320             const DataArrayView::RegionType& region);             const DataTypes::RegionType& region);
1321    
1322    /**    /**
1323       \brief       \brief
1324       Archive the current Data object to the given file.       print the data values to stdout. Used for debugging
      \param fileName - Input - file to archive to.  
1325    */    */
1326      ESCRIPT_DLL_API
1327    void    void
1328    archiveData(const std::string fileName);          print(void);
1329    
1330    /**    /**
1331       \brief       \brief
1332       Extract the Data object archived in the given file, overwriting       return the MPI rank number of the local data
1333       the current Data object.                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1334       Note - the current object must be of type DataEmpty.                   is returned
      \param fileName - Input - file to extract from.  
      \param fspace - Input - a suitable FunctionSpace descibing the data.  
1335    */    */
1336    void    ESCRIPT_DLL_API
1337    extractData(const std::string fileName,          int
1338                const FunctionSpace& fspace);          get_MPIRank(void) const;
1339    
1340      /**
1341         \brief
1342         return the MPI rank number of the local data
1343                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1344                     is returned
1345      */
1346      ESCRIPT_DLL_API
1347            int
1348            get_MPISize(void) const;
1349    
1350      /**
1351         \brief
1352         return the MPI rank number of the local data
1353                     MPI_COMM_WORLD is assumed and returned.
1354      */
1355      ESCRIPT_DLL_API
1356            MPI_Comm
1357            get_MPIComm(void) const;
1358    
1359      /**
1360         \brief
1361         return the object produced by the factory, which is a DataConstant or DataExpanded
1362        TODO Ownership of this object should be explained in doco.
1363      */
1364      ESCRIPT_DLL_API
1365            DataAbstract*
1366            borrowData(void) const;
1367    
1368    
1369      /**
1370         \brief
1371         Return a pointer to the beginning of the datapoint at the specified offset.
1372         TODO Eventually these should be inlined.
1373         \param i - position(offset) in the underlying datastructure
1374      */
1375      ESCRIPT_DLL_API
1376            DataTypes::ValueType::const_reference
1377            getDataAtOffset(DataTypes::ValueType::size_type i) const;
1378    
1379    
1380      ESCRIPT_DLL_API
1381            DataTypes::ValueType::reference
1382            getDataAtOffset(DataTypes::ValueType::size_type i);
1383    
1384   protected:   protected:
1385    
# Line 1118  class Data { Line 1438  class Data {
1438    
1439    /**    /**
1440       \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  
1441       Convert the data type of the RHS to match this.       Convert the data type of the RHS to match this.
1442       \param right - Input - data type to match.       \param right - Input - data type to match.
1443    */    */
# Line 1147  class Data { Line 1456  class Data {
1456       \brief       \brief
1457       Construct a Data object of the appropriate type.       Construct a Data object of the appropriate type.
1458    */    */
1459    template <class IValueType>  
1460    void    void
1461    initialise(const IValueType& value,    initialise(const DataTypes::ValueType& value,
1462             const DataTypes::ShapeType& shape,
1463               const FunctionSpace& what,               const FunctionSpace& what,
1464               bool expanded);               bool expanded);
1465    
   /**  
      \brief  
      Reshape the data point if the data point is currently rank 0.  
      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.  
   */  
1466    void    void
1467    reshapeDataPoint(const DataArrayView::ShapeType& shape);    initialise(const boost::python::numeric::array& value,
1468                     const FunctionSpace& what,
1469                     bool expanded);
1470    
1471    //    //
1472    // pointer to the actual data object    // flag to protect the data object against any update
1473    boost::shared_ptr<DataAbstract> m_data;    bool m_protected;
1474    
1475    //    //
1476    // pointer to the internal profiling data    // pointer to the actual data object
1477    struct profDataEntry *profData;    boost::shared_ptr<DataAbstract> m_data;
1478    
1479  };  };
1480    
1481  template <class IValueType>  
1482  void  
1483  Data::initialise(const IValueType& value,  /**
1484                   const FunctionSpace& what,     Modify a filename for MPI parallel output to multiple files
1485                   bool expanded)  */
1486  {  char *Escript_MPI_appendRankToFileName(const char *, int, int);
   //  
   // Construct a Data object of the appropriate type.  
   // Construct the object first as there seems to be a bug which causes  
   // undefined behaviour if an exception is thrown during construction  
   // within the shared_ptr constructor.  
   if (expanded) {  
     DataAbstract* temp=new DataExpanded(value,what);  
     boost::shared_ptr<DataAbstract> temp_data(temp);  
     m_data=temp_data;  
   } else {  
     DataAbstract* temp=new DataConstant(value,what);  
     boost::shared_ptr<DataAbstract> temp_data(temp);  
     m_data=temp_data;  
   }  
 }  
1487    
1488  /**  /**
1489     Binary Data object operators.     Binary Data object operators.
1490  */  */
1491    inline double rpow(double x,double y)
1492    {
1493        return pow(y,x);
1494    }
1495    
1496  /**  /**
1497    \brief    \brief
1498    Operator+    Operator+
1499    Takes two Data objects.    Takes two Data objects.
1500  */  */
1501  Data operator+(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1502    
1503  /**  /**
1504    \brief    \brief
1505    Operator-    Operator-
1506    Takes two Data objects.    Takes two Data objects.
1507  */  */
1508  Data operator-(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1509    
1510  /**  /**
1511    \brief    \brief
1512    Operator*    Operator*
1513    Takes two Data objects.    Takes two Data objects.
1514  */  */
1515  Data operator*(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1516    
1517  /**  /**
1518    \brief    \brief
1519    Operator/    Operator/
1520    Takes two Data objects.    Takes two Data objects.
1521  */  */
1522  Data operator/(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1523    
1524  /**  /**
1525    \brief    \brief
# Line 1233  Data operator/(const Data& left, const D Line 1527  Data operator/(const Data& left, const D
1527    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1528    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1529  */  */
1530  Data operator+(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const boost::python::object& right);
1531    
1532  /**  /**
1533    \brief    \brief
# Line 1241  Data operator+(const Data& left, const b Line 1535  Data operator+(const Data& left, const b
1535    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1536    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1537  */  */
1538  Data operator-(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const boost::python::object& right);
1539    
1540  /**  /**
1541    \brief    \brief
# Line 1249  Data operator-(const Data& left, const b Line 1543  Data operator-(const Data& left, const b
1543    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1544    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1545  */  */
1546  Data operator*(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const boost::python::object& right);
1547    
1548  /**  /**
1549    \brief    \brief
# Line 1257  Data operator*(const Data& left, const b Line 1551  Data operator*(const Data& left, const b
1551    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1552    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1553  */  */
1554  Data operator/(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const boost::python::object& right);
1555    
1556  /**  /**
1557    \brief    \brief
# Line 1265  Data operator/(const Data& left, const b Line 1559  Data operator/(const Data& left, const b
1559    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1560    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1561  */  */
1562  Data operator+(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const boost::python::object& left, const Data& right);
1563    
1564  /**  /**
1565    \brief    \brief
# Line 1273  Data operator+(const boost::python::obje Line 1567  Data operator+(const boost::python::obje
1567    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1568    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1569  */  */
1570  Data operator-(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const boost::python::object& left, const Data& right);
1571    
1572  /**  /**
1573    \brief    \brief
# Line 1281  Data operator-(const boost::python::obje Line 1575  Data operator-(const boost::python::obje
1575    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1576    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1577  */  */
1578  Data operator*(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const boost::python::object& left, const Data& right);
1579    
1580  /**  /**
1581    \brief    \brief
# Line 1289  Data operator*(const boost::python::obje Line 1583  Data operator*(const boost::python::obje
1583    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1584    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1585  */  */
1586  Data operator/(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1587    
1588    
1589    
1590  /**  /**
1591    \brief    \brief
1592    Output operator    Output operator
1593  */  */
1594  std::ostream& operator<<(std::ostream& o, const Data& data);  ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1595    
1596  /**  /**
1597    \brief    \brief
1598    Return true if operands are equivalent, else return false.    Compute a tensor product of two Data objects
1599    NB: this operator does very little at this point, and isn't to    \param arg0 - Input - Data object
1600    be relied on. Requires further implementation.    \param arg1 - Input - Data object
1601      \param axis_offset - Input - axis offset
1602      \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1603  */  */
1604  //bool operator==(const Data& left, const Data& right);  ESCRIPT_DLL_API
1605    Data
1606    C_GeneralTensorProduct(Data& arg0,
1607                         Data& arg1,
1608                         int axis_offset=0,
1609                         int transpose=0);
1610    
1611    
1612    
1613    // /**
1614    /*  \brief
1615      Return true if operands are equivalent, else return false.
1616      NB: this operator does very little at this point, and isn't to
1617      be relied on. Requires further implementation.*/
1618    //*/
1619    // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1620    
1621  /**  /**
1622    \brief    \brief
# Line 1318  Data::binaryOp(const Data& right, Line 1631  Data::binaryOp(const Data& right,
1631  {  {
1632     //     //
1633     // 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
1634     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1635       reshapeDataPoint(right.getPointDataView().getShape());       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1636     }     }
1637     //     //
1638     // initially make the temporary a shallow copy     // initially make the temporary a shallow copy
# Line 1327  Data::binaryOp(const Data& right, Line 1640  Data::binaryOp(const Data& right,
1640     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1641       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1642         //         //
1643         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1644         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1645       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1646         //         //
# Line 1375  Data::binaryOp(const Data& right, Line 1688  Data::binaryOp(const Data& right,
1688    
1689  /**  /**
1690    \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  
1691    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.
1692    Given operation combines each element of each data point, thus argument    Given operation combines each element of each data point, thus argument
1693    object (*this) is a rank n Data object, and returned object is a scalar.    object (*this) is a rank n Data object, and returned object is a scalar.
# Line 1483  Data::algorithm(BinaryFunction operation Line 1710  Data::algorithm(BinaryFunction operation
1710      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1711      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1712      return escript::algorithm(*leftC,operation,initial_value);      return escript::algorithm(*leftC,operation,initial_value);
1713      } else if (isEmpty()) {
1714        throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1715    }    }
1716    return 0;    return 0;
1717  }  }
# Line 1491  Data::algorithm(BinaryFunction operation Line 1720  Data::algorithm(BinaryFunction operation
1720    \brief    \brief
1721    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.
1722    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1723    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
1724    rank 0 Data object.    rank 0 Data object.
1725    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1726  */  */
# Line 1500  inline Line 1729  inline
1729  Data  Data
1730  Data::dp_algorithm(BinaryFunction operation, double initial_value) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1731  {  {
1732    if (isExpanded()) {    if (isEmpty()) {
1733      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1734      }
1735      else if (isExpanded()) {
1736        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1737      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1738      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1739      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1740      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1741      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1742      return result;      return result;
1743    } else if (isTagged()) {    }
1744      else if (isTagged()) {
1745      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
     DataArrayView::ShapeType viewShape;  
     DataArrayView::ValueType viewData(1);  
     viewData[0]=0;  
     DataArrayView defaultValue(viewData,viewShape);  
     DataTagged::TagListType keys;  
     DataTagged::ValueListType values;  
     DataTagged::DataMapType::const_iterator i;  
     for (i=dataT->getTagLookup().begin();i!=dataT->getTagLookup().end();i++) {  
       keys.push_back(i->first);  
       values.push_back(defaultValue);  
     }  
     Data result(keys,values,defaultValue,getFunctionSpace());  
     DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());  
1746      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1747      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      DataTypes::ValueType defval(1);
1748        defval[0]=0;
1749        DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1750      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1751      return result;      return Data(resultT);   // note: the Data object now owns the resultT pointer
1752    } else if (isConstant()) {    }
1753      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());    else if (isConstant()) {
1754        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1755      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1756      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1757      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
# Line 1540  Data::dp_algorithm(BinaryFunction operat Line 1763  Data::dp_algorithm(BinaryFunction operat
1763    return falseRetVal;    return falseRetVal;
1764  }  }
1765    
1766    /**
1767      \brief
1768      Compute a tensor operation with two Data objects
1769      \param arg0 - Input - Data object
1770      \param arg1 - Input - Data object
1771      \param operation - Input - Binary op functor
1772    */
1773    template <typename BinaryFunction>
1774    inline
1775    Data
1776    C_TensorBinaryOperation(Data const &arg_0,
1777                            Data const &arg_1,
1778                            BinaryFunction operation)
1779    {
1780      if (arg_0.isEmpty() || arg_1.isEmpty())
1781      {
1782         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1783      }
1784      // Interpolate if necessary and find an appropriate function space
1785      Data arg_0_Z, arg_1_Z;
1786      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1787        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1788          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1789          arg_1_Z = Data(arg_1);
1790        }
1791        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1792          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1793          arg_0_Z =Data(arg_0);
1794        }
1795        else {
1796          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1797        }
1798      } else {
1799          arg_0_Z = Data(arg_0);
1800          arg_1_Z = Data(arg_1);
1801      }
1802      // Get rank and shape of inputs
1803      int rank0 = arg_0_Z.getDataPointRank();
1804      int rank1 = arg_1_Z.getDataPointRank();
1805      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1806      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1807      int size0 = arg_0_Z.getDataPointSize();
1808      int size1 = arg_1_Z.getDataPointSize();
1809    
1810      // Declare output Data object
1811      Data res;
1812    
1813      if (shape0 == shape1) {
1814    
1815        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1816          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1817    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1818          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1819          double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1820          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1821          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1822          double *ptr_2 = &(res.getDataAtOffset(0));
1823    
1824          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1825        }
1826        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1827    
1828          // Prepare the DataConstant input
1829          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1830    
1831          // Borrow DataTagged input from Data object
1832          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1833    
1834          // Prepare a DataTagged output 2
1835          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1836          res.tag();
1837          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1838    
1839          // Prepare offset into DataConstant
1840          int offset_0 = tmp_0->getPointOffset(0,0);
1841          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1842          // Get the views
1843    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1844    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1845    //       // Get the pointers to the actual data
1846    //       double *ptr_1 = &((view_1.getData())[0]);
1847    //       double *ptr_2 = &((view_2.getData())[0]);
1848    
1849          // Get the pointers to the actual data
1850          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1851          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1852    
1853          // Compute a result for the default
1854          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1855          // Compute a result for each tag
1856          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1857          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1858          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1859            tmp_2->addTag(i->first);
1860    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1861            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1862            double *ptr_1 = &view_1.getData(0);
1863            double *ptr_2 = &view_2.getData(0);*/
1864            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1865            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1866    
1867            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1868          }
1869    
1870        }
1871        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1872    
1873          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1874          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1875          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1876          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1877    
1878          int sampleNo_1,dataPointNo_1;
1879          int numSamples_1 = arg_1_Z.getNumSamples();
1880          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1881          int offset_0 = tmp_0->getPointOffset(0,0);
1882          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1883          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1884            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1885              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1886              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1887    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1888    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1889    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1890    
1891              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1892              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1893              double *ptr_2 = &(res.getDataAtOffset(offset_2));
1894              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1895            }
1896          }
1897    
1898        }
1899        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1900    
1901          // Borrow DataTagged input from Data object
1902          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1903    
1904          // Prepare the DataConstant input
1905          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1906    
1907          // Prepare a DataTagged output 2
1908          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1909          res.tag();
1910          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1911    
1912          // Prepare offset into DataConstant
1913          int offset_1 = tmp_1->getPointOffset(0,0);
1914    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1915          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1916          // Get the views
1917    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1918    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1919    //       // Get the pointers to the actual data
1920    //       double *ptr_0 = &((view_0.getData())[0]);
1921    //       double *ptr_2 = &((view_2.getData())[0]);
1922          // Get the pointers to the actual data
1923          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1924          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1925          // Compute a result for the default
1926          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1927          // Compute a result for each tag
1928          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1929          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1930          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1931            tmp_2->addTag(i->first);
1932    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1933    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1934    //         double *ptr_0 = &view_0.getData(0);
1935    //         double *ptr_2 = &view_2.getData(0);
1936            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1937            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1938            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1939          }
1940    
1941        }
1942        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1943    
1944          // Borrow DataTagged input from Data object
1945          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1946    
1947          // Borrow DataTagged input from Data object
1948          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1949    
1950          // Prepare a DataTagged output 2
1951          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1952          res.tag();        // DataTagged output
1953          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1954    
1955    //       // Get the views
1956    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1957    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1958    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1959    //       // Get the pointers to the actual data
1960    //       double *ptr_0 = &((view_0.getData())[0]);
1961    //       double *ptr_1 = &((view_1.getData())[0]);
1962    //       double *ptr_2 = &((view_2.getData())[0]);
1963    
1964          // Get the pointers to the actual data
1965          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1966          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1967          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1968    
1969          // Compute a result for the default
1970          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1971          // Merge the tags
1972          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1973          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1974          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1975          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1976            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
1977          }
1978          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1979            tmp_2->addTag(i->first);
1980          }
1981          // Compute a result for each tag
1982          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1983          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1984    
1985    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1986    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1987    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1988    //         double *ptr_0 = &view_0.getData(0);
1989    //         double *ptr_1 = &view_1.getData(0);
1990    //         double *ptr_2 = &view_2.getData(0);
1991    
1992            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1993            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1994            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1995    
1996            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1997          }
1998    
1999        }
2000        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2001    
2002          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2003          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2004          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2005          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2006          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2007    
2008          int sampleNo_0,dataPointNo_0;
2009          int numSamples_0 = arg_0_Z.getNumSamples();
2010          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2011          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2012          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2013            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2014            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2015            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2016              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2017              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2018    
2019    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2020    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2021              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2022              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2023    
2024    
2025              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2026            }
2027          }
2028    
2029        }
2030        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2031    
2032          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2033          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2034          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2035          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2036    
2037          int sampleNo_0,dataPointNo_0;
2038          int numSamples_0 = arg_0_Z.getNumSamples();
2039          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2040          int offset_1 = tmp_1->getPointOffset(0,0);
2041          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2042          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2043            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2044              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2045              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2046    
2047    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2048    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2049    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2050    
2051              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2052              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2053              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2054    
2055    
2056              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2057            }
2058          }
2059    
2060        }
2061        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2062    
2063          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2064          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2065          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2066          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2067          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2068    
2069          int sampleNo_0,dataPointNo_0;
2070          int numSamples_0 = arg_0_Z.getNumSamples();
2071          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2072          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2073          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2074            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2075            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2076            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2077              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2078              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2079              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2080              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2081              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2082            }
2083          }
2084    
2085        }
2086        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2087    
2088          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2089          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2090          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2091          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2092          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2093    
2094          int sampleNo_0,dataPointNo_0;
2095          int numSamples_0 = arg_0_Z.getNumSamples();
2096          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2097          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2098          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2099            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2100              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2101              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2102              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2103              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2104              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2105              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2106              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2107            }
2108          }
2109    
2110        }
2111        else {
2112          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2113        }
2114    
2115      } else if (0 == rank0) {
2116    
2117        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2118          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2119          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2120          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2121          double *ptr_2 = &(res.getDataAtOffset(0));
2122          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2123        }
2124        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2125    
2126          // Prepare the DataConstant input
2127          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2128    
2129          // Borrow DataTagged input from Data object
2130          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2131    
2132          // Prepare a DataTagged output 2
2133          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2134          res.tag();
2135          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2136    
2137          // Prepare offset into DataConstant
2138          int offset_0 = tmp_0->getPointOffset(0,0);
2139          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2140          // Get the views
2141    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2142    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2143    //       // Get the pointers to the actual data
2144    //       double *ptr_1 = &((view_1.getData())[0]);
2145    //       double *ptr_2 = &((view_2.getData())[0]);
2146           double *ptr_1 = &(tmp_1->getDefaultValue(0));
2147           double *ptr_2 = &(tmp_2->getDefaultValue(0));
2148    
2149          // Compute a result for the default
2150          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2151          // Compute a result for each tag
2152          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2153          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2154          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2155            tmp_2->addTag(i->first);
2156    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2157    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2158    //         double *ptr_1 = &view_1.getData(0);
2159    //         double *ptr_2 = &view_2.getData(0);
2160            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2161            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2162            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2163          }
2164    
2165        }
2166        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2167    
2168          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2169          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2170          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2171          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2172    
2173          int sampleNo_1,dataPointNo_1;
2174          int numSamples_1 = arg_1_Z.getNumSamples();
2175          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2176          int offset_0 = tmp_0->getPointOffset(0,0);
2177          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2178          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2179            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2180              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2181              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2182              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2183              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2184              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2185              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2186    
2187            }
2188          }
2189    
2190        }
2191        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2192    
2193          // Borrow DataTagged input from Data object
2194          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2195    
2196          // Prepare the DataConstant input
2197          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2198    
2199          // Prepare a DataTagged output 2
2200          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2201          res.tag();
2202          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2203    
2204          // Prepare offset into DataConstant
2205          int offset_1 = tmp_1->getPointOffset(0,0);
2206    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2207          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2208          // Get the views
2209    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2210          DataArrayView view_2 = tmp_2->getDefaultValue();
2211          // Get the pointers to the actual data
2212          double *ptr_0 = &((view_0.getData())[0]);
2213          double *ptr_2 = &((view_2.getData())[0]);*/
2214    
2215          // Get the pointers to the actual data
2216          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2217          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2218    
2219    
2220          // Compute a result for the default
2221          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2222          // Compute a result for each tag
2223          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2224          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2225          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2226            tmp_2->addTag(i->first);
2227    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2228            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2229            double *ptr_0 = &view_0.getData(0);
2230            double *ptr_2 = &view_2.getData(0);*/
2231            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2232            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2233    
2234            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2235          }
2236    
2237        }
2238        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2239    
2240          // Borrow DataTagged input from Data object
2241          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2242    
2243          // Borrow DataTagged input from Data object
2244          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2245    
2246          // Prepare a DataTagged output 2
2247          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2248          res.tag();        // DataTagged output
2249          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2250    
2251          // Get the views
2252    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2253          DataArrayView view_1 = tmp_1->getDefaultValue();
2254          DataArrayView view_2 = tmp_2->getDefaultValue();
2255          // Get the pointers to the actual data
2256          double *ptr_0 = &((view_0.getData())[0]);
2257          double *ptr_1 = &((view_1.getData())[0]);
2258          double *ptr_2 = &((view_2.getData())[0]);*/
2259    
2260          // Get the pointers to the actual data
2261          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2262          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2263          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2264    
2265    
2266          // Compute a result for the default
2267          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2268          // Merge the tags
2269          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2270          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2271          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2272          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2273            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2274          }
2275          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2276            tmp_2->addTag(i->first);
2277          }
2278          // Compute a result for each tag
2279          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2280          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2281    
2282    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2283            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2284            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2285            double *ptr_0 = &view_0.getData(0);
2286            double *ptr_1 = &view_1.getData(0);
2287            double *ptr_2 = &view_2.getData(0);*/
2288    
2289            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2290            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2291            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2292    
2293            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2294          }
2295    
2296        }
2297        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2298    
2299          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2300          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2301          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2302          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2303          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2304    
2305          int sampleNo_0,dataPointNo_0;
2306          int numSamples_0 = arg_0_Z.getNumSamples();
2307          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2308          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2309          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2310            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2311            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2312            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2313              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2314              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2315              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2316              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2317              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2318            }
2319          }
2320    
2321        }
2322        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2323    
2324          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2325          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2326          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2327          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2328    
2329          int sampleNo_0,dataPointNo_0;
2330          int numSamples_0 = arg_0_Z.getNumSamples();
2331          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2332          int offset_1 = tmp_1->getPointOffset(0,0);
2333          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2334          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2335            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2336              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2337              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2338              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2339              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2340              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2341              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2342            }
2343          }
2344    
2345    
2346        }
2347        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2348    
2349          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2350          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2351          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2352          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2353          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2354    
2355          int sampleNo_0,dataPointNo_0;
2356          int numSamples_0 = arg_0_Z.getNumSamples();
2357          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2358          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2359          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2360            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2361            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2362            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2363              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2364              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2365              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2366              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2367              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2368            }
2369          }
2370    
2371        }
2372        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2373    
2374          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2375          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2376          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2377          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2378          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2379    
2380          int sampleNo_0,dataPointNo_0;
2381          int numSamples_0 = arg_0_Z.getNumSamples();
2382          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2383          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2384          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2385            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2386              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2387              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2388              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2389              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2390              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2391              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2392              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2393            }
2394          }
2395    
2396        }
2397        else {
2398          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2399        }
2400    
2401      } else if (0 == rank1) {
2402    
2403        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2404          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2405          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2406          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2407          double *ptr_2 = &(res.getDataAtOffset(0));
2408          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2409        }
2410        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2411    
2412          // Prepare the DataConstant input
2413          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2414    
2415          // Borrow DataTagged input from Data object
2416          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2417    
2418          // Prepare a DataTagged output 2
2419          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2420          res.tag();
2421          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2422    
2423          // Prepare offset into DataConstant
2424          int offset_0 = tmp_0->getPointOffset(0,0);
2425          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2426          // Get the views
2427    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2428          DataArrayView view_2 = tmp_2->getDefaultValue();
2429          // Get the pointers to the actual data
2430          double *ptr_1 = &((view_1.getData())[0]);
2431          double *ptr_2 = &((view_2.getData())[0]);*/
2432          //Get the pointers to the actual data
2433          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2434          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2435    
2436          // Compute a result for the default
2437          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2438          // Compute a result for each tag
2439          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2440          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2441          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2442            tmp_2->addTag(i->first);
2443    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2444    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2445    //         double *ptr_1 = &view_1.getData(0);
2446    //         double *ptr_2 = &view_2.getData(0);
2447            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2448            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2449    
2450    
2451            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2452          }
2453    
2454        }
2455        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2456    
2457          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2458          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2459          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2460          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2461    
2462          int sampleNo_1,dataPointNo_1;
2463          int numSamples_1 = arg_1_Z.getNumSamples();
2464          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2465          int offset_0 = tmp_0->getPointOffset(0,0);
2466          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2467          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2468            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2469              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2470              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2471              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2472              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2473              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2474              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2475            }
2476          }
2477    
2478        }
2479        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2480    
2481          // Borrow DataTagged input from Data object
2482          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2483    
2484          // Prepare the DataConstant input
2485          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2486    
2487          // Prepare a DataTagged output 2
2488          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2489          res.tag();
2490          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2491    
2492          // Prepare offset into DataConstant
2493          int offset_1 = tmp_1->getPointOffset(0,0);
2494          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2495          // Get the views
2496    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2497    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2498    //       // Get the pointers to the actual data
2499    //       double *ptr_0 = &((view_0.getData())[0]);
2500    //       double *ptr_2 = &((view_2.getData())[0]);
2501          // Get the pointers to the actual data
2502          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2503          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2504          // Compute a result for the default
2505          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2506          // Compute a result for each tag
2507          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2508          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2509          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2510            tmp_2->addTag(i->first);
2511    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2512            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2513            double *ptr_0 = &view_0.getData(0);
2514            double *ptr_2 = &view_2.getData(0);*/
2515            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2516            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2517            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2518          }
2519    
2520        }
2521        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2522    
2523          // Borrow DataTagged input from Data object
2524          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2525    
2526          // Borrow DataTagged input from Data object
2527          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2528    
2529          // Prepare a DataTagged output 2
2530          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2531          res.tag();        // DataTagged output
2532          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2533    
2534          // Get the views
2535    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2536    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2537    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2538    //       // Get the pointers to the actual data
2539    //       double *ptr_0 = &((view_0.getData())[0]);
2540    //       double *ptr_1 = &((view_1.getData())[0]);
2541    //       double *ptr_2 = &((view_2.getData())[0]);
2542    
2543          // Get the pointers to the actual data
2544          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2545          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2546          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2547    
2548          // Compute a result for the default
2549          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2550          // Merge the tags
2551          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2552          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2553          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2554          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2555            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2556          }
2557          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2558            tmp_2->addTag(i->first);
2559          }
2560          // Compute a result for each tag
2561          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2562          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2563    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2564    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2565    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2566    //         double *ptr_0 = &view_0.getData(0);
2567    //         double *ptr_1 = &view_1.getData(0);
2568    //         double *ptr_2 = &view_2.getData(0);
2569    
2570            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2571            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2572            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2573            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2574          }
2575    
2576        }
2577        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2578    
2579          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2580          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2581          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2582          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2583          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2584    
2585          int sampleNo_0,dataPointNo_0;
2586          int numSamples_0 = arg_0_Z.getNumSamples();
2587          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2588          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2589          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2590            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2591            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2592            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2593              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2594              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2595              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2596              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2597              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2598            }
2599          }
2600    
2601        }
2602        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2603    
2604          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2605          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2606          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2607          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2608    
2609          int sampleNo_0,dataPointNo_0;
2610          int numSamples_0 = arg_0_Z.getNumSamples();
2611          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2612          int offset_1 = tmp_1->getPointOffset(0,0);
2613          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2614          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2615            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2616              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2617              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2618              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2619              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2620              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2621              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2622            }
2623          }
2624    
2625    
2626        }
2627        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2628    
2629          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2630          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2631          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2632          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2633          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2634    
2635          int sampleNo_0,dataPointNo_0;
2636          int numSamples_0 = arg_0_Z.getNumSamples();
2637          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2638          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2639          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2640            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2641            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2642            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2643              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2644              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2645              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2646              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2647              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2648            }
2649          }
2650    
2651        }
2652        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2653    
2654          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2655          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2656          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2657          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2658          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2659    
2660          int sampleNo_0,dataPointNo_0;
2661          int numSamples_0 = arg_0_Z.getNumSamples();
2662          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2663          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2664          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2665            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2666              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2667              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2668              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2669              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2670              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2671              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2672              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2673            }
2674          }
2675    
2676        }
2677        else {
2678          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2679        }
2680    
2681      } else {
2682        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2683      }
2684    
2685      return res;
2686    }
2687    
2688    template <typename UnaryFunction>
2689    Data
2690    C_TensorUnaryOperation(Data const &arg_0,
2691                           UnaryFunction operation)
2692    {
2693      if (arg_0.isEmpty())  // do this before we attempt to interpolate
2694      {
2695         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2696      }
2697    
2698      // Interpolate if necessary and find an appropriate function space
2699      Data arg_0_Z = Data(arg_0);
2700    
2701      // Get rank and shape of inputs
2702      int rank0 = arg_0_Z.getDataPointRank();
2703      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2704      int size0 = arg_0_Z.getDataPointSize();
2705    
2706      // Declare output Data object
2707      Data res;
2708    
2709      if (arg_0_Z.isConstant()) {
2710        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2711    //     double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2712    //     double *ptr_2 = &((res.getPointDataView().getData())[0]);
2713        double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2714        double *ptr_2 = &(res.getDataAtOffset(0));
2715        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2716      }
2717      else if (arg_0_Z.isTagged()) {
2718    
2719        // Borrow DataTagged input from Data object
2720        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2721    
2722        // Prepare a DataTagged output 2
2723        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2724        res.tag();
2725        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2726    
2727    //     // Get the views
2728    //     DataArrayView view_0 = tmp_0->getDefaultValue();
2729    //     DataArrayView view_2 = tmp_2->getDefaultValue();
2730    //     // Get the pointers to the actual data
2731    //     double *ptr_0 = &((view_0.getData())[0]);
2732    //     double *ptr_2 = &((view_2.getData())[0]);
2733        // Get the pointers to the actual data
2734        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2735        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2736        // Compute a result for the default
2737        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2738        // Compute a result for each tag
2739        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2740        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2741        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2742          tmp_2->addTag(i->first);
2743    //       DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2744    //       DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2745    //       double *ptr_0 = &view_0.getData(0);
2746    //       double *ptr_2 = &view_2.getData(0);
2747          double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2748          double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2749          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2750        }
2751    
2752      }
2753      else if (arg_0_Z.isExpanded()) {
2754    
2755        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2756        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2757        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2758    
2759        int sampleNo_0,dataPointNo_0;
2760        int numSamples_0 = arg_0_Z.getNumSamples();
2761        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2762        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2763        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2764          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2765    //         int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2766    //         int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2767    //         double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2768    //         double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2769            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2770            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2771            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2772            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2773            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2774          }
2775        }
2776      }
2777      else {
2778        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2779      }
2780    
2781      return res;
2782    }
2783    
2784  }  }
2785  #endif  #endif

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

  ViewVC Help
Powered by ViewVC 1.1.26