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

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26