/[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/esys2/escript/src/Data/Data.h revision 147 by jgs, Fri Aug 12 01:45:47 2005 UTC branches/more_shared_ptrs_from_1812/escript/src/Data.h revision 1820 by jfenwick, Wed Oct 1 03:48:18 2008 UTC
# Line 1  Line 1 
1  // $Id$  
2  /*  /*******************************************************
3   ******************************************************************************  *
4   *                                                                            *  * Copyright (c) 2003-2008 by University of Queensland
5   *       COPYRIGHT ACcESS 2004 -  All Rights Reserved                         *  * Earth Systems Science Computational Center (ESSCC)
6   *                                                                            *  * http://www.uq.edu.au/esscc
7   * This software is the property of ACcESS.  No part of this code             *  *
8   * may be copied in any form or by any means without the expressed written    *  * Primary Business: Queensland, Australia
9   * consent of ACcESS.  Copying, use or modification of this software          *  * Licensed under the Open Software License version 3.0
10   * by any unauthorised person is illegal unless that                          *  * http://www.opensource.org/licenses/osl-3.0.php
11   * person has a software license agreement with ACcESS.                       *  *
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 "escript/Data/DataAbstract.h"  #include "DataAbstract.h"
22  #include "escript/Data/DataTagged.h"  #include "DataAlgorithm.h"
23  #include "escript/Data/DataAlgorithm.h"  #include "FunctionSpace.h"
24  #include "escript/Data/FunctionSpace.h"  #include "BinaryOp.h"
25  #include "escript/Data/BinaryOp.h"  #include "UnaryOp.h"
26  #include "escript/Data/UnaryOp.h"  #include "DataException.h"
27  #include "escript/Data/DataException.h"  #include "DataTypes.h"
28    
29  extern "C" {  extern "C" {
30  #include "escript/Data/DataC.h"  #include "DataC.h"
31    /* #include "paso/Paso.h" doesn't belong in this file...causes trouble for BruceFactory.cpp */
32  }  }
33    
34  #include <iostream>  #include "esysmpi.h"
35  #include <string>  #include <string>
 #include <memory>  
36  #include <algorithm>  #include <algorithm>
37    #include <sstream>
38    
39    
40  #include <boost/shared_ptr.hpp>  #include <boost/shared_ptr.hpp>
41  #include <boost/python/object.hpp>  #include <boost/python/object.hpp>
 #include <boost/python/list.hpp>  
42  #include <boost/python/tuple.hpp>  #include <boost/python/tuple.hpp>
43  #include <boost/python/numeric.hpp>  #include <boost/python/numeric.hpp>
44    
45  namespace escript {  namespace escript {
46    
47  //  //
48  // Forward declaration for various implimentations of Data.  // Forward declaration for various implementations of Data.
 class DataEmpty;  
49  class DataConstant;  class DataConstant;
50  class DataTagged;  class DataTagged;
51  class DataExpanded;  class DataExpanded;
52    
53  /**  /**
54     \brief     \brief
55     Data creates the appropriate Data object for the given construction     Data 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 71  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 80  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 87  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 95  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 123  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 135  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 167  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 182  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 195  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 202  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       Perform a deep copy.       Destructor
211    */    */
212      ESCRIPT_DLL_API
213      ~Data();
214    
215      /**
216         \brief Make this object a deep copy of "other".
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 fills the expanded Data object from values of a  python numarray object.       \brief
247         Returns trueif the data object is protected against update
248    
249    */    */
250    void    ESCRIPT_DLL_API
251    fillFromNumArray(const boost::python::numeric::array);    bool
252      isProtected() const;
253    
254    /**    /**
255       \brief       \brief
256       Return the values of all data-points for the given sample 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    convertToNumArrayFromSampleNo(int sampleNo);    getValueOfDataPoint(int dataPointNo);
261    
262    /**    /**
263       \brief       \brief
264       Return the value of the specified data-point as a single python numarray object.       sets the values of a data-point from a python object on this process
265    */    */
266      ESCRIPT_DLL_API
267      void
268      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    const boost::python::numeric::array
292    convertToNumArrayFromDPNo(int sampleNo,    getValueOfGlobalDataPoint(int procNo, int dataPointNo);
293                              int dataPointNo);  
294      /**
295         \brief
296         Return the tag number associated with the given data-point.
297    
298      */
299      ESCRIPT_DLL_API
300      int
301      getTagNumber(int dpno);
302    
303    /**    /**
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 296  class Data { Line 363  class Data {
363       If possible convert this Data to DataTagged. This will only allow       If possible convert this Data to DataTagged. This will only allow
364       Constant data to be converted to tagged. An attempt to convert       Constant data to be converted to tagged. An attempt to convert
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 304  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 311  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 318  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 332  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 343  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 350  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();
# Line 361  class Data { Line 439  class Data {
439       \brief       \brief
440       Return a copy of the domain.       Return a copy of the domain.
441    */    */
442      ESCRIPT_DLL_API
443    const AbstractDomain    const AbstractDomain
444    getCopyOfDomain() const;    getCopyOfDomain() const;
445    
# Line 368  class Data { Line 447  class Data {
447       \brief       \brief
448       Return the rank of the point data.       Return the rank of the point data.
449    */    */
450      ESCRIPT_DLL_API
451    inline    inline
452    int    int
453    getDataPointRank() const    getDataPointRank() const
454    {    {
455      return m_data->getPointDataView().getRank();  //    return m_data->getPointDataView().getRank();
456        return m_data->getRank();
457    }    }
458    
459    /**    /**
460       \brief       \brief
461         Return the number of data points
462      */
463      ESCRIPT_DLL_API
464      inline
465      int
466      getNumDataPoints() const
467      {
468        return getNumSamples() * getNumDataPointsPerSample();
469      }
470      /**
471         \brief
472       Return the number of samples.       Return the number of samples.
473    */    */
474      ESCRIPT_DLL_API
475    inline    inline
476    int    int
477    getNumSamples() const    getNumSamples() const
# Line 390  class Data { Line 483  class Data {
483       \brief       \brief
484       Return the number of data points per sample.       Return the number of data points per sample.
485    */    */
486      ESCRIPT_DLL_API
487    inline    inline
488    int    int
489    getNumDataPointsPerSample() const    getNumDataPointsPerSample() const
# Line 397  class Data { Line 491  class Data {
491      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
492    }    }
493    
494    
495      /**
496        \brief
497        Return the number of values in the shape for this object.
498      */
499      ESCRIPT_DLL_API
500      int
501      getNoValues() const
502      {
503        return m_data->getNoValues();
504      }
505    
506    
507      /**
508         \brief
509         dumps the object into a netCDF file
510      */
511      ESCRIPT_DLL_API
512      void
513      dump(const std::string fileName) const;
514    /**    /**
515       \brief       \brief
516       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
517       preferred interface but is provided for use by C code.       preferred interface but is provided for use by C code.
518       \param sampleNo - Input - the given sample no.       \param sampleNo - Input - the given sample no.
519    */    */
520      ESCRIPT_DLL_API
521    inline    inline
522    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
523    getSampleData(DataAbstract::ValueType::size_type sampleNo)    getSampleData(DataAbstract::ValueType::size_type sampleNo)
# Line 416  class Data { Line 531  class Data {
531       access data that isn't tagged an exception will be thrown.       access data that isn't tagged an exception will be thrown.
532       \param tag - Input - the tag key.       \param tag - Input - the tag key.
533    */    */
534      ESCRIPT_DLL_API
535    inline    inline
536    DataAbstract::ValueType::value_type*    DataAbstract::ValueType::value_type*
537    getSampleDataByTag(int tag)    getSampleDataByTag(int tag)
# Line 423  class Data { Line 539  class Data {
539      return m_data->getSampleDataByTag(tag);      return m_data->getSampleDataByTag(tag);
540    }    }
541    
542    /**  //  /**
543       \brief  /*     \brief
544       Assign the given value to the data-points referenced by the given       Return a view into the data for the data point specified.
545       reference number.       NOTE: Construction of the DataArrayView is a relatively expensive
546         operation.
547       The value supplied is a python numarray object.  The data from this numarray       \param sampleNo - Input -
548       is unpacked into a DataArray, and this is used to set the corresponding       \param dataPointNo - Input -*/
549       data-points in the underlying Data object.  //  */
550    //   ESCRIPT_DLL_API
551       If the underlying Data object cannot be accessed via reference numbers, an  //   inline
552       exception will be thrown.  //   DataArrayView
553    //   getDataPoint(int sampleNo,
554       \param ref - Input - reference number.  //                int dataPointNo)
555       \param value - Input - value to assign to data-points associated with  //   {
556                              the given reference number.  //                 return m_data->getDataPoint(sampleNo,dataPointNo);
557    */  //   }
   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.  
