/[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 1828 by jfenwick, Thu Oct 2 04:52:11 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      DataAbstract_ptr m_data;
1479    
1480  };  };
1481    
1482  template <class IValueType>  
1483  void  
1484  Data::initialise(const IValueType& value,  /**
1485                   const FunctionSpace& what,     Modify a filename for MPI parallel output to multiple files
1486                   bool expanded)  */
1487  {  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;  
   }  
 }  
1488    
1489  /**  /**
1490     Binary Data object operators.     Binary Data object operators.
1491  */  */
1492    inline double rpow(double x,double y)
1493    {
1494        return pow(y,x);
1495    }
1496    
1497  /**  /**
1498    \brief    \brief
1499    Operator+    Operator+
1500    Takes two Data objects.    Takes two Data objects.
1501  */  */
1502  Data operator+(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1503    
1504  /**  /**
1505    \brief    \brief
1506    Operator-    Operator-
1507    Takes two Data objects.    Takes two Data objects.
1508  */  */
1509  Data operator-(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1510    
1511  /**  /**
1512    \brief    \brief
1513    Operator*    Operator*
1514    Takes two Data objects.    Takes two Data objects.
1515  */  */
1516  Data operator*(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1517    
1518  /**  /**
1519    \brief    \brief
1520    Operator/    Operator/
1521    Takes two Data objects.    Takes two Data objects.
1522  */  */
1523  Data operator/(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1524    
1525  /**  /**
1526    \brief    \brief
# Line 1233  Data operator/(const Data& left, const D Line 1528  Data operator/(const Data& left, const D
1528    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1529    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1530  */  */
1531  Data operator+(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const boost::python::object& right);
1532    
1533  /**  /**
1534    \brief    \brief
# Line 1241  Data operator+(const Data& left, const b Line 1536  Data operator+(const Data& left, const b
1536    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1537    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1538  */  */
1539  Data operator-(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const boost::python::object& right);
1540    
1541  /**  /**
1542    \brief    \brief
# Line 1249  Data operator-(const Data& left, const b Line 1544  Data operator-(const Data& left, const b
1544    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1545    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1546  */  */
1547  Data operator*(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const boost::python::object& right);
1548    
1549  /**  /**
1550    \brief    \brief
# Line 1257  Data operator*(const Data& left, const b Line 1552  Data operator*(const Data& left, const b
1552    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1553    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1554  */  */
1555  Data operator/(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const boost::python::object& right);
1556    
1557  /**  /**
1558    \brief    \brief
# Line 1265  Data operator/(const Data& left, const b Line 1560  Data operator/(const Data& left, const b
1560    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1561    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1562  */  */
1563  Data operator+(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const boost::python::object& left, const Data& right);
1564    
1565  /**  /**
1566    \brief    \brief
# Line 1273  Data operator+(const boost::python::obje Line 1568  Data operator+(const boost::python::obje
1568    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1569    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1570  */  */
1571  Data operator-(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const boost::python::object& left, const Data& right);
1572    
1573  /**  /**
1574    \brief    \brief
# Line 1281  Data operator-(const boost::python::obje Line 1576  Data operator-(const boost::python::obje
1576    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1577    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1578  */  */
1579  Data operator*(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const boost::python::object& left, const Data& right);
1580    
1581  /**  /**
1582    \brief    \brief
# Line 1289  Data operator*(const boost::python::obje Line 1584  Data operator*(const boost::python::obje
1584    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1585    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1586  */  */
1587  Data operator/(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1588    
1589    
1590    
1591  /**  /**
1592    \brief    \brief
1593    Output operator    Output operator
1594  */  */
1595  std::ostream& operator<<(std::ostream& o, const Data& data);  ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1596    
1597  /**  /**
1598    \brief    \brief
1599    Return true if operands are equivalent, else return false.    Compute a tensor product of two Data objects
1600    NB: this operator does very little at this point, and isn't to    \param arg0 - Input - Data object
1601    be relied on. Requires further implementation.    \param arg1 - Input - Data object
1602      \param axis_offset - Input - axis offset
1603      \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1604  */  */
1605  //bool operator==(const Data& left, const Data& right);  ESCRIPT_DLL_API
1606    Data
1607    C_GeneralTensorProduct(Data& arg0,
1608                         Data& arg1,
1609                         int axis_offset=0,
1610                         int transpose=0);
1611    
1612    
1613    
1614    // /**
1615    /*  \brief
1616      Return true if operands are equivalent, else return false.
1617      NB: this operator does very little at this point, and isn't to
1618      be relied on. Requires further implementation.*/
1619    //*/
1620    // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1621    
1622  /**  /**
1623    \brief    \brief
# Line 1318  Data::binaryOp(const Data& right, Line 1632  Data::binaryOp(const Data& right,
1632  {  {
1633     //     //
1634     // 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
1635     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1636       reshapeDataPoint(right.getPointDataView().getShape());       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1637     }     }
1638     //     //
1639     // initially make the temporary a shallow copy     // initially make the temporary a shallow copy
# Line 1327  Data::binaryOp(const Data& right, Line 1641  Data::binaryOp(const Data& right,
1641     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1642       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1643         //         //
1644         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1645         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1646       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1647         //         //
# Line 1375  Data::binaryOp(const Data& right, Line 1689  Data::binaryOp(const Data& right,
1689    
1690  /**  /**
1691    \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  
1692    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.
1693    Given operation combines each element of each data point, thus argument    Given operation combines each element of each data point, thus argument
1694    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 1711  Data::algorithm(BinaryFunction operation
1711      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1712      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1713      return escript::algorithm(*leftC,operation,initial_value);      return escript::algorithm(*leftC,operation,initial_value);
1714      } else if (isEmpty()) {
1715        throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1716    }    }
1717    return 0;    return 0;
1718  }  }
# Line 1491  Data::algorithm(BinaryFunction operation Line 1721  Data::algorithm(BinaryFunction operation
1721    \brief    \brief
1722    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.
1723    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1724    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
1725    rank 0 Data object.    rank 0 Data object.
1726    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1727  */  */
# Line 1500  inline Line 1730  inline
1730  Data  Data
1731  Data::dp_algorithm(BinaryFunction operation, double initial_value) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1732  {  {
1733    if (isExpanded()) {    if (isEmpty()) {
1734      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1735      }
1736      else if (isExpanded()) {
1737        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1738      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1739      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1740      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1741      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1742      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1743      return result;      return result;
1744    } else if (isTagged()) {    }
1745      else if (isTagged()) {
1746      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());  
1747      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1748      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      DataTypes::ValueType defval(1);
1749        defval[0]=0;
1750        DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1751      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1752      return result;      return Data(resultT);   // note: the Data object now owns the resultT pointer
1753    } else if (isConstant()) {    }
1754      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());    else if (isConstant()) {
1755        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1756      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1757      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1758      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 1764  Data::dp_algorithm(BinaryFunction operat
1764    return falseRetVal;    return falseRetVal;
1765  }  }
1766    
1767    /**
1768      \brief
1769      Compute a tensor operation with two Data objects
1770      \param arg0 - Input - Data object
1771      \param arg1 - Input - Data object
1772      \param operation - Input - Binary op functor
1773    */
1774    template <typename BinaryFunction>
1775    inline
1776    Data
1777    C_TensorBinaryOperation(Data const &arg_0,
1778                            Data const &arg_1,
1779                            BinaryFunction operation)
1780    {
1781      if (arg_0.isEmpty() || arg_1.isEmpty())
1782      {
1783         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1784      }
1785      // Interpolate if necessary and find an appropriate function space
1786      Data arg_0_Z, arg_1_Z;
1787      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1788        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1789          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1790          arg_1_Z = Data(arg_1);
1791        }
1792        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1793          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1794          arg_0_Z =Data(arg_0);
1795        }
1796        else {
1797          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1798        }
1799      } else {
1800          arg_0_Z = Data(arg_0);
1801          arg_1_Z = Data(arg_1);
1802      }
1803      // Get rank and shape of inputs
1804      int rank0 = arg_0_Z.getDataPointRank();
1805      int rank1 = arg_1_Z.getDataPointRank();
1806      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1807      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1808      int size0 = arg_0_Z.getDataPointSize();
1809      int size1 = arg_1_Z.getDataPointSize();
1810    
1811      // Declare output Data object
1812      Data res;
1813    
1814      if (shape0 == shape1) {
1815    
1816        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1817          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1818    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1819          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1820          double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1821          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1822          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1823          double *ptr_2 = &(res.getDataAtOffset(0));
1824    
1825          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1826        }
1827        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1828    
1829          // Prepare the DataConstant input
1830          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1831    
1832          // Borrow DataTagged input from Data object
1833          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1834    
1835          // Prepare a DataTagged output 2
1836          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1837          res.tag();
1838          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1839    
1840          // Prepare offset into DataConstant
1841          int offset_0 = tmp_0->getPointOffset(0,0);
1842          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1843          // Get the views
1844    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1845    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1846    //       // Get the pointers to the actual data
1847    //       double *ptr_1 = &((view_1.getData())[0]);
1848    //       double *ptr_2 = &((view_2.getData())[0]);
1849    
1850          // Get the pointers to the actual data
1851          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1852          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1853    
1854          // Compute a result for the default
1855          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1856          // Compute a result for each tag
1857          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1858          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1859          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1860            tmp_2->addTag(i->first);
1861    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1862            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1863            double *ptr_1 = &view_1.getData(0);
1864            double *ptr_2 = &view_2.getData(0);*/
1865            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1866            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1867    
1868            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1869          }
1870    
1871        }
1872        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1873    
1874          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1875          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1876          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1877          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1878    
1879          int sampleNo_1,dataPointNo_1;
1880          int numSamples_1 = arg_1_Z.getNumSamples();
1881          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1882          int offset_0 = tmp_0->getPointOffset(0,0);
1883          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1884          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1885            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1886              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1887              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1888    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1889    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1890    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1891    
1892              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1893              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1894              double *ptr_2 = &(res.getDataAtOffset(offset_2));
1895              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1896            }
1897          }
1898    
1899        }
1900        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1901    
1902          // Borrow DataTagged input from Data object
1903          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1904    
1905          // Prepare the DataConstant input
1906          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1907    
1908          // Prepare a DataTagged output 2
1909          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1910          res.tag();
1911          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1912    
1913          // Prepare offset into DataConstant
1914          int offset_1 = tmp_1->getPointOffset(0,0);
1915    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1916          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1917          // Get the views
1918    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1919    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1920    //       // Get the pointers to the actual data
1921    //       double *ptr_0 = &((view_0.getData())[0]);
1922    //       double *ptr_2 = &((view_2.getData())[0]);
1923          // Get the pointers to the actual data
1924          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1925          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1926          // Compute a result for the default
1927          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1928          // Compute a result for each tag
1929          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1930          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1931          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1932            tmp_2->addTag(i->first);
1933    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1934    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1935    //         double *ptr_0 = &view_0.getData(0);
1936    //         double *ptr_2 = &view_2.getData(0);
1937            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1938            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1939            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1940          }
1941    
1942        }
1943        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1944    
1945          // Borrow DataTagged input from Data object
1946          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1947    
1948          // Borrow DataTagged input from Data object
1949          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1950    
1951          // Prepare a DataTagged output 2
1952          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1953          res.tag();        // DataTagged output
1954          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1955    
1956    //       // Get the views
1957    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1958    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1959    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1960    //       // Get the pointers to the actual data
1961    //       double *ptr_0 = &((view_0.getData())[0]);
1962    //       double *ptr_1 = &((view_1.getData())[0]);
1963    //       double *ptr_2 = &((view_2.getData())[0]);
1964    
1965          // Get the pointers to the actual data
1966          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1967          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1968          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1969    
1970          // Compute a result for the default
1971          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1972          // Merge the tags
1973          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1974          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1975          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1976          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1977            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
1978          }
1979          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1980            tmp_2->addTag(i->first);
1981          }
1982          // Compute a result for each tag
1983          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1984          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1985    
1986    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1987    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1988    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1989    //         double *ptr_0 = &view_0.getData(0);
1990    //         double *ptr_1 = &view_1.getData(0);
1991    //         double *ptr_2 = &view_2.getData(0);
1992    
1993            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1994            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1995            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1996    
1997            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1998          }
1999    
2000        }
2001        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2002    
2003          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2004          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2005          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2006          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2007          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2008    
2009          int sampleNo_0,dataPointNo_0;
2010          int numSamples_0 = arg_0_Z.getNumSamples();
2011          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2012          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2013          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2014            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2015            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2016            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2017              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2018              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2019    
2020    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2021    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2022              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2023              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2024    
2025    
2026              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2027            }
2028          }
2029    
2030        }
2031        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2032    
2033          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2034          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2035          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2036          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2037    
2038          int sampleNo_0,dataPointNo_0;
2039          int numSamples_0 = arg_0_Z.getNumSamples();
2040          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2041          int offset_1 = tmp_1->getPointOffset(0,0);
2042          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2043          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2044            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2045              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2046              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2047    
2048    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2049    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2050    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2051    
2052              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2053              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2054              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2055    
2056    
2057              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2058            }
2059          }
2060    
2061        }
2062        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2063    
2064          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2065          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2066          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2067          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2068          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2069    
2070          int sampleNo_0,dataPointNo_0;
2071          int numSamples_0 = arg_0_Z.getNumSamples();
2072          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2073          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2074          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2075            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2076            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2077            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2078              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2079              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2080              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2081              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2082              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2083            }
2084          }
2085    
2086        }
2087        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2088    
2089          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2090          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2091          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2092          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2093          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2094    
2095          int sampleNo_0,dataPointNo_0;
2096          int numSamples_0 = arg_0_Z.getNumSamples();
2097          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2098          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2099          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2100            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2101              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2102              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2103              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2104              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2105              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2106              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2107              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2108            }
2109          }
2110    
2111        }
2112        else {
2113          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2114        }
2115    
2116      } else if (0 == rank0) {
2117    
2118        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2119          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2120          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2121          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2122          double *ptr_2 = &(res.getDataAtOffset(0));
2123          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2124        }
2125        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2126    
2127          // Prepare the DataConstant input
2128          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2129    
2130          // Borrow DataTagged input from Data object
2131          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2132    
2133          // Prepare a DataTagged output 2
2134          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2135          res.tag();
2136          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2137    
2138          // Prepare offset into DataConstant
2139          int offset_0 = tmp_0->getPointOffset(0,0);
2140          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2141          // Get the views
2142    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2143    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2144    //       // Get the pointers to the actual data
2145    //       double *ptr_1 = &((view_1.getData())[0]);
2146    //       double *ptr_2 = &((view_2.getData())[0]);
2147           double *ptr_1 = &(tmp_1->getDefaultValue(0));
2148           double *ptr_2 = &(tmp_2->getDefaultValue(0));
2149    
2150          // Compute a result for the default
2151          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2152          // Compute a result for each tag
2153          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2154          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2155          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2156            tmp_2->addTag(i->first);
2157    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2158    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2159    //         double *ptr_1 = &view_1.getData(0);
2160    //         double *ptr_2 = &view_2.getData(0);
2161            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2162            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2163            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2164          }
2165    
2166        }
2167        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2168    
2169          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2170          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2171          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2172          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2173    
2174          int sampleNo_1,dataPointNo_1;
2175          int numSamples_1 = arg_1_Z.getNumSamples();
2176          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2177          int offset_0 = tmp_0->getPointOffset(0,0);
2178          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2179          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2180            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2181              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2182              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2183              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2184              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2185              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2186              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2187    
2188            }
2189          }
2190    
2191        }
2192        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2193    
2194          // Borrow DataTagged input from Data object
2195          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2196    
2197          // Prepare the DataConstant input
2198          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2199    
2200          // Prepare a DataTagged output 2
2201          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2202          res.tag();
2203          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2204    
2205          // Prepare offset into DataConstant
2206          int offset_1 = tmp_1->getPointOffset(0,0);
2207    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2208          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2209          // Get the views
2210    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2211          DataArrayView view_2 = tmp_2->getDefaultValue();
2212          // Get the pointers to the actual data
2213          double *ptr_0 = &((view_0.getData())[0]);
2214          double *ptr_2 = &((view_2.getData())[0]);*/
2215    
2216          // Get the pointers to the actual data
2217          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2218          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2219    
2220    
2221          // Compute a result for the default
2222          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2223          // Compute a result for each tag
2224          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2225          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2226          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2227            tmp_2->addTag(i->first);
2228    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2229            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2230            double *ptr_0 = &view_0.getData(0);
2231            double *ptr_2 = &view_2.getData(0);*/
2232            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2233            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2234    
2235            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2236          }
2237    
2238        }
2239        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2240    
2241          // Borrow DataTagged input from Data object
2242          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2243    
2244          // Borrow DataTagged input from Data object
2245          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2246    
2247          // Prepare a DataTagged output 2
2248          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2249          res.tag();        // DataTagged output
2250          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2251    
2252          // Get the views
2253    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2254          DataArrayView view_1 = tmp_1->getDefaultValue();
2255          DataArrayView view_2 = tmp_2->getDefaultValue();
2256          // Get the pointers to the actual data
2257          double *ptr_0 = &((view_0.getData())[0]);
2258          double *ptr_1 = &((view_1.getData())[0]);
2259          double *ptr_2 = &((view_2.getData())[0]);*/
2260    
2261          // Get the pointers to the actual data
2262          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2263          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2264          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2265    
2266    
2267          // Compute a result for the default
2268          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2269          // Merge the tags
2270          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2271          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2272          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2273          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2274            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2275          }
2276          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2277            tmp_2->addTag(i->first);
2278          }
2279          // Compute a result for each tag
2280          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2281          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2282    
2283    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2284            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2285            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2286            double *ptr_0 = &view_0.getData(0);
2287            double *ptr_1 = &view_1.getData(0);
2288            double *ptr_2 = &view_2.getData(0);*/
2289    
2290            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2291            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2292            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2293    
2294            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2295          }
2296    
2297        }
2298        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2299    
2300          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2301          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2302          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2303          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2304          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2305    
2306          int sampleNo_0,dataPointNo_0;
2307          int numSamples_0 = arg_0_Z.getNumSamples();
2308          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2309          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2310          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2311            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2312            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2313            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2314              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2315              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2316              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2317              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2318              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2319            }
2320          }
2321    
2322        }
2323        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2324    
2325          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2326          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2327          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2328          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2329    
2330          int sampleNo_0,dataPointNo_0;
2331          int numSamples_0 = arg_0_Z.getNumSamples();
2332          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2333          int offset_1 = tmp_1->getPointOffset(0,0);
2334          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2335          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2336            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2337              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2338              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2339              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2340              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2341              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2342              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2343            }
2344          }
2345    
2346    
2347        }
2348        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2349    
2350          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2351          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2352          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2353          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2354          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2355    
2356          int sampleNo_0,dataPointNo_0;
2357          int numSamples_0 = arg_0_Z.getNumSamples();
2358          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2359          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2360          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2361            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2362            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2363            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2364              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2365              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2366              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2367              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2368              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2369            }
2370          }
2371    
2372        }
2373        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2374    
2375          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2376          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2377          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2378          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2379          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2380    
2381          int sampleNo_0,dataPointNo_0;
2382          int numSamples_0 = arg_0_Z.getNumSamples();
2383          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2384          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2385          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2386            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2387              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2388              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2389              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2390              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2391              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2392              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2393              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2394            }
2395          }
2396    
2397        }
2398        else {
2399          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2400        }
2401    
2402      } else if (0 == rank1) {
2403    
2404        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2405          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2406          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2407          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2408          double *ptr_2 = &(res.getDataAtOffset(0));
2409          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2410        }
2411        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2412    
2413          // Prepare the DataConstant input
2414          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2415    
2416          // Borrow DataTagged input from Data object
2417          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2418    
2419          // Prepare a DataTagged output 2
2420          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2421          res.tag();
2422          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2423    
2424          // Prepare offset into DataConstant
2425          int offset_0 = tmp_0->getPointOffset(0,0);
2426          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2427          // Get the views
2428    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2429          DataArrayView view_2 = tmp_2->getDefaultValue();
2430          // Get the pointers to the actual data
2431          double *ptr_1 = &((view_1.getData())[0]);
2432          double *ptr_2 = &((view_2.getData())[0]);*/
2433          //Get the pointers to the actual data
2434          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2435          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2436    
2437          // Compute a result for the default
2438          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2439          // Compute a result for each tag
2440          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2441          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2442          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2443            tmp_2->addTag(i->first);
2444    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2445    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2446    //         double *ptr_1 = &view_1.getData(0);
2447    //         double *ptr_2 = &view_2.getData(0);
2448            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2449            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2450    
2451    
2452            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2453          }
2454    
2455        }
2456        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2457    
2458          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2459          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2460          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2461          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2462    
2463          int sampleNo_1,dataPointNo_1;
2464          int numSamples_1 = arg_1_Z.getNumSamples();
2465          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2466          int offset_0 = tmp_0->getPointOffset(0,0);
2467          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2468          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2469            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2470              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2471              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2472              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2473              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2474              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2475              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2476            }
2477          }
2478    
2479        }
2480        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2481    
2482          // Borrow DataTagged input from Data object
2483          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2484    
2485          // Prepare the DataConstant input
2486          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2487    
2488          // Prepare a DataTagged output 2
2489          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2490          res.tag();
2491          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2492    
2493          // Prepare offset into DataConstant
2494          int offset_1 = tmp_1->getPointOffset(0,0);
2495          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2496          // Get the views
2497    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2498    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2499    //       // Get the pointers to the actual data
2500    //       double *ptr_0 = &((view_0.getData())[0]);
2501    //       double *ptr_2 = &((view_2.getData())[0]);
2502          // Get the pointers to the actual data
2503          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2504          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2505          // Compute a result for the default
2506          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2507          // Compute a result for each tag
2508          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2509          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2510          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2511            tmp_2->addTag(i->first);
2512    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2513            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2514            double *ptr_0 = &view_0.getData(0);
2515            double *ptr_2 = &view_2.getData(0);*/
2516            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2517            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2518            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2519          }
2520    
2521        }
2522        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2523    
2524          // Borrow DataTagged input from Data object
2525          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2526    
2527          // Borrow DataTagged input from Data object
2528          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2529    
2530          // Prepare a DataTagged output 2
2531          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2532          res.tag();        // DataTagged output
2533          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2534    
2535          // Get the views
2536    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2537    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2538    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2539    //       // Get the pointers to the actual data
2540    //       double *ptr_0 = &((view_0.getData())[0]);
2541    //       double *ptr_1 = &((view_1.getData())[0]);
2542    //       double *ptr_2 = &((view_2.getData())[0]);
2543    
2544          // Get the pointers to the actual data
2545          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2546          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2547          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2548    
2549          // Compute a result for the default
2550          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2551          // Merge the tags
2552          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2553          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2554          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2555          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2556            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2557          }
2558          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2559            tmp_2->addTag(i->first);
2560          }
2561          // Compute a result for each tag
2562          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2563          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2564    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2565    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2566    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2567    //         double *ptr_0 = &view_0.getData(0);
2568    //         double *ptr_1 = &view_1.getData(0);
2569    //         double *ptr_2 = &view_2.getData(0);
2570    
2571            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2572            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2573            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2574            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2575          }
2576    
2577        }
2578        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2579    
2580          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2581          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2582          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2583          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2584          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2585    
2586          int sampleNo_0,dataPointNo_0;
2587          int numSamples_0 = arg_0_Z.getNumSamples();
2588          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2589          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2590          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2591            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2592            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2593            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2594              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2595              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2596              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2597              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2598              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2599            }
2600          }
2601    
2602        }
2603        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2604    
2605          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2606          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2607          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2608          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2609    
2610          int sampleNo_0,dataPointNo_0;
2611          int numSamples_0 = arg_0_Z.getNumSamples();
2612          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2613          int offset_1 = tmp_1->getPointOffset(0,0);
2614          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2615          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2616            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2617              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2618              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2619              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2620              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2621              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2622              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2623            }
2624          }
2625    
2626    
2627        }
2628        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2629    
2630          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2631          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2632          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2633          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2634          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2635    
2636          int sampleNo_0,dataPointNo_0;
2637          int numSamples_0 = arg_0_Z.getNumSamples();
2638          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2639          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2640          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2641            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2642            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2643            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2644              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2645              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2646              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2647              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2648              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2649            }
2650          }
2651    
2652        }
2653        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2654    
2655          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2656          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2657          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2658          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2659          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2660    
2661          int sampleNo_0,dataPointNo_0;
2662          int numSamples_0 = arg_0_Z.getNumSamples();
2663          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2664          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2665          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2666            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2667              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2668              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2669              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2670              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2671              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2672              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2673              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2674            }
2675          }
2676    
2677        }
2678        else {
2679          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2680        }
2681    
2682      } else {
2683        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2684      }
2685    
2686      return res;
2687    }
2688    
2689    template <typename UnaryFunction>
2690    Data
2691    C_TensorUnaryOperation(Data const &arg_0,
2692                           UnaryFunction operation)
2693    {
2694      if (arg_0.isEmpty())  // do this before we attempt to interpolate
2695      {
2696         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2697      }
2698    
2699      // Interpolate if necessary and find an appropriate function space
2700      Data arg_0_Z = Data(arg_0);
2701    
2702      // Get rank and shape of inputs
2703      int rank0 = arg_0_Z.getDataPointRank();
2704      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2705      int size0 = arg_0_Z.getDataPointSize();
2706    
2707      // Declare output Data object
2708      Data res;
2709    
2710      if (arg_0_Z.isConstant()) {
2711        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2712    //     double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2713    //     double *ptr_2 = &((res.getPointDataView().getData())[0]);
2714        double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2715        double *ptr_2 = &(res.getDataAtOffset(0));
2716        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2717      }
2718      else if (arg_0_Z.isTagged()) {
2719    
2720        // Borrow DataTagged input from Data object
2721        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2722    
2723        // Prepare a DataTagged output 2
2724        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2725        res.tag();
2726        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2727    
2728    //     // Get the views
2729    //     DataArrayView view_0 = tmp_0->getDefaultValue();
2730    //     DataArrayView view_2 = tmp_2->getDefaultValue();
2731    //     // Get the pointers to the actual data
2732    //     double *ptr_0 = &((view_0.getData())[0]);
2733    //     double *ptr_2 = &((view_2.getData())[0]);
2734        // Get the pointers to the actual data
2735        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2736        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2737        // Compute a result for the default
2738        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2739        // Compute a result for each tag
2740        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2741        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2742        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2743          tmp_2->addTag(i->first);
2744    //       DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2745    //       DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2746    //       double *ptr_0 = &view_0.getData(0);
2747    //       double *ptr_2 = &view_2.getData(0);
2748          double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2749          double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2750          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2751        }
2752    
2753      }
2754      else if (arg_0_Z.isExpanded()) {
2755    
2756        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2757        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2758        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2759    
2760        int sampleNo_0,dataPointNo_0;
2761        int numSamples_0 = arg_0_Z.getNumSamples();
2762        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2763        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2764        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2765          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2766    //         int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2767    //         int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2768    //         double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2769    //         double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2770            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2771            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2772            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2773            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2774            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2775          }
2776        }
2777      }
2778      else {
2779        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2780      }
2781    
2782      return res;
2783    }
2784    
2785  }  }
2786  #endif  #endif

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

  ViewVC Help
Powered by ViewVC 1.1.26