558    
      \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);  
559    
560    /**    /**
561       \brief       \brief
# Line 470  class Data { Line 565  class Data {
565       \param sampleNo - Input -       \param sampleNo - Input -
566       \param dataPointNo - Input -       \param dataPointNo - Input -
567    */    */
568      ESCRIPT_DLL_API
569      DataTypes::ValueType::const_reference
570      getDataPoint(int sampleNo, int dataPointNo) const;
571    
572    
573      ESCRIPT_DLL_API
574      DataTypes::ValueType::reference
575      getDataPoint(int sampleNo, int dataPointNo);
576    
577    
578    
579      /**
580         \brief
581         Return the offset for the given sample and point within the sample
582      */
583      ESCRIPT_DLL_API
584    inline    inline
585    DataArrayView    DataTypes::ValueType::size_type
586    getDataPoint(int sampleNo,    getDataOffset(int sampleNo,
587                 int dataPointNo)                 int dataPointNo)
588    {    {
589      return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getPointOffset(sampleNo,dataPointNo);
590    }    }
591    
592    /**    /**
593       \brief       \brief
594       Return a reference to the data point shape.       Return a reference to the data point shape.
595    */    */
596    const DataArrayView::ShapeType&    ESCRIPT_DLL_API
597    getDataPointShape() const;    inline
598      const DataTypes::ShapeType&
599      getDataPointShape() const
600      {
601        return m_data->getShape();
602      }
603    
604    /**    /**
605       \brief       \brief
606       Return the data point shape as a tuple of integers.       Return the data point shape as a tuple of integers.
607    */    */
608      ESCRIPT_DLL_API
609    const boost::python::tuple    const boost::python::tuple
610    getShapeTuple() const;    getShapeTuple() const;
611    
# Line 497  class Data { Line 614  class Data {
614       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
615       data point shape dimensions.       data point shape dimensions.
616    */    */
617      ESCRIPT_DLL_API
618    int    int
619    getDataPointSize() const;    getDataPointSize() const;
620    
# Line 504  class Data { Line 622  class Data {
622       \brief       \brief
623       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
624    */    */
625    DataArrayView::ValueType::size_type    ESCRIPT_DLL_API
626      DataTypes::ValueType::size_type
627    getLength() const;    getLength() const;
628    
629    
630    
631    /**    /**
632       \brief       \brief
633       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag assocciated with name. Implicitly converts this
634       object to type DataTagged. Throws an exception if this object       object to type DataTagged. Throws an exception if this object
635       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
636       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
637       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
638        ==>*
639    */    */
640      ESCRIPT_DLL_API
641      void
642      setTaggedValueByName(std::string name,
643                           const boost::python::object& value);
644    
645      /**
646         \brief
647         Assign the given value to the tag. Implicitly converts this
648         object to type DataTagged if it is constant.
649    
650         \param tagKey - Input - Integer key.
651         \param value - Input - Value to associate with given key.
652        ==>*
653      */
654      ESCRIPT_DLL_API
655    void    void
656    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
657                   const boost::python::object& value);                   const boost::python::object& value);
658    
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
671    //   setTaggedValueFromCPP(int tagKey,
672    //                         const DataArrayView& value);
673    
674    /**    /**
675       \brief       \brief
676       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
677       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
678       cannot be converted to a DataTagged object.  
679       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
680         \param pointshape - Input - The shape of the value parameter
681       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
682         \param dataOffset - Input - Offset of the begining of the point within the value parameter
683    */    */
684      ESCRIPT_DLL_API
685    void    void
686    setTaggedValueFromCPP(int tagKey,    setTaggedValueFromCPP(int tagKey,
687                          const DataArrayView& value);              const DataTypes::ShapeType& pointshape,
688                            const DataTypes::ValueType& value,
689                int dataOffset=0);
690    
691    
692    
693    /**    /**
694      \brief      \brief
695      Copy other Data object into this Data object where mask is positive.      Copy other Data object into this Data object where mask is positive.
696    */    */
697      ESCRIPT_DLL_API
698    void    void
699    copyWithMask(const Data& other,    copyWithMask(const Data& other,
700                 const Data& mask);                 const Data& mask);
# Line 545  class Data { Line 705  class Data {
705    
706    /**    /**
707       \brief       \brief
708         set all values to zero
709         *
710      */
711      ESCRIPT_DLL_API
712      void
713      setToZero();
714    
715      /**
716         \brief
717       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
718       the result as a Data object.       the result as a Data object.
719       *       *
720    */    */
721      ESCRIPT_DLL_API
722    Data    Data
723    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
724    /**    /**
725       \brief       \brief
726       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
727       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.
728       *       *
729    */    */
730      ESCRIPT_DLL_API
731    Data    Data
732    gradOn(const FunctionSpace& functionspace) const;    gradOn(const FunctionSpace& functionspace) const;
733    
734      ESCRIPT_DLL_API
735    Data    Data
736    grad() const;    grad() const;
737    
# Line 569  class Data { Line 740  class Data {
740       Calculate the integral over the function space domain.       Calculate the integral over the function space domain.
741       *       *
742    */    */
743      ESCRIPT_DLL_API
744    boost::python::numeric::array    boost::python::numeric::array
745    integrate() const;    integrate() const;
746    
747    /**    /**
748       \brief       \brief
749         Returns 1./ Data object
750         *
751      */
752      ESCRIPT_DLL_API
753      Data
754      oneOver() const;
755      /**
756         \brief
757       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.
758       *       *
759    */    */
760      ESCRIPT_DLL_API
761    Data    Data
762    wherePositive() const;    wherePositive() const;
763    
# Line 585  class Data { Line 766  class Data {
766       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.
767       *       *
768    */    */
769      ESCRIPT_DLL_API
770    Data    Data
771    whereNegative() const;    whereNegative() const;
772    
# Line 593  class Data { Line 775  class Data {
775       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.
776       *       *
777    */    */
778      ESCRIPT_DLL_API
779    Data    Data
780    whereNonNegative() const;    whereNonNegative() const;
781    
# Line 601  class Data { Line 784  class Data {
784       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.
785       *       *
786    */    */
787      ESCRIPT_DLL_API
788    Data    Data
789    whereNonPositive() const;    whereNonPositive() const;
790    
# Line 609  class Data { Line 793  class Data {
793       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.
794       *       *
795    */    */
796      ESCRIPT_DLL_API
797    Data    Data
798    whereZero() const;    whereZero(double tol=0.0) const;
799    
800    /**    /**
801       \brief       \brief
802       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.
803       *       *
804    */    */
805      ESCRIPT_DLL_API
806    Data    Data
807    whereNonZero() const;    whereNonZero(double tol=0.0) const;
808    
809    /**    /**
810       \brief       \brief
811       Return the maximum absolute value of this Data object.       Return the maximum absolute value of this Data object.
812       *       *
813    */    */
814      ESCRIPT_DLL_API
815    double    double
816    Lsup() const;    Lsup() const;
817    
818    /**    /**
819       \brief       \brief
      Return the minimum absolute value of this Data object.  
      *  
   */  
   double  
   Linf() const;  
   
   /**  
      \brief  
820       Return the maximum value of this Data object.       Return the maximum value of this Data object.
821       *       *
822    */    */
823      ESCRIPT_DLL_API
824    double    double
825    sup() const;    sup() const;
826    
# Line 649  class Data { Line 829  class Data {
829       Return the minimum value of this Data object.       Return the minimum value of this Data object.
830       *       *
831    */    */
832      ESCRIPT_DLL_API
833    double    double
834    inf() const;    inf() const;
835    
# Line 657  class Data { Line 838  class Data {
838       Return the absolute value of each data point of this Data object.       Return the absolute value of each data point of this Data object.
839       *       *
840    */    */
841      ESCRIPT_DLL_API
842    Data    Data
843    abs() const;    abs() const;
844    
# Line 665  class Data { Line 847  class Data {
847       Return the maximum value of each data point of this Data object.       Return the maximum value of each data point of this Data object.
848       *       *
849    */    */
850      ESCRIPT_DLL_API
851    Data    Data
852    maxval() const;    maxval() const;
853    
# Line 673  class Data { Line 856  class Data {
856       Return the minimum value of each data point of this Data object.       Return the minimum value of each data point of this Data object.
857       *       *
858    */    */
859      ESCRIPT_DLL_API
860    Data    Data
861    minval() const;    minval() const;
862    
# Line 681  class Data { Line 865  class Data {
865       Return the (sample number, data-point number) of the data point with       Return the (sample number, data-point number) of the data point with
866       the minimum value in this Data object.       the minimum value in this Data object.
867    */    */
868      ESCRIPT_DLL_API
869    const boost::python::tuple    const boost::python::tuple
870    mindp() const;    minGlobalDataPoint() const;
871    
872      ESCRIPT_DLL_API
873      void
874      calc_minGlobalDataPoint(int& ProcNo,  int& DataPointNo) const;
875      /**
876         \brief
877         Return the sign of each data point of this Data object.
878         -1 for negative values, zero for zero values, 1 for positive values.
879         *
880      */
881      ESCRIPT_DLL_API
882      Data
883      sign() const;
884    
885    /**    /**
886       \brief       \brief
887       Return the length of each data point of this Data object.       Return the symmetric part of a matrix which is half the matrix plus its transpose.
      sqrt(sum(A[i,j,k,l]^2))  
888       *       *
889    */    */
890      ESCRIPT_DLL_API
891    Data    Data
892    length() const;    symmetric() const;
893    
894    /**    /**
895       \brief       \brief
896       Return the sign of each data point of this Data object.       Return the nonsymmetric part of a matrix which is half the matrix minus its transpose.
      -1 for negative values, zero for zero values, 1 for positive values.  
897       *       *
898    */    */
899      ESCRIPT_DLL_API
900    Data    Data
901    sign() const;    nonsymmetric() const;
902    
903      /**
904         \brief
905         Return the trace of a matrix
906         *
907      */
908      ESCRIPT_DLL_API
909      Data
910      trace(int axis_offset) const;
911    
912    /**    /**
913       \brief       \brief
914       Transpose each data point of this Data object around the given axis.       Transpose each data point of this Data object around the given axis.
      --* not implemented yet *--  
915       *       *
916    */    */
917      ESCRIPT_DLL_API
918      Data
919      transpose(int axis_offset) const;
920    
921      /**
922         \brief
923         Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.
924         Currently this function is restricted to rank 2, square shape, and dimension 3.
925         *
926      */
927      ESCRIPT_DLL_API
928      Data
929      eigenvalues() const;
930    
931      /**
932         \brief
933         Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.
934         the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than
935         tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the
936         first non-zero entry is positive.
937         Currently this function is restricted to rank 2, square shape, and dimension 3
938         *
939      */
940      ESCRIPT_DLL_API
941      const boost::python::tuple
942      eigenvalues_and_eigenvectors(const double tol=1.e-12) const;
943    
944      /**
945         \brief
946         swaps the components axis0 and axis1
947         *
948      */
949      ESCRIPT_DLL_API
950    Data    Data
951    transpose(int axis) const;    swapaxes(const int axis0, const int axis1) const;
952    
953    /**    /**
954       \brief       \brief
955       Calculate the trace of each data point of this Data object.       Return the error function erf of each data point of this Data object.
      sum(A[i,i,i,i])  
956       *       *
957    */    */
958      ESCRIPT_DLL_API
959    Data    Data
960    trace() const;    erf() const;
961    
962    /**    /**
963       \brief       \brief
964       Return the sin of each data point of this Data object.       Return the sin of each data point of this Data object.
965       *       *
966    */    */
967      ESCRIPT_DLL_API
968    Data    Data
969    sin() const;    sin() const;
970    
# Line 733  class Data { Line 973  class Data {
973       Return the cos of each data point of this Data object.       Return the cos of each data point of this Data object.
974       *       *
975    */    */
976      ESCRIPT_DLL_API
977    Data    Data
978    cos() const;    cos() const;
979    
# Line 741  class Data { Line 982  class Data {
982       Return the tan of each data point of this Data object.       Return the tan of each data point of this Data object.
983       *       *
984    */    */
985      ESCRIPT_DLL_API
986    Data    Data
987    tan() const;    tan() const;
988    
989    /**    /**
990       \brief       \brief
991         Return the asin of each data point of this Data object.
992         *
993      */
994      ESCRIPT_DLL_API
995      Data
996      asin() const;
997    
998      /**
999         \brief
1000         Return the acos of each data point of this Data object.
1001         *
1002      */
1003      ESCRIPT_DLL_API
1004      Data
1005      acos() const;
1006    
1007      /**
1008         \brief
1009         Return the atan of each data point of this Data object.
1010         *
1011      */
1012      ESCRIPT_DLL_API
1013      Data
1014      atan() const;
1015    
1016      /**
1017         \brief
1018         Return the sinh of each data point of this Data object.
1019         *
1020      */
1021      ESCRIPT_DLL_API
1022      Data
1023      sinh() const;
1024    
1025      /**
1026         \brief
1027         Return the cosh of each data point of this Data object.
1028         *
1029      */
1030      ESCRIPT_DLL_API
1031      Data
1032      cosh() const;
1033    
1034      /**
1035         \brief
1036         Return the tanh of each data point of this Data object.
1037         *
1038      */
1039      ESCRIPT_DLL_API
1040      Data
1041      tanh() const;
1042    
1043      /**
1044         \brief
1045         Return the asinh of each data point of this Data object.
1046         *
1047      */
1048      ESCRIPT_DLL_API
1049      Data
1050      asinh() const;
1051    
1052      /**
1053         \brief
1054         Return the acosh of each data point of this Data object.
1055         *
1056      */
1057      ESCRIPT_DLL_API
1058      Data
1059      acosh() const;
1060    
1061      /**
1062         \brief
1063         Return the atanh of each data point of this Data object.
1064         *
1065      */
1066      ESCRIPT_DLL_API
1067      Data
1068      atanh() const;
1069    
1070      /**
1071         \brief
1072       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.
1073       *       *
1074    */    */
1075      ESCRIPT_DLL_API
1076    Data    Data
1077    log() const;    log10() const;
1078    
1079    /**    /**
1080       \brief       \brief
1081       Return the natural log of each data point of this Data object.       Return the natural log of each data point of this Data object.
1082       *       *
1083    */    */
1084      ESCRIPT_DLL_API
1085    Data    Data
1086    ln() const;    log() const;
1087    
1088    /**    /**
1089       \brief       \brief
1090       Return the exponential function of each data point of this Data object.       Return the exponential function of each data point of this Data object.
1091       *       *
1092    */    */
1093      ESCRIPT_DLL_API
1094    Data    Data
1095    exp() const;    exp() const;
1096    
# Line 773  class Data { Line 1099  class Data {
1099       Return the square root of each data point of this Data object.       Return the square root of each data point of this Data object.
1100       *       *
1101    */    */
1102      ESCRIPT_DLL_API
1103    Data    Data
1104    sqrt() const;    sqrt() const;
1105    
# Line 781  class Data { Line 1108  class Data {
1108       Return the negation of each data point of this Data object.       Return the negation of each data point of this Data object.
1109       *       *
1110    */    */
1111      ESCRIPT_DLL_API
1112    Data    Data
1113    neg() const;    neg() const;
1114    
# Line 790  class Data { Line 1118  class Data {
1118       Simply returns this object unmodified.       Simply returns this object unmodified.
1119       *       *
1120    */    */
1121      ESCRIPT_DLL_API
1122    Data    Data
1123    pos() const;    pos() const;
1124    
# Line 800  class Data { Line 1129  class Data {
1129       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1130       *       *
1131    */    */
1132      ESCRIPT_DLL_API
1133    Data    Data
1134    powD(const Data& right) const;    powD(const Data& right) const;
1135    
1136    /**    /**
1137       \brief       \brief
1138       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.
1139        
1140       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1141       *       *
1142     */     */
1143      ESCRIPT_DLL_API
1144    Data    Data
1145    powO(const boost::python::object& right) const;    powO(const boost::python::object& right) const;
1146    
1147    /**    /**
1148       \brief       \brief
1149         Return the given power of each data point of this boost python object.
1150    
1151         \param left Input - the bases
1152         *
1153       */
1154    
1155      ESCRIPT_DLL_API
1156      Data
1157      rpowO(const boost::python::object& left) const;
1158    
1159      /**
1160         \brief
1161       writes the object to a file in the DX file format       writes the object to a file in the DX file format
1162    */    */
1163      ESCRIPT_DLL_API
1164    void    void
1165    saveDX(std::string fileName) const;    saveDX(std::string fileName) const;
1166    
# Line 824  class Data { Line 1168  class Data {
1168       \brief       \brief
1169       writes the object to a file in the VTK file format       writes the object to a file in the VTK file format
1170    */    */
1171      ESCRIPT_DLL_API
1172    void    void
1173    saveVTK(std::string fileName) const;    saveVTK(std::string fileName) const;
1174    
# Line 833  class Data { Line 1178  class Data {
1178       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1179       *       *
1180    */    */
1181      ESCRIPT_DLL_API
1182    Data& operator+=(const Data& right);    Data& operator+=(const Data& right);
1183      ESCRIPT_DLL_API
1184    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1185    
1186      ESCRIPT_DLL_API
1187      Data& operator=(const Data& other);
1188    
1189    /**    /**
1190       \brief       \brief
1191       Overloaded operator -=       Overloaded operator -=
1192       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1193       *       *
1194    */    */
1195      ESCRIPT_DLL_API
1196    Data& operator-=(const Data& right);    Data& operator-=(const Data& right);
1197      ESCRIPT_DLL_API
1198    Data& operator-=(const boost::python::object& right);    Data& operator-=(const boost::python::object& right);
1199    
1200   /**   /**
# Line 851  class Data { Line 1203  class Data {
1203       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1204       *       *
1205    */    */
1206      ESCRIPT_DLL_API
1207    Data& operator*=(const Data& right);    Data& operator*=(const Data& right);
1208      ESCRIPT_DLL_API
1209    Data& operator*=(const boost::python::object& right);    Data& operator*=(const boost::python::object& right);
1210    
1211   /**   /**
# Line 860  class Data { Line 1214  class Data {
1214       \param right - Input - The right hand side.       \param right - Input - The right hand side.
1215       *       *
1216    */    */
1217      ESCRIPT_DLL_API
1218    Data& operator/=(const Data& right);    Data& operator/=(const Data& right);
1219      ESCRIPT_DLL_API
1220    Data& operator/=(const boost::python::object& right);    Data& operator/=(const boost::python::object& right);
1221    
1222    /**    /**
1223       \brief       \brief
1224       Returns true if this can be interpolated to functionspace.       Returns true if this can be interpolated to functionspace.
1225    */    */
1226      ESCRIPT_DLL_API
1227    bool    bool
1228    probeInterpolation(const FunctionSpace& functionspace) const;    probeInterpolation(const FunctionSpace& functionspace) const;
1229    
# Line 885  class Data { Line 1242  class Data {
1242       \param key - Input - python slice tuple specifying       \param key - Input - python slice tuple specifying
1243       slice to return.       slice to return.
1244    */    */
1245      ESCRIPT_DLL_API
1246    Data    Data
1247    getItem(const boost::python::object& key) const;    getItem(const boost::python::object& key) const;
1248    
# Line 899  class Data { Line 1257  class Data {
1257       slice to copy from value.       slice to copy from value.
1258       \param value - Input - Data object to copy from.       \param value - Input - Data object to copy from.
1259    */    */
1260      ESCRIPT_DLL_API
1261    void    void
1262    setItemD(const boost::python::object& key,    setItemD(const boost::python::object& key,
1263             const Data& value);             const Data& value);
1264    
1265      ESCRIPT_DLL_API
1266    void    void
1267    setItemO(const boost::python::object& key,    setItemO(const boost::python::object& key,
1268             const boost::python::object& value);             const boost::python::object& value);
# Line 915  class Data { Line 1275  class Data {
1275       this Data object.       this Data object.
1276    */    */
1277    template <class UnaryFunction>    template <class UnaryFunction>
1278      ESCRIPT_DLL_API
1279    inline    inline
1280    void    void
1281    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1282    
1283    /**    /**
1284       \brief       \brief
# Line 926  class Data { Line 1287  class Data {
1287       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1288       *       *
1289    */    */
1290      ESCRIPT_DLL_API
1291    Data    Data
1292    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataTypes::RegionType& region) const;
1293    
1294    /**    /**
1295       \brief       \brief
# Line 937  class Data { Line 1299  class Data {
1299       \param region - Input - Region to copy.       \param region - Input - Region to copy.
1300       *       *
1301    */    */
1302      ESCRIPT_DLL_API
1303    void    void
1304    setSlice(const Data& value,    setSlice(const Data& value,
1305             const DataArrayView::RegionType& region);             const DataTypes::RegionType& region);
1306    
1307    /**    /**
1308       \brief       \brief
1309       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.  
1310    */    */
1311      ESCRIPT_DLL_API
1312    void    void
1313    archiveData(const std::string fileName);          print(void);
1314    
1315    /**    /**
1316       \brief       \brief
1317       Extract the Data object archived in the given file, overwriting       return the MPI rank number of the local data
1318       the current Data object.                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1319       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.  
1320    */    */
1321    void    ESCRIPT_DLL_API
1322    extractData(const std::string fileName,          int
1323                const FunctionSpace& fspace);          get_MPIRank(void) const;
1324    
1325      /**
1326         \brief
1327         return the MPI rank number of the local data
1328                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1329                     is returned
1330      */
1331      ESCRIPT_DLL_API
1332            int
1333            get_MPISize(void) const;
1334    
1335      /**
1336         \brief
1337         return the MPI rank number of the local data
1338                     MPI_COMM_WORLD is assumed and returned.
1339      */
1340      ESCRIPT_DLL_API
1341            MPI_Comm
1342            get_MPIComm(void) const;
1343    
1344      /**
1345         \brief
1346         return the object produced by the factory, which is a DataConstant or DataExpanded
1347        TODO Ownership of this object should be explained in doco.
1348      */
1349      ESCRIPT_DLL_API
1350            DataAbstract*
1351            borrowData(void) const;
1352    
1353    
1354      /**
1355         \brief
1356         Return a pointer to the beginning of the datapoint at the specified offset.
1357         TODO Eventually these should be inlined.
1358         \param i - position(offset) in the underlying datastructure
1359      */
1360      ESCRIPT_DLL_API
1361            DataTypes::ValueType::const_reference
1362            getDataAtOffset(DataTypes::ValueType::size_type i) const;
1363    
1364    
1365      ESCRIPT_DLL_API
1366            DataTypes::ValueType::reference
1367            getDataAtOffset(DataTypes::ValueType::size_type i);
1368    
1369   protected:   protected:
1370    
# Line 1018  class Data { Line 1423  class Data {
1423    
1424    /**    /**
1425       \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  
1426       Convert the data type of the RHS to match this.       Convert the data type of the RHS to match this.
1427       \param right - Input - data type to match.       \param right - Input - data type to match.
1428    */    */
# Line 1047  class Data { Line 1441  class Data {
1441       \brief       \brief
1442       Construct a Data object of the appropriate type.       Construct a Data object of the appropriate type.
1443    */    */
1444    template <class IValueType>  
1445    void    void
1446    initialise(const IValueType& value,    initialise(const DataTypes::ValueType& value,
1447             const DataTypes::ShapeType& shape,
1448               const FunctionSpace& what,               const FunctionSpace& what,
1449               bool expanded);               bool expanded);
1450    
   /**  
      \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.  
   */  
1451    void    void
1452    reshapeDataPoint(const DataArrayView::ShapeType& shape);    initialise(const boost::python::numeric::array& value,
1453                     const FunctionSpace& what,
1454                     bool expanded);
1455    
1456    //    //
1457    // pointer to the actual data object    // flag to protect the data object against any update
1458    boost::shared_ptr<DataAbstract> m_data;    bool m_protected;
1459    
1460    //    //
1461    // pointer to the internal profiling data    // pointer to the actual data object
1462    struct profDataEntry *profData;    boost::shared_ptr<DataAbstract> m_data;
1463    
1464  };  };
1465    
1466  template <class IValueType>  
1467  void  
1468  Data::initialise(const IValueType& value,  /**
1469                   const FunctionSpace& what,     Modify a filename for MPI parallel output to multiple files
1470                   bool expanded)  */
1471  {  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;  
   }  
 }  
1472    
1473  /**  /**
1474     Binary Data object operators.     Binary Data object operators.
1475  */  */
1476    inline double rpow(double x,double y)
1477    {
1478        return pow(y,x);
1479    }
1480    
1481  /**  /**
1482    \brief    \brief
1483    Operator+    Operator+
1484    Takes two Data objects.    Takes two Data objects.
1485  */  */
1486  Data operator+(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1487    
1488  /**  /**
1489    \brief    \brief
1490    Operator-    Operator-
1491    Takes two Data objects.    Takes two Data objects.
1492  */  */
1493  Data operator-(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1494    
1495  /**  /**
1496    \brief    \brief
1497    Operator*    Operator*
1498    Takes two Data objects.    Takes two Data objects.
1499  */  */
1500  Data operator*(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1501    
1502  /**  /**
1503    \brief    \brief
1504    Operator/    Operator/
1505    Takes two Data objects.    Takes two Data objects.
1506  */  */
1507  Data operator/(const Data& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1508    
1509  /**  /**
1510    \brief    \brief
# Line 1133  Data operator/(const Data& left, const D Line 1512  Data operator/(const Data& left, const D
1512    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1513    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1514  */  */
1515  Data operator+(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator+(const Data& left, const boost::python::object& right);
1516    
1517  /**  /**
1518    \brief    \brief
# Line 1141  Data operator+(const Data& left, const b Line 1520  Data operator+(const Data& left, const b
1520    Takes LHS Data object and RHS python::object.    Takes LHS Data object and RHS python::object.
1521    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1522  */  */
1523  Data operator-(const Data& left, const boost::python::object& right);  ESCRIPT_DLL_API Data operator-(const Data& left, const boost::python::object& right);
1524    
1525  /**  /**
1526    \brief    \brief
# Line 1149  Data operator-(const Data& left, const b Line 1528  Data operator-(const Data& left, const b
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 1157  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 1165  Data operator/(const Data& left, const b Line 1544  Data operator/(const Data& left, const b
1544    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1545    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1546  */  */
1547  Data operator+(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator+(const boost::python::object& left, const Data& right);
1548    
1549  /**  /**
1550    \brief    \brief
# Line 1173  Data operator+(const boost::python::obje Line 1552  Data operator+(const boost::python::obje
1552    Takes LHS python::object and RHS Data object.    Takes LHS python::object and RHS Data object.
1553    python::object must be convertable to Data type.    python::object must be convertable to Data type.
1554  */  */
1555  Data operator-(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator-(const boost::python::object& left, const Data& right);
1556    
1557  /**  /**
1558    \brief    \brief
# Line 1181  Data operator-(const boost::python::obje Line 1560  Data operator-(const boost::python::obje
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 1189  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    
1575  /**  /**
1576    \brief    \brief
1577    Output operator    Output operator
1578  */  */
1579  std::ostream& operator<<(std::ostream& o, const Data& data);  ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1580    
1581  /**  /**
1582    \brief    \brief
1583    Return true if operands are equivalent, else return false.    Compute a tensor product of two Data objects
1584    NB: this operator does very little at this point, and isn't to    \param arg0 - Input - Data object
1585    be relied on. Requires further implementation.    \param arg1 - Input - Data object
1586      \param axis_offset - Input - axis offset
1587      \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1588  */  */
1589  //bool operator==(const Data& left, const Data& right);  ESCRIPT_DLL_API
1590    Data
1591    C_GeneralTensorProduct(Data& arg0,
1592                         Data& arg1,
1593                         int axis_offset=0,
1594                         int transpose=0);
1595    
1596    
1597    
1598    // /**
1599    /*  \brief
1600      Return true if operands are equivalent, else return false.
1601      NB: this operator does very little at this point, and isn't to
1602      be relied on. Requires further implementation.*/
1603    //*/
1604    // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1605    
1606  /**  /**
1607    \brief    \brief
# Line 1218  Data::binaryOp(const Data& right, Line 1616  Data::binaryOp(const Data& right,
1616  {  {
1617     //     //
1618     // 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
1619     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1620       reshapeDataPoint(right.getPointDataView().getShape());       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1621     }     }
1622     //     //
1623     // initially make the temporary a shallow copy     // initially make the temporary a shallow copy
# Line 1227  Data::binaryOp(const Data& right, Line 1625  Data::binaryOp(const Data& right,
1625     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1626       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1627         //         //
1628         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1629         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1630       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1631         //         //
# Line 1275  Data::binaryOp(const Data& right, Line 1673  Data::binaryOp(const Data& right,
1673    
1674  /**  /**
1675    \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  
1676    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.
1677    Given operation combines each element of each data point, thus argument    Given operation combines each element of each data point, thus argument
1678    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 1383  Data::algorithm(BinaryFunction operation Line 1695  Data::algorithm(BinaryFunction operation
1695      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1696      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1697      return escript::algorithm(*leftC,operation,initial_value);      return escript::algorithm(*leftC,operation,initial_value);
1698      } else if (isEmpty()) {
1699        throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1700    }    }
1701    return 0;    return 0;
1702  }  }
# Line 1391  Data::algorithm(BinaryFunction operation Line 1705  Data::algorithm(BinaryFunction operation
1705    \brief    \brief
1706    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.
1707    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1708    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
1709    rank 0 Data object.    rank 0 Data object.
1710    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1711  */  */
# Line 1400  inline Line 1714  inline
1714  Data  Data
1715  Data::dp_algorithm(BinaryFunction operation, double initial_value) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1716  {  {
1717    Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());    if (isEmpty()) {
1718    if (isExpanded()) {      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1719      }
1720      else if (isExpanded()) {
1721        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1722      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1723      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1724      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1725      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1726      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1727    } else if (isTagged()) {      return result;
1728      }
1729      else if (isTagged()) {
1730      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
     DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());  
1731      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1732      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      DataTypes::ValueType defval(1);
1733        defval[0]=0;
1734        DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1735      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1736    } else if (isConstant()) {      return Data(resultT);   // note: the Data object now owns the resultT pointer
1737      }
1738      else if (isConstant()) {
1739        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1740      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1741      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1742      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1743      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");      EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1744      escript::dp_algorithm(*dataC,*resultC,operation,initial_value);      escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1745        return result;
1746      }
1747      Data falseRetVal; // to keep compiler quiet
1748      return falseRetVal;
1749    }
1750    
1751    /**
1752      \brief
1753      Compute a tensor operation with two Data objects
1754      \param arg0 - Input - Data object
1755      \param arg1 - Input - Data object
1756      \param operation - Input - Binary op functor
1757    */
1758    template <typename BinaryFunction>
1759    inline
1760    Data
1761    C_TensorBinaryOperation(Data const &arg_0,
1762                            Data const &arg_1,
1763                            BinaryFunction operation)
1764    {
1765      if (arg_0.isEmpty() || arg_1.isEmpty())
1766      {
1767         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1768      }
1769      // Interpolate if necessary and find an appropriate function space
1770      Data arg_0_Z, arg_1_Z;
1771    std::cerr << "C_TensorBinaryOperation fs1=" << &(arg_0.getFunctionSpace()) << " fs2=" << &(arg_1.getFunctionSpace())
1772    << std::endl;
1773      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1774        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1775          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1776          arg_1_Z = Data(arg_1);
1777        }
1778        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1779          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1780          arg_0_Z =Data(arg_0);
1781        }
1782        else {
1783          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1784        }
1785      } else {
1786          arg_0_Z = Data(arg_0);
1787          arg_1_Z = Data(arg_1);
1788      }
1789      // Get rank and shape of inputs
1790      int rank0 = arg_0_Z.getDataPointRank();
1791      int rank1 = arg_1_Z.getDataPointRank();
1792      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1793      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1794      int size0 = arg_0_Z.getDataPointSize();
1795      int size1 = arg_1_Z.getDataPointSize();
1796    
1797      // Declare output Data object
1798      Data res;
1799    
1800      if (shape0 == shape1) {
1801    
1802        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1803          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1804    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1805          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1806          double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1807          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1808          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1809          double *ptr_2 = &(res.getDataAtOffset(0));
1810    
1811          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1812        }
1813        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1814    
1815          // Prepare the DataConstant input
1816          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1817    
1818          // Borrow DataTagged input from Data object
1819          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1820    
1821          // Prepare a DataTagged output 2
1822          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1823          res.tag();
1824          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1825    
1826          // Prepare offset into DataConstant
1827          int offset_0 = tmp_0->getPointOffset(0,0);
1828          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1829          // Get the views
1830    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1831    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1832    //       // Get the pointers to the actual data
1833    //       double *ptr_1 = &((view_1.getData())[0]);
1834    //       double *ptr_2 = &((view_2.getData())[0]);
1835    
1836          // Get the pointers to the actual data
1837          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1838          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1839    
1840          // Compute a result for the default
1841          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1842          // Compute a result for each tag
1843          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1844          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1845          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1846            tmp_2->addTag(i->first);
1847    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1848            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1849            double *ptr_1 = &view_1.getData(0);
1850            double *ptr_2 = &view_2.getData(0);*/
1851            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1852            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1853    
1854            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1855          }
1856    
1857        }
1858        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1859    
1860          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1861          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1862          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1863          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1864    
1865          int sampleNo_1,dataPointNo_1;
1866          int numSamples_1 = arg_1_Z.getNumSamples();
1867          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1868          int offset_0 = tmp_0->getPointOffset(0,0);
1869          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1870          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1871            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1872              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1873              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1874    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1875    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1876    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1877    
1878              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1879              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1880              double *ptr_2 = &(res.getDataAtOffset(offset_2));
1881              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1882            }
1883          }
1884    
1885        }
1886        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1887    
1888          // Borrow DataTagged input from Data object
1889          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1890    
1891          // Prepare the DataConstant input
1892          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1893    
1894          // Prepare a DataTagged output 2
1895          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1896          res.tag();
1897          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1898    
1899          // Prepare offset into DataConstant
1900          int offset_1 = tmp_1->getPointOffset(0,0);
1901    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1902          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1903          // Get the views
1904    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1905    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1906    //       // Get the pointers to the actual data
1907    //       double *ptr_0 = &((view_0.getData())[0]);
1908    //       double *ptr_2 = &((view_2.getData())[0]);
1909          // Get the pointers to the actual data
1910          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1911          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1912          // Compute a result for the default
1913          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1914          // Compute a result for each tag
1915          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1916          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1917          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1918            tmp_2->addTag(i->first);
1919    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1920    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1921    //         double *ptr_0 = &view_0.getData(0);
1922    //         double *ptr_2 = &view_2.getData(0);
1923            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1924            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1925            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1926          }
1927    
1928        }
1929        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1930    
1931          // Borrow DataTagged input from Data object
1932          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1933    
1934          // Borrow DataTagged input from Data object
1935          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1936    
1937          // Prepare a DataTagged output 2
1938          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1939          res.tag();        // DataTagged output
1940          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1941    
1942    //       // Get the views
1943    //       DataArrayView view_0 = tmp_0->getDefaultValue();
1944    //       DataArrayView view_1 = tmp_1->getDefaultValue();
1945    //       DataArrayView view_2 = tmp_2->getDefaultValue();
1946    //       // Get the pointers to the actual data
1947    //       double *ptr_0 = &((view_0.getData())[0]);
1948    //       double *ptr_1 = &((view_1.getData())[0]);
1949    //       double *ptr_2 = &((view_2.getData())[0]);
1950    
1951          // Get the pointers to the actual data
1952          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1953          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1954          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1955    
1956          // Compute a result for the default
1957          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1958          // Merge the tags
1959          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1960          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1961          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1962          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1963            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
1964          }
1965          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1966            tmp_2->addTag(i->first);
1967          }
1968          // Compute a result for each tag
1969          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1970          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1971    
1972    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1973    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1974    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1975    //         double *ptr_0 = &view_0.getData(0);
1976    //         double *ptr_1 = &view_1.getData(0);
1977    //         double *ptr_2 = &view_2.getData(0);
1978    
1979            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1980            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1981            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1982    
1983            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1984          }
1985    
1986        }
1987        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
1988    
1989          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1990          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1991          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1992          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1993          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1994    
1995          int sampleNo_0,dataPointNo_0;
1996          int numSamples_0 = arg_0_Z.getNumSamples();
1997          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1998          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1999          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2000            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2001            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2002            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2003              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2004              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2005    
2006    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2007    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2008              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2009              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2010    
2011    
2012              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2013            }
2014          }
2015    
2016        }
2017        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2018    
2019          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2020          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2021          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2022          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2023    
2024          int sampleNo_0,dataPointNo_0;
2025          int numSamples_0 = arg_0_Z.getNumSamples();
2026          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2027          int offset_1 = tmp_1->getPointOffset(0,0);
2028          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2029          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2030            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2031              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2032              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2033    
2034    //           double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2035    //           double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2036    //           double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2037    
2038              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2039              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2040              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2041    
2042    
2043              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2044            }
2045          }
2046    
2047        }
2048        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2049    
2050          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2051          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2052          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2053          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2054          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2055    
2056          int sampleNo_0,dataPointNo_0;
2057          int numSamples_0 = arg_0_Z.getNumSamples();
2058          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2059          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2060          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2061            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2062            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2063            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2064              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2065              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2066              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2067              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2068              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2069            }
2070          }
2071    
2072        }
2073        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2074    
2075          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2076          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2077          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2078          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2079          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2080    
2081          int sampleNo_0,dataPointNo_0;
2082          int numSamples_0 = arg_0_Z.getNumSamples();
2083          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2084          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2085          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2086            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2087              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2088              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2089              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2090              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2091              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2092              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2093              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2094            }
2095          }
2096    
2097        }
2098        else {
2099          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2100        }
2101    
2102      } else if (0 == rank0) {
2103    
2104        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2105          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2106          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2107          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2108          double *ptr_2 = &(res.getDataAtOffset(0));
2109          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2110        }
2111        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2112    
2113          // Prepare the DataConstant input
2114          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2115    
2116          // Borrow DataTagged input from Data object
2117          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2118    
2119          // Prepare a DataTagged output 2
2120          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2121          res.tag();
2122          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2123    
2124          // Prepare offset into DataConstant
2125          int offset_0 = tmp_0->getPointOffset(0,0);
2126          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2127          // Get the views
2128    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2129    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2130    //       // Get the pointers to the actual data
2131    //       double *ptr_1 = &((view_1.getData())[0]);
2132    //       double *ptr_2 = &((view_2.getData())[0]);
2133           double *ptr_1 = &(tmp_1->getDefaultValue(0));
2134           double *ptr_2 = &(tmp_2->getDefaultValue(0));
2135    
2136          // Compute a result for the default
2137          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2138          // Compute a result for each tag
2139          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2140          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2141          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2142            tmp_2->addTag(i->first);
2143    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2144    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2145    //         double *ptr_1 = &view_1.getData(0);
2146    //         double *ptr_2 = &view_2.getData(0);
2147            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2148            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2149            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2150          }
2151    
2152        }
2153        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2154    
2155          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2156          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2157          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2158          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2159    
2160          int sampleNo_1,dataPointNo_1;
2161          int numSamples_1 = arg_1_Z.getNumSamples();
2162          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2163          int offset_0 = tmp_0->getPointOffset(0,0);
2164          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2165          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2166            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2167              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2168              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2169              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2170              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2171              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2172              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2173    
2174            }
2175          }
2176    
2177        }
2178        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2179    
2180          // Borrow DataTagged input from Data object
2181          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2182    
2183          // Prepare the DataConstant input
2184          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2185    
2186          // Prepare a DataTagged output 2
2187          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2188          res.tag();
2189          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2190    
2191          // Prepare offset into DataConstant
2192          int offset_1 = tmp_1->getPointOffset(0,0);
2193    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2194          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2195          // Get the views
2196    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2197          DataArrayView view_2 = tmp_2->getDefaultValue();
2198          // Get the pointers to the actual data
2199          double *ptr_0 = &((view_0.getData())[0]);
2200          double *ptr_2 = &((view_2.getData())[0]);*/
2201    
2202          // Get the pointers to the actual data
2203          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2204          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2205    
2206    
2207          // Compute a result for the default
2208          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2209          // Compute a result for each tag
2210          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2211          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2212          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2213            tmp_2->addTag(i->first);
2214    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2215            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2216            double *ptr_0 = &view_0.getData(0);
2217            double *ptr_2 = &view_2.getData(0);*/
2218            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2219            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2220    
2221            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2222          }
2223    
2224        }
2225        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2226    
2227          // Borrow DataTagged input from Data object
2228          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2229    
2230          // Borrow DataTagged input from Data object
2231          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2232    
2233          // Prepare a DataTagged output 2
2234          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2235          res.tag();        // DataTagged output
2236          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2237    
2238          // Get the views
2239    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2240          DataArrayView view_1 = tmp_1->getDefaultValue();
2241          DataArrayView view_2 = tmp_2->getDefaultValue();
2242          // Get the pointers to the actual data
2243          double *ptr_0 = &((view_0.getData())[0]);
2244          double *ptr_1 = &((view_1.getData())[0]);
2245          double *ptr_2 = &((view_2.getData())[0]);*/
2246    
2247          // Get the pointers to the actual data
2248          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2249          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2250          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2251    
2252    
2253          // Compute a result for the default
2254          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2255          // Merge the tags
2256          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2257          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2258          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2259          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2260            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2261          }
2262          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2263            tmp_2->addTag(i->first);
2264          }
2265          // Compute a result for each tag
2266          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2267          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2268    
2269    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2270            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2271            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2272            double *ptr_0 = &view_0.getData(0);
2273            double *ptr_1 = &view_1.getData(0);
2274            double *ptr_2 = &view_2.getData(0);*/
2275    
2276            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2277            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2278            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2279    
2280            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2281          }
2282    
2283        }
2284        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2285    
2286          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2287          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2288          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2289          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2290          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2291    
2292          int sampleNo_0,dataPointNo_0;
2293          int numSamples_0 = arg_0_Z.getNumSamples();
2294          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2295          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2296          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2297            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2298            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2299            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2300              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2301              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2302              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2303              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2304              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2305            }
2306          }
2307    
2308        }
2309        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2310    
2311          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2312          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2313          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2314          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2315    
2316          int sampleNo_0,dataPointNo_0;
2317          int numSamples_0 = arg_0_Z.getNumSamples();
2318          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2319          int offset_1 = tmp_1->getPointOffset(0,0);
2320          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2321          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2322            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2323              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2324              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2325              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2326              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2327              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2328              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2329            }
2330          }
2331    
2332    
2333        }
2334        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2335    
2336          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2337          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2338          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2339          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2340          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2341    
2342          int sampleNo_0,dataPointNo_0;
2343          int numSamples_0 = arg_0_Z.getNumSamples();
2344          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2345          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2346          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2347            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2348            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2349            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2350              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2351              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2352              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2353              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2354              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2355            }
2356          }
2357    
2358        }
2359        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2360    
2361          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2362          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2363          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2364          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2365          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2366    
2367          int sampleNo_0,dataPointNo_0;
2368          int numSamples_0 = arg_0_Z.getNumSamples();
2369          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2370          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2371          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2372            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2373              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2374              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2375              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2376              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2377              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2378              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2379              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2380            }
2381          }
2382    
2383        }
2384        else {
2385          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2386        }
2387    
2388      } else if (0 == rank1) {
2389    
2390        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2391          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2392          double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2393          double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2394          double *ptr_2 = &(res.getDataAtOffset(0));
2395          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2396        }
2397        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2398    
2399          // Prepare the DataConstant input
2400          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2401    
2402          // Borrow DataTagged input from Data object
2403          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2404    
2405          // Prepare a DataTagged output 2
2406          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2407          res.tag();
2408          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2409    
2410          // Prepare offset into DataConstant
2411          int offset_0 = tmp_0->getPointOffset(0,0);
2412          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2413          // Get the views
2414    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2415          DataArrayView view_2 = tmp_2->getDefaultValue();
2416          // Get the pointers to the actual data
2417          double *ptr_1 = &((view_1.getData())[0]);
2418          double *ptr_2 = &((view_2.getData())[0]);*/
2419          //Get the pointers to the actual data
2420          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2421          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2422    
2423          // Compute a result for the default
2424          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2425          // Compute a result for each tag
2426          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2427          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2428          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2429            tmp_2->addTag(i->first);
2430    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2431    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2432    //         double *ptr_1 = &view_1.getData(0);
2433    //         double *ptr_2 = &view_2.getData(0);
2434            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2435            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2436    
2437    
2438            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2439          }
2440    
2441        }
2442        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2443    
2444          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2445          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2446          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2447          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2448    
2449          int sampleNo_1,dataPointNo_1;
2450          int numSamples_1 = arg_1_Z.getNumSamples();
2451          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2452          int offset_0 = tmp_0->getPointOffset(0,0);
2453          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2454          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2455            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2456              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2457              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2458              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2459              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2460              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2461              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2462            }
2463          }
2464    
2465        }
2466        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2467    
2468          // Borrow DataTagged input from Data object
2469          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2470    
2471          // Prepare the DataConstant input
2472          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2473    
2474          // Prepare a DataTagged output 2
2475          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2476          res.tag();
2477          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2478    
2479          // Prepare offset into DataConstant
2480          int offset_1 = tmp_1->getPointOffset(0,0);
2481          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2482          // Get the views
2483    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2484    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2485    //       // Get the pointers to the actual data
2486    //       double *ptr_0 = &((view_0.getData())[0]);
2487    //       double *ptr_2 = &((view_2.getData())[0]);
2488          // Get the pointers to the actual data
2489          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2490          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2491          // Compute a result for the default
2492          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2493          // Compute a result for each tag
2494          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2495          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2496          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2497            tmp_2->addTag(i->first);
2498    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2499            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2500            double *ptr_0 = &view_0.getData(0);
2501            double *ptr_2 = &view_2.getData(0);*/
2502            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2503            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2504            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2505          }
2506    
2507        }
2508        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2509    
2510          // Borrow DataTagged input from Data object
2511          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2512    
2513          // Borrow DataTagged input from Data object
2514          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2515    
2516          // Prepare a DataTagged output 2
2517          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2518          res.tag();        // DataTagged output
2519          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2520    
2521          // Get the views
2522    //       DataArrayView view_0 = tmp_0->getDefaultValue();
2523    //       DataArrayView view_1 = tmp_1->getDefaultValue();
2524    //       DataArrayView view_2 = tmp_2->getDefaultValue();
2525    //       // Get the pointers to the actual data
2526    //       double *ptr_0 = &((view_0.getData())[0]);
2527    //       double *ptr_1 = &((view_1.getData())[0]);
2528    //       double *ptr_2 = &((view_2.getData())[0]);
2529    
2530          // Get the pointers to the actual data
2531          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2532          double *ptr_1 = &(tmp_1->getDefaultValue(0));
2533          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2534    
2535          // Compute a result for the default
2536          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2537          // Merge the tags
2538          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2539          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2540          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2541          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2542            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2543          }
2544          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2545            tmp_2->addTag(i->first);
2546          }
2547          // Compute a result for each tag
2548          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2549          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2550    //         DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2551    //         DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2552    //         DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2553    //         double *ptr_0 = &view_0.getData(0);
2554    //         double *ptr_1 = &view_1.getData(0);
2555    //         double *ptr_2 = &view_2.getData(0);
2556    
2557            double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2558            double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2559            double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2560            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2561          }
2562    
2563        }
2564        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2565    
2566          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2567          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2568          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2569          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2570          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2571    
2572          int sampleNo_0,dataPointNo_0;
2573          int numSamples_0 = arg_0_Z.getNumSamples();
2574          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2575          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2576          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2577            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2578            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2579            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2580              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2581              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2582              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2583              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2584              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2585            }
2586          }
2587    
2588        }
2589        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2590    
2591          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2592          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2593          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2594          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2595    
2596          int sampleNo_0,dataPointNo_0;
2597          int numSamples_0 = arg_0_Z.getNumSamples();
2598          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2599          int offset_1 = tmp_1->getPointOffset(0,0);
2600          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2601          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2602            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2603              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2604              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2605              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2606              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2607              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2608              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2609            }
2610          }
2611    
2612    
2613        }
2614        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2615    
2616          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2617          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2618          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2619          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2620          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2621    
2622          int sampleNo_0,dataPointNo_0;
2623          int numSamples_0 = arg_0_Z.getNumSamples();
2624          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2625          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2626          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2627            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2628            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2629            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2630              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2631              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2632              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2633              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2634              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2635            }
2636          }
2637    
2638        }
2639        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2640    
2641          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2642          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2643          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2644          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2645          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2646    
2647          int sampleNo_0,dataPointNo_0;
2648          int numSamples_0 = arg_0_Z.getNumSamples();
2649          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2650          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2651          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2652            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2653              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2654              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2655              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2656              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2657              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2658              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2659              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2660            }
2661          }
2662    
2663        }
2664        else {
2665          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2666        }
2667    
2668      } else {
2669        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2670      }
2671    
2672      return res;
2673    }
2674    
2675    template <typename UnaryFunction>
2676    Data
2677    C_TensorUnaryOperation(Data const &arg_0,
2678                           UnaryFunction operation)
2679    {
2680      if (arg_0.isEmpty())  // do this before we attempt to interpolate
2681      {
2682         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2683    }    }
2684    return result;  
2685      // Interpolate if necessary and find an appropriate function space
2686      Data arg_0_Z = Data(arg_0);
2687    
2688      // Get rank and shape of inputs
2689      int rank0 = arg_0_Z.getDataPointRank();
2690      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2691      int size0 = arg_0_Z.getDataPointSize();
2692    
2693      // Declare output Data object
2694      Data res;
2695    
2696      if (arg_0_Z.isConstant()) {
2697        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2698    //     double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2699    //     double *ptr_2 = &((res.getPointDataView().getData())[0]);
2700        double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2701        double *ptr_2 = &(res.getDataAtOffset(0));
2702        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2703      }
2704      else if (arg_0_Z.isTagged()) {
2705    
2706        // Borrow DataTagged input from Data object
2707        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2708    
2709        // Prepare a DataTagged output 2
2710        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2711        res.tag();
2712        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2713    
2714    //     // Get the views
2715    //     DataArrayView view_0 = tmp_0->getDefaultValue();
2716    //     DataArrayView view_2 = tmp_2->getDefaultValue();
2717    //     // Get the pointers to the actual data
2718    //     double *ptr_0 = &((view_0.getData())[0]);
2719    //     double *ptr_2 = &((view_2.getData())[0]);
2720        // Get the pointers to the actual data
2721        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2722        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2723        // Compute a result for the default
2724        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2725        // Compute a result for each tag
2726        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2727        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2728        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2729          tmp_2->addTag(i->first);
2730    //       DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2731    //       DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2732    //       double *ptr_0 = &view_0.getData(0);
2733    //       double *ptr_2 = &view_2.getData(0);
2734          double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2735          double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2736          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2737        }
2738    
2739      }
2740      else if (arg_0_Z.isExpanded()) {
2741    
2742        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2743        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2744        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2745    
2746        int sampleNo_0,dataPointNo_0;
2747        int numSamples_0 = arg_0_Z.getNumSamples();
2748        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2749        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2750        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2751          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2752    //         int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2753    //         int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2754    //         double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2755    //         double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2756            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2757            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2758            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2759            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2760            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2761          }
2762        }
2763      }
2764      else {
2765        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2766      }
2767    
2768      return res;
2769  }  }
2770    
2771  }  }

Legend:
Removed from v.147  
changed lines
  Added in v.1820

  ViewVC Help
Powered by ViewVC 1.1.26