Proto  3.2
Proto_BoxData.H
Go to the documentation of this file.
1 #pragma once
2 #ifndef _PROTO_RECTMDARRAY_H_
3 #define _PROTO_RECTMDARRAY_H_
4 
5 #include <memory> //for shared_ptr
6 #include <iostream>
7 #include <fstream> // for parallel pretty printing
8 #include <iomanip> // for pretty printing
9 #include <limits> // for max / min functions
10 #include <cstdlib> // for size_t
11 #include <cmath> // floating point abs, isnan
12 #include <map>
13 #include <random> // random initialization
14 #include <unordered_map>
15 #include <type_traits> // used in containsNAN
16 
17 #include "Proto_Timer.H"
18 
19 #include "Proto_Accel.H"
20 #include "Proto_MemType.H"
21 #include "Proto_Memory.H"
22 #include "Proto_Stack.H"
23 #include "Proto_Array.H"
24 #include "Proto_Box.H"
25 #include "Proto_CoordPermutation.H"
26 #include "Proto_Stencil.H"
27 #include "Proto_CInterval.H"
28 #include "Proto_Reduction.H"
29 
30 #include "Proto_DisjointBoxLayout.H" //this shouldn't be here
31 
32 // This is to facilitate automated testing.
33 #ifdef PROTO_MEM_CHECK
34 struct BoxDataMemCheck
35 {
36  static BoxDataMemCheck& instance()
37  {
38  static BoxDataMemCheck inst;
39  return inst;
40  }
41 
42  BoxDataMemCheck()
43  {
44  m_numCopies = 0;
45  m_numSlowCopies = 0;
46  m_numFastCopies = 0;
47  m_numMoveAssign = 0;
48  }
49 
50  inline static int& numCopies() { return instance().m_numCopies; }
51  inline static int& numFastCopies() { return instance().m_numFastCopies; }
52  inline static int& numSlowCopies() { return instance().m_numSlowCopies; }
53  inline static int& numMoveAssign() { return instance().m_numMoveAssign; }
54 
55  inline static void clear()
56  {
57  numCopies() = 0;
58  numFastCopies() = 0;
59  numSlowCopies() = 0;
60  numMoveAssign() = 0;
61  }
62 
63  private:
64 
65  int m_numCopies;
66  int m_numSlowCopies;
67  int m_numFastCopies;
68  int m_numMoveAssign;
69 };
70 #endif
71 
72 using std::shared_ptr;
73 namespace Proto
74 {
75  // Forward Declarations
76  template<typename T> class Stencil;
77  template<typename T, unsigned int C, MemType MEM, unsigned int D, unsigned int E>
78  class LazyStencil;
79 
80  template<typename T, unsigned int C, MemType MEM, unsigned int D, unsigned int E>
82 
83  template<MemType MEM>
84  inline void null_deleter_boxdata(void* ptr) { }
85 
86  enum BoxDataOp
87  {
88  Invalid = -1,
89  Copy = 0,
90  Add = 1,
96  };
97 
98 /** @defgroup pointwise_operations Pointwise Operations*/
99 
100 /** @addtogroup pointwise_operations*/
101 /*@{*/
102 
103  /// Pointwise Variable
104  /**
105  Var is used for implementing pointwise operators on BoxDatas.
106  See the documentation for forall for more information.
107  Template parameters refer to the type and dimension of data held by the associated BoxData.
108  See BoxData documentation.
109 
110  \tparam T Type of data in array (bool, int, double, etc.)
111  \tparam C Number of components in first data index. Defaults to 1.
112  \tparam D Number of components in second data index. Defaults to 1.
113  \tparam E Number of components in third data index. Defaults to 1.
114  */
115  template<typename T, unsigned int C=1, MemType MEM=MEMTYPE_DEFAULT,
116  unsigned int D=1, unsigned int E=1>
117  class Var
118  {
119  public:
120 
121 
122 #ifdef PROTO_ACCEL
123  __device__
124  inline T& getValDevice(unsigned int a_c, unsigned int a_d = 0, unsigned int a_e = 0)
125  {
126  int idx = threadIdx.x + blockIdx.x*blockDim.x;
127  int idy = blockIdx.y;
128  #if DIM == 3
129  int idz = blockIdx.z;
130  return (m_ptrs[a_c + C*a_d + C*D*a_e])[idx + boxDimX * (idy + idz * boxDimY)];
131  #else
132  return (m_ptrs[a_c + C*a_d + C*D*a_e])[idx + idy * boxDimX];
133  #endif
134  }
135 
136  #ifdef PROTO_HIP
137  __host__
138  inline T& getValDevice(unsigned int a_c, unsigned int a_d = 0, unsigned int a_e = 0)
139  {
140  return *(m_ptrs[a_c + C*a_d + C*D*a_e]);
141  }
142  #endif
143 #else
144  inline T& getValDevice(unsigned int a_c, unsigned int a_d = 0, unsigned int a_e = 0)
145  {
146  return *(m_ptrs[a_c + C*a_d + C*D*a_e]);
147  }
148 #endif
149  /// Pointwise Accessor
150  /**
151  Access component (c,d,e) of the <code>BoxData<T,C,MEM,D,E></code>
152  associated with *this.
153 
154  \param a_c First component index
155  \param a_d Second component index (default: 0)
156  \param a_e Third component index (default: 0)
157  */
159  __attribute__((always_inline))
160  T& operator()(unsigned int a_c, unsigned int a_d = 0, unsigned int a_e = 0)
161  {
162  PROTO_ASSERT(a_c < C, "Var::operator() | Error: index out of bounds");
163  PROTO_ASSERT(a_d < D, "Var::operator() | Error: index out of bounds");
164  PROTO_ASSERT(a_e < E, "Var::operator() | Error: index out of bounds");
165 #ifdef PROTO_ACCEL
166  if(MEM==MemType::DEVICE)
167  return getValDevice(a_c,a_d,a_e);
168  else
169 #endif
170  return *(m_ptrs[a_c + C*a_d + C*D*a_e]);
171  }
172 
173  /// Pointwise Accessor (Const)
174  /**
175  Access component (c,d,e) of the <code>const BoxData<T,C,D,E></code>
176  associated with <code>*this</code>.
177 
178  \param a_c First component index
179  \param a_d Second component index (default: 0)
180  \param a_e Third component index (default: 0)
181  */
182 #ifdef PROTO_ACCEL
183  __device__
184  inline const T& getValDevice(
185  unsigned int a_c,
186  unsigned int a_d = 0,
187  unsigned int a_e = 0) const
188  {
189  int idx = threadIdx.x + blockIdx.x*blockDim.x;
190  int idy = blockIdx.y;
191 #if DIM == 3
192  int idz = blockIdx.z;
193  return (m_ptrs[a_c + C*a_d + C*D*a_e])[idx + boxDimX * (idy + idz * boxDimY)];
194 #else
195  return (m_ptrs[a_c + C*a_d + C*D*a_e])[idx + idy * boxDimX];
196 #endif
197  }
198 
199 #ifdef PROTO_HIP
200  __host__
201  inline const T& getValDevice(
202  unsigned int a_c,
203  unsigned int a_d = 0,
204  unsigned int a_e = 0) const
205  {
206  return *(m_ptrs[a_c + C*a_d + C*D*a_e]);
207  }
208 #endif
209 #else
210  inline const T& getValDevice(
211  unsigned int a_c,
212  unsigned int a_d = 0,
213  unsigned int a_e = 0) const
214  {
215  return *(m_ptrs[a_c + C*a_d + C*D*a_e]);
216  }
217 #endif
218 
220  __attribute__((always_inline))
221  const T& operator()(
222  unsigned int a_c,
223  unsigned int a_d = 0,
224  unsigned int a_e = 0) const
225  {
226 #ifdef PROTO_ACCEL
227  if(MEM==MemType::DEVICE)
228  return getValDevice(a_c,a_d,a_e);
229  else
230 #endif
231  return *(m_ptrs[a_c + C*a_d + C*D*a_e]);
232  }
233 
235  inline Var& operator+=(unsigned int& a_increment)
236  {
237  for (int ii = 0; ii < C*D*E; ii++)
238  {
239  m_ptrs[ii] += a_increment;
240  }
241  return *this;
242  }
243 
244  // test
246  inline Var& operator+=(Point& a_p)
247  {
248 #if DIM == 3
249  unsigned int shift = a_p[0] + (a_p[1] + a_p[2]*boxDimY)*boxDimX;
250 #else
251  unsigned int shift = a_p[0] + a_p[1]*boxDimX;
252 #endif
253  return *this+=shift;
254  }
255 
257  inline Var& operator+=(const Point& a_p)
258  {
259 #if DIM == 3
260  unsigned int shift = a_p[0] + (a_p[1] + a_p[2]*boxDimY)*boxDimX;
261 #else
262  unsigned int shift = a_p[0] + a_p[1]*boxDimX;
263 #endif
264  return *this+=shift;
265  }
266 
268  inline Var& operator++()
269  {
270  for (int ii = 0; ii < C*D*E; ii++)
271  {
272  ++m_ptrs[ii];
273  }
274  return *this;
275  }
276 
278  inline Var& operator--()
279  {
280  for (int ii = 0; ii < C*D*E; ii++)
281  {
282  --m_ptrs[ii];
283  }
284  return *this;
285  }
286 
287  unsigned int boxDimX;
288  unsigned int boxDimY;
289  unsigned int subBoxDimX;
290  unsigned int subBoxDimY;
291  T* m_ptrs[C*D*E];
292  }; // End Class Var
293 
294  ///////////////////////////////////////////////////////////////////////////////////////////////
295  /// Multidimensional Rectangular Array
296  /**
297  BoxData is the main dataholder class of Proto. It contains an
298  array of data of type T on a domain defined by a Box.
299  Each data point is associated with a Point in the Box.
300  C, D, and E define the tensor structure of the data:
301  C,D,E = 1: Data is scalar (default)
302  C = N, D,E = 1: Data is vector valued with N components
303  C = M, D = N, E = 1: Data is MxN matrix valued
304 
305  \tparam T Type of data in array (bool, int, double, etc.)
306  \tparam C (Optional) Size of first component axis. Defaults to 1.
307  \tparam D (Optional) Size of second component axis. Defaults to 1.
308  \tparam E (Optional) Size of third component axis. Defaults to 1.
309  \tparam MEM (Optional) Where memory is allocated (device or host). Defaults to host.
310  */
311  template <class T=double, unsigned int C=1,
313  unsigned int D=1, unsigned int E=1>
314  class BoxData
315  {
316  public:
317 
319 
320  /// Forbidden Functions
321  BoxData(const BoxData<T,C,MEM,D,E>& a_src) = delete;
322  BoxData& operator=(const BoxData<T,C,MEM,D,E>& a_src) = delete;
323 
324 
325  //////////////////////////////////////////////////////////////////////////////////////
326  /** @name Constructors and Define*/
327  ///@{
328 
329 
330  /// Default Constructor
331  /**
332  Creates an empty BoxData with an empty Box.
333  <code>BoxData::define</code> must be called to allocate memory.
334  */
335  BoxData();
336 
337  /// Box Constructor
338  /**
339  Creates and allocates an uninitialized array according to the space
340  needed by <code>a_box</code> and the number of components.
341 
342  \param a_box Box defining the domain of *this
343  */
344  explicit BoxData(const Box& a_box);
345 
346  /// Box Constructor With Initialization
347  /**
348  Creates, allocates, and initializes a BoxData using a constant value.
349  The Stack is automatically used if it is active when this function is called.
350 
351  \param a_box Box defining the domain of *this
352  \param a_init T value used to initialize all data values
353  */
354  BoxData(const Box& a_box, T a_init);
355 
356  /// Move constructor
357  /**
358  Necessary in cases where we return BoxData by value, but don't want an actual deep copy
359  The Stack is automatically used if it is active when this function is called.
360 
361  \param a_src Source data
362  */
363  BoxData(BoxData<T,C,MEM,D,E>&& a_src);
364 
365  /// Box Define
366  /**
367  Allocates or reallocates memory for a previously declared BoxData.
368  The Stack is automatically used if it is active when this function is called.
369 
370  \param a_box Box defining the domain of *this
371  */
372  void define(const Box& a_box);
373 
374 
375  /// Alias Define
376  /**@private */
377  template<unsigned int ncomp>
378  void define(BoxData<T,ncomp,MEM,1,1>& a_input,
379  unsigned int& a_comp);
380 
381  /// Raw Pointer Alias Constructor
382  /**
383  Builds a vector valued BoxData by aliasing a raw pointer to T which should be of size
384  <code> a_box.size()*a_ncomp </code>. The data in <code> a_ptr </code> is not copied.
385  This constructor is not recommended for public use, but is provided to facilitate
386  compatability with third party libraries.
387 
388  \param a_ptr MEM Source buffer of type T to which *this will be aliased.
389  \param a_box Box defining the domain of *this
390  \param a_ncomp Dummy input for the number of components. Completely unused.
391  */
392  BoxData(const T* a_ptr, const Box& a_box, int a_ncomp = C);
393 
394  /// Raw Pointer Alias Define
395  /**
396  Defines a vector valued BoxData by aliasing a raw pointer to T which should be of size
397  <code> a_box.size()*a_ncomp </code>. The data in <code> a_ptr </code> is not copied.
398  This constructor is not recommended for public use, but is provided to facilitate
399  compatability with third party libraries.
400 
401  \param a_ptr MEM Source buffer of type T to which *this will be aliased.
402  \param a_box Box defining the domain of *this
403  \param a_ncomp Dummy input for the number of components. Completely unused.
404  */
405  void define(const T* a_ptr, const Box& a_box, int a_ncomp = C);
406 
407 
408  /// LazyStencil Constructor
409  /**
410  @private
411  Builds a BoxData from a lazily evaluated Stencil operation. Called implicitly.
412  Allows for the syntax:
413 
414  @code
415  Box domain = Box::Cube(64);
416  BoxData<double> ones(domain, 1);
417  Stencil<double> triple = 3*Shift::Zeros();
418  BoxData<double> threes = triple(ones);
419  //NB: Using "auto" here will result in an error:
420  auto threes = triple(ones); // runtime error
421  @endcode
422 
423  \param a_op The output of a Stencil or InterpStencil apply operation.
424  */
425  BoxData(LazyStencil<T,C,MEM,D,E>&& a_op);
427 
428  /// Slice Constructor
429  /**
430  @private
431  Used internally. Not part of the public interface.
432  */
433  BoxData(shared_ptr<T> a_data,const T* a_ptr,const Box& a_box);
434 
435  /// Destructor.
436  ~BoxData();
437 
438  ///@}
439 
440  ///////////////////////////////////////////////////////////////////////////////////////
441  /** @name Data Movement */
442  ///@{
443 
444  /// Move Assignment Operator
445  /**
446  Moves data in a_src to *this without performing a deep copy.
447 
448  \param a_src Source Data
449  */
450  BoxData& operator=(BoxData<T,C,MEM,D,E>&& a_src);
451 
452  /// Copy on Intersection.
453  /**
454  Copy data from <code> *this </code> to <code> a_dest </code>
455  within the domain intersection. Does nothing if the domain intersection is empty.
456  Note that <code>a_dest</code> must have the same MemType as *this.
457 
458  \param a_dest Destination data holder
459  */
460  template<MemType MEM_DEST>
461  void copyTo(BoxData<T,C,MEM_DEST,D,E>& a_dest) const;
462 
463  /// Copy Region
464  /**
465  Copy with a prescribed Box argument and optional shift.
466  Explicitly, this function copies the subset of data from <code> *this </code>
467  contained in <code> a_srcBox </code> into the region of <code> a_dest </code>
468  defined by <code> a_srcBox.shift(a_destShift) </code>.
469 
470  This function will fail if <code> a_srcBox </code> is not contained in both
471  <code> this->box() </code> and <code> a_dest.box().shift(a_destShift) </code>.
472 
473  Note that <code>a_dest</code> must have the same MemType as *this.
474 
475  \param a_dest Destination data holder
476  \param a_srcBox Region of data to copy from *this
477  \param a_destShift (Optional) Determines region of a_dest to copy data to.
478  */
479  template<MemType MEM_DEST>
480  void copyTo(
482  const Box& a_srcBox,
483  const Point& a_destShift = Point::Zeros()) const;
484 
485  ///Copy with src and dest boxes.
486  /**
487  Copies from a <code>a_srcBox</code> in <code>*this</code> into
488  a <code>a_destBox</code> in <code>a_dest</code>. Used in ::Proto::Copier.
489  Note that <code>a_dest</code> must have the same MemType as *this.
490  TODO: This needs debugging. It's unclear what this function is supposed to do.
491  */
492  template<MemType MEM_DEST>
493  void copyTo(BoxData<T,C,MEM_DEST,D,E>& a_dest,
494  const Box& a_srcBox,
495  const Box& a_destBox) const;
496 
497  /// General Copy
498  /**
499  The most general form of copyTo.
500  Copies a prescribed set of components from <code> *this </code>
501  into <code> a_dest </code> within prescribed region with a possible shift.
502  <code>a_srcComps </code> and <code> a_destComps </code> must have the same size.
503  The range of the copy in <code>a_dest</code> is
504  <code>a_srcBox.shift(a_destShift) & a_dest.box()</code>.
505  Note that <code>a_dest</code> must have the same MemType as *this.
506 
507  Example Usage:
508 
509  \param a_dest Destination data holder
510  \param a_srcBox Region of data to copy from *this
511  \param a_srcComps Components of *this to copy from
512  \param a_destShift Determines region of a_dest to copy data to
513  \param a_destComps Components of a_dest to copy into.
514  */
515  template <unsigned int Cdest, MemType MEM_DEST,
516  unsigned int Ddest, unsigned int Edest>
517  void copyTo(
519  const Box& a_srcBox,
520  CInterval a_srcComps,
521  const Point& a_destShift,
522  CInterval a_destComps) const;
523 
524  /// General Copy From
525  /**
526  Nearly identical to the most general version of <code> copyTo </code>
527  except the copy direction is reversed.
528  Only valid for vector or scalar valued BoxData.
529  This function is provided to facilitate interoperability with third party libraries,
530  and is not recommended for public use unless necessary.
531 
532  \param a_dsrc Source data
533  \param a_srcBox Source domain to copy from
534  \param a_srcComp First component to copy from source
535  \param a_destBox Destination domain to copy into
536  \param a_destComp First component to copy into destiation
537  \param a_numcomp Number of components to copy
538  */
539  template<unsigned int Csrc>
540  void copy(
541  const BoxData<T,Csrc,MEM,D,E>& a_dsrc,
542  const Box& a_srcBox,
543  unsigned int a_srcComp,
544  const Box& a_destBox,
545  unsigned int a_destComp,
546  unsigned int a_numcomp);
547 
548  /// Copy With Rotation
549  /**
550  * Copy between two BoxData with the same number of data points, but with
551  * permuted coordinates. This function is mostly used interally in Copiers.
552  *
553  * \param a_dst Destination data holder
554  * \param a_rotation Permutation from this to a_dst's coordinates
555  */
556  void copyTo(
558  const CoordPermutation& a_rotation) const;
559 
560  /// Create a new BoxData that is transposed relative to this
561  /** Very inefficient. Only use this if you have to.
562  */
563  BoxData<T,C,MEM,D,E> transpose(int c0, int c1) const;
564  /// Rotate Coordinates
565  /**
566  * Permute the coordinates of this BoxData in place
567  *
568  * \param a_box Rotated domain. Must have the same number of points as the current one
569  * \param a_rotation Permutation from current to desired coordinates
570  */
571  void rotate(
572  Box a_box,
573  const CoordPermutation& a_rotation);
574  ///@}
575 
576  ///////////////////////////////////////////////////////////////////////////////////////
577  /** @name Accessors */
578  ///@{
579 
580  /// Compute Index
581  /**
582  Computes the index in <code>[0,this->size())</code> associated with a given
583  Point and components
584 
585  \param a_pt A Point in the domain of <code> *this </code>
586  \param a_c (Optional) First tensor index. (defaults : 0)
587  \param a_d (Optional) Second tensor index. (defaults : 0)
588  \param a_e (Optional) Third tensor index. (defaults : 0)
589  */
591  inline size_t index(const Point a_pt,
592  unsigned int a_c = 0,
593  unsigned int a_d = 0,
594  unsigned int a_e = 0) const;
595 
596  //TODO: Why do we need so many accessors? Sury we can prune these down
597  //TODO: Documentation claims this is read only, but it returns a writeable value?
598  /// Point Accessor
599  /**
600  Read-only access to data stored in <code> *this </code>.
601  This function is read-only to facilitate cross-platform code (e.g. GPU compatability).
602  This function is for debugging ONLY, and will not work on the device.
603  Pointwise write operations should be done through forall.
604 
605  \param a_pt A Point in the domain of <code> *this </code>
606  \param a_c (Optional) First tensor index. (defaults : 0)
607  \param a_d (Optional) Second tensor index. (defaults : 0)
608  \param a_e (Optional) Third tensor index. (defaults : 0)
609  */
611  inline T& operator()(
612  const Point& a_pt,
613  unsigned int a_c = 0,
614  unsigned int a_d = 0,
615  unsigned int a_e = 0) const;
616 
617 
618  /// Array Accessor
619  /** Acquire the data in *this at a Point in the form of an Array. The output is a
620  * copy, not an alias and cannot be used to alter the content of *this
621  */
623  inline Array<T,C*D*E> array(const Point& a_pt) const;
624 
625 
626  /// Index Accessor (Const)
627  /**
628  Access *this using a linear index. Useful for interacting with
629  BoxData like a regular buffer, but not recommended.
630 
631  \param a_index Index in [0,this->size() = m_box.size()*C*D*E)
632  */
633  inline const T* operator[](unsigned int a_index) const;
634 
635  /// Index Accessor (Non-Const)
636  /**
637  Access *this using a linear index. Useful for interacting with
638  BoxData like a regular buffer, but not recommended.
639 
640  \param a_index Index in [0,this->size() = m_box.size()*C*D*E)
641  */
642  inline T* operator[](unsigned int a_index);
643 
644  /// Pointer Accessor (Const)
645  /**
646  Return a const pointer to a data point in <code> *this </code>
647  given a Point and tensor indices.
648 
649  \param a_p Point in the domain of this
650  \param a_c (Optional) First tensor index. (defaults : 0)
651  \param a_d (Optional) Second tensor index. (defaults : 0)
652  \param a_e (Optional) Third tensor index. (defaults : 0)
653  */
654  inline const T* data(
655  const Point& a_p,
656  unsigned int a_c = 0,
657  unsigned int a_d = 0,
658  unsigned int a_e = 0) const;
659 
660  /// Pointer Accessor (Non-Const)
661  /**
662  Return a pointer to a data point in <code> *this </code>
663  given a Point and tensor indices.
664 
665  \param a_p Point in the domain of this
666  \param a_c (Optional) First tensor index. (defaults : 0)
667  \param a_d (Optional) Second tensor index. (defaults : 0)
668  \param a_e (Optional) Third tensor index. (defaults : 0)
669  */
670  inline T* data(
671  const Point& a_p,
672  unsigned int a_c = 0,
673  unsigned int a_d = 0,
674  unsigned int a_e = 0);
675 
676  /// Buffer Accessor (Non-Const)
677  /**
678  Return the contiguous data buffer where the data in <code>*this</code> is stored,
679  starting at a specified component. Not recommended for public use.
680 
681  \param a_c (Optional) First tensor index. (defaults : 0)
682  \param a_d (Optional) Second tensor index. (defaults : 0)
683  \param a_e (Optional) Third tensor index. (defaults : 0)
684  */
685  inline T* data(
686  unsigned int a_c = 0,
687  unsigned int a_d = 0,
688  unsigned int a_e = 0);
689 
690  /// Buffer Accessor (Const)
691  /**
692  Return the contiguous data buffer where the data in <code>*this</code> is stored.
693  Not recommended for public use.
694  */
695  inline const T* data(
696  unsigned int a_c = 0,
697  unsigned int a_d = 0,
698  unsigned int a_e = 0) const;
699 
700  /// Shared Buffer Accessor
701  /**
702  Returns the shared_ptr object that is common to all aliases. If this not
703  an alias, this function is identical to data().
704  */
705  inline ::std::shared_ptr<T> aliasData() { return m_data; }
706 
707  /// Shared Buffer Accessor (Const)
708  /**
709  Returns the shared_ptr object that is common to all aliases. If this not
710  an alias, this function is identical to data().
711  */
712  inline ::std::shared_ptr<T> aliasData() const { return m_data; }
713 
714  // Get Domain Box
715  /**
716  Return's the domain Box of <code> *this </code>.
717  Includes ghost cells if it was built it that way.
718  */
719  inline Box box() const {return m_box;};
720 
721  // Get Size
722  /**
723  Returns the number of data points in <code> *this </code>.
724  Return value is equal to <code> m_box.size()*C*D*E </code>
725  */
726 
727  inline std::size_t size() const {return m_box.size()*C*D*E;};
728  inline std::size_t numValues() const { return m_box.size()*C*D*E; }
729  /// Defined Query
730  /**
731  Returns true if this is defined (e.g., it has memory allocated to it).
732  This will return false for default constructed objects and true otherwise
733  */
734  inline bool defined() const {return bool(m_data);};
735 
736  //TODO: should be private
737  /// Create Pointwise Access Variable (Non-Const)
738  /**
739  @private
740  */
741  inline Var<T,C,MEM,D,E> var(const Point& a_pt);
742 
743  //TODO: should be private
744  /// Create Pointwise Access Variable (Const)
745  /**
746  @private
747  */
748  inline Var<T,C,MEM,D,E> var(const Point& a_pt) const;
749 
750  ///@}
751 
752  ///////////////////////////////////////////////////////////////////////////////////////
753  /** @name Algebraic Operations */
754  ///@{
755 
756  /// Algebraic Op Helper
757  /** @private */
758  template<BoxDataOp>
759  inline void operatorT(const BoxData<T,C,MEM,D,E>& a_src);
760 
761  /// Algebraic Op Helper
762  /** @private */
763  template<BoxDataOp>
764  inline void operatorT(const T a_scale);
765 
766  /// Pointwise Addition on Intersection
767  /**
768  Output range is the intersection of the inputs.
769  Not recommended for performance unless necessary.
770  Try to fuse arithmetic operations into forall or Stencil operations if possible.
771 
772  \param a_rhs Another BoxData
773  */
774  inline BoxData<T,C,MEM,D,E> operator+(const BoxData<T,C,MEM,D,E>& a_rhs) const;
775 
776  /// Pointwise Subtraction on Intersection
777  /**
778  Output range is the intersection of the inputs.
779  Not recommended for performance unless necessary.
780  Try to fuse arithmetic operations into forall or Stencil operations if possible.
781 
782  \param a_rhs Another BoxData
783  */
784  inline BoxData<T,C,MEM,D,E> operator-(const BoxData<T,C,MEM,D,E>& a_rhs) const;
785 
786  /// Pointwise Multiplication on Intersection
787  /**
788  Output range is the intersection of the inputs.
789  Not recommended for performance unless necessary.
790  Try to fuse arithmetic operations into forall or Stencil operations if possible.
791 
792  \param a_rhs Another BoxData
793  */
794  inline BoxData<T,C,MEM,D,E> operator*(const BoxData<T,C,MEM,D,E>& a_rhs) const;
795 
796  /// Pointwise Division on Intersection
797  /**
798  Output range is the intersection of the inputs.
799  Not recommended for performance unless necessary.
800  Try to fuse arithmetic operations into forall or Stencil operations if possible.
801 
802  \param a_rhs Another BoxData
803  */
804  inline BoxData<T,C,MEM,D,E> operator/(const BoxData<T,C,MEM,D,E>& a_rhs) const;
805 
806  /// Pointwise Addition on Intersection
807  /**
808  Not recommended for performance unless necessary.
809  Try to fuse arithmetic operations into forall or Stencil operations if possible.
810 
811  \param a_rhs Another BoxData
812  */
814 
815  /// Pointwise Subtraction on Intersection
816  /**
817  Not recommended for performance unless necessary.
818  Try to fuse arithmetic operations into forall or Stencil operations if possible.
819 
820  \param a_rhs Another BoxData
821  */
822  inline BoxData<T,C,MEM,D,E>& operator-=(const BoxData<T,C,MEM,D,E>& a_rhs);
823 
824  /// Pointwise Multiplication on Intersection
825  /**
826  Not recommended for performance unless necessary.
827  Try to fuse arithmetic operations into forall or Stencil operations if possible.
828 
829  \param a_rhs Another BoxData
830  */
831  inline BoxData<T,C,MEM,D,E>& operator*=(const BoxData<T,C,MEM,D,E>& a_rhs);
832 
833  /// Pointwise Division on Intersection
834  /**
835  Not recommended for performance unless necessary.
836  Try to fuse arithmetic operations into forall or Stencil operations if possible.
837 
838  \param a_rhs Another BoxData
839  */
840  inline BoxData<T,C,MEM,D,E>& operator/=(const BoxData<T,C,MEM,D,E>& a_rhs);
841 
842  /// Pointwise Addition by Scalar
843  /**
844  Not recommended for performance unless necessary.
845  Try to fuse arithmetic operations into forall or Stencil operations if possible.
846 
847  \param a_scale A scalare of type T
848  */
849  inline BoxData<T,C,MEM,D,E>& operator+=(T a_scale);
850 
851  /// Pointwise Subtraction by Scalar
852  /**
853  Not recommended for performance unless necessary.
854  Try to fuse arithmetic operations into forall or Stencil operations if possible.
855 
856  \param a_scale A scalare of type T
857  */
858  inline BoxData<T,C,MEM,D,E>& operator-=(T scale);
859 
860  /// Pointwise Multiplication by Scalar
861  /**
862  Not recommended for performance unless necessary.
863  Try to fuse arithmetic operations into forall or Stencil operations if possible.
864 
865  \param a_scale A scalare of type T
866  */
867  inline BoxData<T,C,MEM,D,E>& operator*=(T scale);
868 
869  /// Pointwise Division by Scalar
870  /**
871  Not recommended for performance unless necessary.
872  Try to fuse arithmetic operations into forall or Stencil operations if possible.
873 
874  \param a_scale A scalare of type T
875  */
876  inline BoxData<T,C,MEM,D,E>& operator/=(T scale);
877 
878  /// Pointwise Addition an Array
879  /**
880  Not recommended for performance unless necessary.
881  Try to fuse arithmetic operations into forall or Stencil operations if possible.
882 
883  \param a_scale A scalare of type T
884  */
885  inline BoxData<T,C,MEM,D,E>& operator+=(const Array<T,C*D*E>& a_array);
886 
887  /// Pointwise Subtraction an Array
888  /**
889  Not recommended for performance unless necessary.
890  Try to fuse arithmetic operations into forall or Stencil operations if possible.
891 
892  \param a_scale A scalare of type T
893  */
894  inline BoxData<T,C,MEM,D,E>& operator-=(const Array<T, C*D*E>& a_array);
895 
896  /// Pointwise Multiplication an Array
897  /**
898  Not recommended for performance unless necessary.
899  Try to fuse arithmetic operations into forall or Stencil operations if possible.
900 
901  \param a_scale A scalare of type T
902  */
903  inline BoxData<T,C,MEM,D,E>& operator*=(const Array<T, C*D*E>& a_array);
904 
905  /// Pointwise Division by an Array
906  /**
907  Not recommended for performance unless necessary.
908  Try to fuse arithmetic operations into forall or Stencil operations if possible.
909 
910  \param a_scale A scalare of type T
911  */
912  inline BoxData<T,C,MEM,D,E>& operator/=(const Array<T, C*D*E>& a_array);
913 
914  inline void increment(const BoxData<T,C,MEM,D,E>& rhs, T scale = 1);
915 
916  inline void incrementProduct(const BoxData<T,C,MEM,D,E>& A, const BoxData<T,C,MEM,D,E>& B, T scale = 1);
917 
918  ///@}
919 
920  ///////////////////////////////////////////////////////////////////////////////////////
921  /** @name Utility */
922  ///@{
923 
924  /// Initialize All Values
925  /**
926  Set all values equal to a constant.
927 
928  \param a_val A constant value.
929  */
930  inline void setVal(const T& a_val);
931 
932  // TODO: Deprecated because Threshold ops don't work with std::complex
933  /// Clamp Values
934  /**
935  Threshold data between an input max and min
936 
937  \param a_min Minimum value
938  \param a_max Maximum value
939  */
940  //inline void clampVal(const T& a_min, const T& a_max);
941 
942  /// Initialize All Values as Zero
943  /**
944  Set all values equal to a zero.
945 
946  */
947  inline void setToZero();
948 
949  /// Set All Values in Box
950  /**
951  Selectively initializes values for a specified Box. If <code>a_box</code>
952  is not contained in <code>this->box()</code>, the initialization is done
953  on the intersection.
954  Avoid calling this function as much as possible in performance critical code
955 
956  \param a_val A constant value.
957  \param a_box Domain to set to a_val
958  */
959  inline void setVal(const T& a_val, const Box& a_box);
960 
961  /// Set All Values of Component in Box
962  /**
963  Avoid calling this function as much as possible in performance critical code
964 
965  \param a_val A constant value.
966  \param a_box Domain to set to a_val
967  \param a_c First index
968  \param a_d (Optional) Second index. (default: 0)
969  \param a_e (Optional) Third index. (default: 0)
970  */
971  inline void setVal(const T& a_val,
972  const Box& a_box,
973  int a_c,
974  int a_d = 0,
975  int a_e = 0);
976 
977  /// Set Random Noise
978  inline void setRandom(T a_low, T a_high);
979 
980  /// Generic Reduction (Global)
981  /**
982  Computes a reduction operation
983  Stores the result in a Reduction operator.
984 
985  \param a_rxn A reduction operator
986  */
987  template<Proto::Operation OP>
988  inline void reduce(Reduction<T,OP,MEM>& a_Rxn) const;
989 
990  /// Generic Reduction (Componentwise)
991  /**
992  Computes a reduction operation on a given component
993  Stores the result in a Reduction operator.
994 
995  \param a_rxn A reduction operator
996  \param a_c First tensor index.
997  \param a_d (Optional) Second index. (default: 0)
998  \param a_e (Optional) Third index. (default: 0)
999  */
1000  template<Proto::Operation OP>
1001  inline void reduce( Reduction<T,OP,MEM>& a_Rxn, int a_c, int a_d = 0, int a_e = 0) const;
1002 
1003  /// Absolute Maximum Value (Global)
1004  /**
1005  Returns the maximum absolute value over the entire data set
1006  */
1007  inline T absMax() const;
1008 
1009  /// Absolute Maximum Value (Componentwise)
1010  /**
1011  Returns the maximum absolute value of a given component
1012 
1013  \param a_c First tensor index.
1014  \param a_d Second tensor index.
1015  \param a_e Third tensor index.
1016  */
1017  inline T absMax(int a_c, int a_d = 0, int a_e = 0) const;
1018 
1019  /// Absolute Maximum Value (Global, Reduction)
1020  /**
1021  Computes the global maximum absolute value
1022  Stores the result in a Reduction operator.
1023 
1024  \param a_rxn A reduction operator
1025  */
1026  inline void absMax(Reduction<T,Abs,MEM>& a_Rxn) const;
1027 
1028  /// Absolute Maximum Value (Componentwise, Reduction)
1029  /**
1030  Computes the maximum absolute value of a given component
1031  Stores the result in a Reduction operator.
1032 
1033  \param a_rxn A reduction operator
1034  \param a_c First tensor index.
1035  \param a_d Second tensor index.
1036  \param a_e Third tensor index.
1037  */
1038  inline void absMax(Reduction<T,Abs,MEM>& a_Rxn, int a_c, int a_d = 0, int a_e = 0) const;
1039 
1040  /// Minimum Value (Global)
1041  /**
1042  Returns the minimum value over the entire data set
1043  */
1044  inline T min() const;
1045 
1046  /// Minimum Value (Componentwise)
1047  /**
1048  Returns the minimum value of a given component
1049 
1050  \param a_c First tensor index.
1051  \param a_d Second tensor index.
1052  \param a_e Third tensor index.
1053  */
1054  inline T min(int a_c, int a_d = 0, int a_e = 0) const;
1055 
1056  /// Minimum Value (Global, Reduction)
1057  /**
1058  Computes the minimum value over the entire data set
1059  Stores the result in a reduction operator
1060 
1061  \param a_rxn A reduction operator
1062  */
1063  inline void min(Reduction<T, Min, MEM>& a_rxn) const;
1064 
1065  /// Minimum Value (Componentwise, Reduction)
1066  /**
1067  Computes the minimum value of a given component
1068  Stores the result in a reduction operator
1069 
1070  \param a_rxn A reduction operator
1071  \param a_c First tensor index.
1072  \param a_d Second tensor index.
1073  \param a_e Third tensor index.
1074  */
1075  inline void min(Reduction<T, Min, MEM>& a_rxn, int a_c, int a_d = 0, int a_e = 0) const;
1076 
1077  /// Maximum Value (Global)
1078  /**
1079  Returns the maximum value over the entire data set
1080  */
1081  inline T max() const;
1082 
1083  /// Maximum Value (Componentwise)
1084  /**
1085  Returns the maximum value of a given component
1086 
1087  \param a_c First tensor index.
1088  \param a_d Second tensor index.
1089  \param a_e Third tensor index.
1090  */
1091  inline T max(int a_c, int a_d = 0, int a_e = 0) const;
1092 
1093  /// Max (Global, Reduction)
1094  /**
1095  Computes the maximum of values over the entire data set
1096  Stores the result in a reduction operator
1097 
1098  \param a_rxn A reduction operator.
1099  */
1100  inline void max(Reduction<T, Max, MEM>& a_rxn) const;
1101 
1102  /// Max (Componentwise, Reduction)
1103  /**
1104  Computes the maximum value of a given component
1105  Stores the result in a reduction operator
1106 
1107  \param a_rxn A reduction operator.
1108  \param a_c First tensor index.
1109  \param a_d Second tensor index.
1110  \param a_e Third tensor index.
1111  */
1112  inline void max(Reduction<T, Max, MEM>& a_rxn, int a_c, int a_d = 0, int a_e = 0) const;
1113 
1114  /// Sum (Global)
1115  /**
1116  Return the global sum
1117  */
1118  inline T sum() const;
1119 
1120  /// Sum (Componentwise)
1121  /**
1122  Returns the sum of a particular component
1123 
1124  \param a_c First tensor index.
1125  \param a_d Second tensor index.
1126  \param a_e Third tensor index.
1127  */
1128  inline T sum(int a_c, int a_d = 0, int a_e = 0) const;
1129 
1130  /// Sum (Global, Reduction)
1131  /**
1132  Computes the global sum
1133  Stores the result in a reduction operator
1134 
1135  \param a_rxn A reduction operator.
1136  */
1137  inline void sum(Reduction<T, Sum, MEM>& a_rxn) const;
1138 
1139  /// Sum (Componentwise)
1140  /**
1141  Computes the sum of a particular component
1142  Stores the result in a reduction operator
1143 
1144  \param a_rxn A reduction operator.
1145  \param a_c First tensor index.
1146  \param a_d Second tensor index.
1147  \param a_e Third tensor index.
1148  */
1149  inline void sum(Reduction<T, Sum, MEM>& a_rxn, int a_c, int a_d = 0, int a_e = 0) const;
1150 
1151  /// Sum Abs(Global)
1152  /**
1153  Return the global sum of the absolute value
1154  */
1155  inline T sumAbs() const;
1156 
1157  /// Sum Abs(Componentwise)
1158  /**
1159  Returns the sum of a particular component
1160 
1161  \param a_c First tensor index.
1162  \param a_d Second tensor index.
1163  \param a_e Third tensor index.
1164  */
1165  inline T sumAbs(int a_c, int a_d = 0, int a_e = 0) const;
1166 
1167  /// Sum Abs (Global, Reduction)
1168  /**
1169  Computes the global sum
1170  Stores the result in a reduction operator
1171 
1172  \param a_rxn A reduction operator.
1173  */
1174  inline void sumAbs(Reduction<T, SumAbs, MEM>& a_rxn) const;
1175 
1176  /// Sum (Componentwise)
1177  /**
1178  Computes the sum of a particular component
1179  Stores the result in a reduction operator
1180 
1181  \param a_rxn A reduction operator.
1182  \param a_c First tensor index.
1183  \param a_d Second tensor index.
1184  \param a_e Third tensor index.
1185  */
1186  inline void sumAbs(Reduction<T, SumAbs, MEM>& a_rxn, int a_c, int a_d = 0, int a_e = 0) const;
1187 
1188 
1189  inline T sumSquare() const;
1190  inline T sumSquare(int a_c, int a_d = 0, int a_e = 0) const;
1191  inline void sumSquare(Reduction<T, SumSquare, MEM>& a_rxn) const;
1192  inline void sumSquare(Reduction<T, SumSquare, MEM>& a_rxn, int a_c, int a_d = 0, int a_e = 0) const;
1193 
1194  /// Integrate (Isotropic Grid)
1195  /**
1196  Approximate the definite integral using an isotropic grid spacing as
1197  <code>sum(a_c, a_d, a_e) * pow(a_dx, DIM) </code>.
1198 
1199  \param a_dx Isotropic grid spacing.
1200  \param a_c First tensor index.
1201  \param a_d Second tensor index.
1202  \param a_e Third tensor index.
1203  */
1204  inline T integrate(T a_dx, int a_c = 0, int a_d = 0, int a_e = 0) const;
1205 
1206  /// Integrate (Anisotropic Grid)
1207  /**
1208  Approximate the definite integral using an isotropic grid spacing as
1209  <code>sum(a_c, a_d, a_e) * pow(a_dx, DIM) </code>.
1210 
1211  \param a_dx Anisotropic grid spacings.
1212  \param a_c First tensor index.
1213  \param a_d Second tensor index.
1214  \param a_e Third tensor index.
1215  */
1216  inline T integrate(
1217  Array<T, DIM> a_dx,
1218  int a_c = 0, int a_d = 0, int a_e = 0) const;
1219 
1220  /// Shift Domain
1221  /**
1222  Shifts the domain Box of this, moving all data along with it.
1223  e.g. data associated with Point p will now be associated with Point p + a_shift.
1224  The function is const because m_box is mutable
1225 
1226  \param a_shift A Point interpreted as a shift vector.
1227  */
1228  inline void shift(const Point& a_shift) const;
1229 
1230  /// Buffer Size
1231  inline size_t linearSize() const;
1232 
1233  /// Buffer Write
1234  /**
1235  Write a subset of data from <code> *this </code> into a C-array buffer.
1236 
1237  \param a_buffer Destination buffer
1238  \param a_box Domain to write from
1239  \param a_comps Components to write from
1240  */
1241  inline void linearOut(
1242  void* a_buffer,
1243  const Box& a_box,
1244  CInterval a_comps) const;
1245 
1246  //FIXME: Only works for vector/scalar valued BoxData
1247  /// Buffer Write (Primitive)
1248  /**
1249  Write a subset of data from <code> *this </code> into a C-array buffer.
1250  Overload using plain-old-data inputs, useful on GPUs
1251 
1252  \param a_buffer Destination buffer
1253  \param a_box Domain to write from
1254  \param a_startcomp First component to write from
1255  \param a_numcomps Number of components to write
1256  */
1257  inline void linearOut(
1258  void* a_buffer,
1259  const Box& a_box,
1260  unsigned int a_startcomp,
1261  unsigned int a_numcomps) const;
1262 
1263  /// Buffer Read
1264  /**
1265  Read data into *this from a C-array buffer populated by
1266  <code>BoxData<T,C,MEM,D,E>::linearOut(...)</code>.
1267  <code>this->box()</code> may be shifted with respect to the BoxData
1268  that wrote to the buffer, but the dimensions of the Box as well as the
1269  tensor structure must be the same.
1270 
1271  \param a_buffer Source buffer
1272  \param a_box Domain to read from
1273  \param a_comps Components to read from
1274  */
1275  inline void linearIn(
1276  void* a_buffer,
1277  const Box& a_box,
1278  CInterval a_comps);
1279 
1280 
1281  /// Buffer Read
1282  /**
1283  Read data into *this from a C-array buffer populated by
1284  <code>BoxData<T,C,MEM,D,E>::linearOut(...)</code>.
1285  Primitive data overload for use with GPUs.
1286 
1287  \param a_buffer Source buffer
1288  \param a_box Domain to read from
1289  \param a_comps Components to read from
1290  */
1291  inline void linearIn(
1292  void* a_buffer,
1293  const ::Proto::Box& a_bx,
1294  unsigned int a_startcomp,
1295  unsigned int a_numcomps);
1296 
1297  /// Contains CInterval
1298  /**
1299  Checks if an CInterval object is a subset of the component space
1300  of *this. This function is mostly used internally, but it can
1301  be useful for checking inputs to CopyTo and the slicing functions
1302  */
1303  inline bool contains(CInterval a_interval) const;
1304 
1305  /// Check Aliasing
1306  /**
1307  Returns true if <code> *this </code> and <code> a_src </code> are aliased
1308  to the same data buffer. This function also returns true if one array
1309  is a slice of another.
1310  */
1311  template<unsigned int CC, unsigned int DD, unsigned int EE>
1312  inline bool isAlias(const BoxData<T, CC, MEM, DD, EE>& a_src) const;
1313 
1314  /// Print
1315  /**
1316  Default Print method. Outputs Domain Box and extrema of *this
1317  */
1318  void print() const;
1319 
1320  /// Print Data
1321  /**
1322  Pretty prints *all* of the data in *this. Prettiness may vary depending
1323  on the domain size. This function is purely for debugging purposes and should not
1324  be used in performance code.
1325 
1326  \param a_prec (Optional) Desired precision for fixed decimal output. Defaults to 2.
1327  */
1328  void printData(int a_prec = 2) const;
1329 
1330  /// Print Data in Box
1331  /**
1332  Pretty prints the data in *this within a given Box for all components.
1333  Input Boxes of size 16^DIM or smaller are recommended to maintain prettiness.
1334  This function is purely for debugging purposes and should not be used in
1335  performance code.
1336 
1337  \param a_box Desired subset for printing
1338  \param a_prec (Optional) Desired precision for fixed decimal output. Defaults to 2.
1339  */
1340  void printData(const Box& a_box, int a_prec = 2) const;
1341 
1342  /// Print Component Data in Box
1343  /**
1344  Pretty prints the data in *this within a given Box for a single component.
1345  Input Boxes of size 16^DIM or smaller are recommended to maintain prettiness.
1346  This function is purely for debugging purposes and should not be used in
1347  performance code.
1348 
1349 
1350  \param a_box Desired subset for printing
1351  \param a_c First tensor index. Defaults to 0.
1352  \param a_d Second tensor index. Defaults to 0.
1353  \param a_e Third tensor index. Defaults to 0.
1354  \param a_prec (Optional) Desired precision for fixed decimal output. Defaults to 2
1355  */
1356  void printData(const Box& a_box, int a_c, int a_d, int a_e, int a_prec = 2) const;
1357 
1358  bool containsInfOrNAN() const;
1359  bool containsInfOrNAN(Box domain) const;
1360  bool containsUninitialized() const;
1361  bool containsUninitialized(Box domain) const;
1362  bool containsAddress(T* address) const;
1363  ///@}
1364 
1365  ///////////////////////////////////////////////////////////////////////////////////////
1366  // Friends
1367 
1368  template<class TT>
1369  friend class Stencil;
1370 
1371  template<class TT, unsigned int CC, unsigned int DD, unsigned int EE,MemType MM>
1373  const Point& a_shift);
1374 
1375  template<class TT, unsigned int CC, unsigned int DD, unsigned int EE,MemType MM>
1376  friend const BoxData<TT,CC,MM,DD,EE> alias(const BoxData<TT,CC,MM,DD,EE>& a_original,
1377  const Point& a_shift);
1378 
1379  template<typename _T, unsigned int _C, MemType _MEM, unsigned int _D, unsigned int _E>
1381  const BoxData<_T,_C,_MEM,_D,_E>& a_src,
1382  unsigned int a_c,
1383  unsigned int a_d,
1384  unsigned int a_e);
1385 
1386  template<typename _T, unsigned int _C, unsigned int _CC, MemType _MEM>
1388  const BoxData<_T,_C,_MEM,1,1>& a_src,
1389  unsigned int a_nstart);
1390 
1391  template<typename _T, unsigned int _C, unsigned int _D, MemType _MEM>
1393  const BoxData<_T,_C,_MEM,_D,1>& a_src,
1394  unsigned int a_d);
1395 
1396  // TODO: Why?
1397  size_t size(const Box& a_box,
1398  const size_t a_comps) const
1399  {
1400  return a_box.size() * (sizeof(T) * a_comps);
1401  }
1402 
1403 
1404  // TODO: Why?
1405  size_t charsize(const ::Proto::Box& a_bx,
1406  unsigned int a_startcomp,
1407  unsigned int a_numcomps) const
1408  {
1409  return a_bx.size()*sizeof(T)*a_numcomps;
1410  }
1411 
1412 
1413 
1414  // TODO: Chombo Compatibility?
1415  static int preAllocatable()
1416  {
1417  return 0; // static preAllocatable
1418  }
1419 
1420  // TODO: What is this for?
1421  static int memTypeAllocation()
1422  {
1423  return 1;
1424  }
1425 
1426  private:
1427  bool m_alias; ///< was this created as an alias
1429  mutable Box m_box; ///< Box defining the domain of *this
1430  ::std::shared_ptr<T> m_data; ///< Data array
1431  T* m_rawPtr; ///< Raw pointer to the data
1432  }; // end class BoxData
1433 
1434  template<class T = double, unsigned int C=1,
1435  MemType MEM=MEMTYPE_DEFAULT, unsigned int D=1, unsigned int E=1>
1437  {
1438  public:
1440  FluxBoxData(const Box& a_box, bool a_doExtrude = true)
1441  {
1442  define(a_box, a_doExtrude);
1443  }
1444  FluxBoxData(Array<std::shared_ptr<BoxData<T,C,MEM,D,E>>,DIM>& a_data)
1445  {
1446  m_data = a_data;
1447  }
1448  FluxBoxData(std::vector<std::shared_ptr<BoxData<T,C,MEM,D,E>>>& a_data)
1449  {
1450  PROTO_ASSERT(a_data.size() == DIM,
1451  "FluxBoxData::constructor | Error: input vector must have DIM components");
1452  for (int ii = 0; ii < DIM; ii++)
1453  {
1454  m_data[ii] = a_data[ii];
1455  }
1456  }
1457  void define(const Box& a_box, bool a_doExtrude = true)
1458  {
1459  m_box0 = a_box;
1460  for (int dir = 0; dir < DIM; dir++)
1461  {
1462  Box Bd = a_box;
1463  if (a_doExtrude)
1464  {
1465  Bd = a_box.extrude(Point::Basis(dir));
1466  }
1467  m_data[dir] = std::make_shared<BoxData<T,C,MEM,D,E>>(Bd);
1468  }
1469  }
1470 
1471  BoxData<T,C,MEM,D,E>& operator[](unsigned int a_index)
1472  {
1473  PROTO_ASSERT(a_index < DIM,
1474  "FluxBoxData::operator[] | Error: index out of bounds");
1475  return *(m_data[a_index]);
1476  }
1477 
1478  const BoxData<T,C,MEM,D,E>& operator[](unsigned int a_index) const
1479  {
1480  PROTO_ASSERT(a_index < DIM,
1481  "FluxBoxData::operator[] | Error: index out of bounds");
1482  return *(m_data[a_index]);
1483  }
1485  const Array<std::shared_ptr<BoxData<T,C,MEM,D,E>>,DIM>& array() const {return m_data;}
1486  Box box() const { return m_box0; }
1487  Box box(int a_dir) const { return m_data[a_dir]->box(); }
1488  private:
1491  };
1492 
1493 
1494 ///////////////////////////////////////////////////////////////////////////////////////////////
1495 /** @name Alias and Slice Operators
1496  The alias and slice operations facilitate BoxData operations while avoiding unnecessary copies.
1497  See the sample code below for an explanation of the syntax.
1498 
1499  Example <code> alias </code> usage:
1500  \snippet Snippets.cpp proto_alias
1501 
1502  Example <code> slice </code> usage:
1503  \snippet Snippets.cpp proto_slice
1504 */
1505 
1506 ///@{
1507 
1508  /// Alias (Non-Const)
1509  /**
1510  Creates a read-write alias to a mutable source BoxData with an optional shift.
1511 
1512  \param a_original Source data
1513  \param a_shift (Optional) Domain shift for the aliased BoxData.
1514  */
1515  template<class T, unsigned int C=1, unsigned int D=1, unsigned int E=1,
1518  BoxData<T,C,MEM,D,E>& a_original,
1519  const Point& a_shift = Point::Zeros());
1520 
1521  /// Alias (Const)
1522  /**
1523  Creates a read-only alias to a const source BoxData with an optional shift.
1524 
1525  \param a_original Source data
1526  \param a_shift (Optional) Domain shift for the aliased BoxData.
1527  */
1528  template<class T, unsigned int C = 1, unsigned int D = 1, unsigned int E = 1,
1531  const BoxData<T,C,MEM,D,E>& a_original,
1532  const Point& a_shift=Point::Zeros());
1533 
1534  /// Slice Arbitrary Component (Non-Const)
1535  /**
1536  Creates a scalar BoxData read-write alias to a prescribed component.
1537 
1538  \param a_src Source data
1539  \param a_c First component index
1540  \param a_d (Optional) Second component index (default: 0)
1541  \param a_e (Optional) Third component index (default: 0)
1542  */
1543  template<typename T, unsigned int C, MemType MEM=MEMTYPE_DEFAULT,
1544  unsigned int D=1, unsigned int E=1>
1546  const BoxData<T,C,MEM,D,E>& a_src,
1547  unsigned int a_c,
1548  unsigned int a_d = 0,
1549  unsigned int a_e = 0);
1550 
1551  /// Vector Slice (Non-Const)
1552  /**
1553  Creates a vector BoxData read-write alias to a prescribed component range
1554 
1555  \param a_src Source data
1556  \param a_startcomp First component of the slice
1557  */
1558  template<typename T, unsigned int C, unsigned int CC, MemType MEM=MEMTYPE_DEFAULT>
1560  const BoxData<T,C,MEM,1,1>& a_src,
1561  unsigned int a_startcomp);
1562 
1563  template<typename T, unsigned int C, unsigned int D, MemType MEM=MEMTYPE_DEFAULT>
1565  const BoxData<T,C,MEM,D,1>& a_src,
1566  unsigned int a_d);
1567 
1568 ///@}
1569 
1570  template <typename T, unsigned int CL, unsigned int CR, MemType MEM,
1571  unsigned int DL, unsigned int DR, unsigned int E = 1>
1573  matrixProduct(
1574  const BoxData<T,CL,MEM,DL,E>& A,
1575  const BoxData<T,CR,MEM,DR,E>& B,
1576  T scale = 1.0);
1577 
1578  template <typename T, unsigned int CL, unsigned int CR, MemType MEM,
1579  unsigned int DL, unsigned int DR, unsigned int E = 1>
1582  const BoxData<T,CL,MEM,DL,E>& A,
1583  const BoxData<T,CR,MEM,DR,E>& B,
1584  T scale = 1.0);
1585 
1586  template <typename T, unsigned int CL, unsigned int CR, MemType MEM,
1587  unsigned int DL, unsigned int DR, unsigned int E = 1>
1590  const BoxData<T,CL,MEM,DL,E>& A,
1591  const BoxData<T,CR,MEM,DR,E>& B,
1592  T scale = 1.0);
1593 
1594 } //end Proto namespace
1595 #endif //end include guard
Definition: Proto_BoxData.H:89
ACCEL_DECORATION std::size_t size(unsigned int a_dim) const
Edge Size.
Box m_box0
Definition: Proto_BoxData.H:1489
std::enable_if< I< sizeof...(LArgs), void >::typecall_mb_level_forall(Func &a_func, MBIndex &a_index, Centering CTR, std::tuple< LArgs... > a_args, FArgs &&... a_fargs){ auto &arg=parse_mb_level_arg(a_index, CTR, std::get< I >a_args));call_mb_level_forall< I+1 >a_func, a_index, CTR, a_args, a_fargs..., arg);}template< typename T, unsigned int C, MemType MEM, Centering CTR >template< typename Func, typename... Srcs >void MBLevelBoxData< T, C, MEM, CTR >::initialize(Func &a_func, Srcs &... a_srcs){ auto srcs=std::tuple< Srcs &... >a_srcs...);for(auto iter :(m_layout)) { auto &patch=(*this)[iter];auto block=layout().block(iter);call_mb_level_forall(a_func, iter, CTR, srcs, patch, block);} }template< typename T, unsigned int C, MemType MEM, Centering CTR >template< typename Func, typename... Srcs >void MBLevelBoxData< T, C, MEM, CTR >::initConvolve(Func &a_func, Srcs &... a_srcs){ auto g=ghost();g[0]=g[0]+Point::Ones();MBLevelBoxData< T, C, MEM, CTR > tmp(m_layout, g);tmp.initialize(a_func, a_srcs...);for(auto iter :m_layout) { auto &tmp_i=tmp[iter];auto &patch=(*this)[iter];Operator::convolve(patch, tmp_i);}}template< typename T, unsigned int C, MemType MEM, Centering CTR >void MBLevelBoxData< T, C, MEM, CTR >::setVal(T a_value){ for(auto data :m_data) { data-> setVal(a_value)
Definition: Proto_MBLevelBoxData.H:208
unsigned int subBoxDimY
Definition: Proto_BoxData.H:290
inline ::std::shared_ptr< T > aliasData()
Shared Buffer Accessor.
Definition: Proto_BoxData.H:705
unsigned int subBoxDimX
Definition: Proto_BoxData.H:289
int linearSize(const T &inputT)
Definition: Proto_PointLIO.H:55
std::size_t size() const
Definition: Proto_BoxData.H:727
inline ::std::shared_ptr< T > aliasData() const
Shared Buffer Accessor (Const)
Definition: Proto_BoxData.H:712
bool m_stackAlloc
Definition: Proto_BoxData.H:1428
FluxBoxData()
Definition: Proto_BoxData.H:1439
Array< std::shared_ptr< BoxData< T, C, MEM, D, E > >, DIM > m_data
Definition: Proto_BoxData.H:1490
BoxDataOp
Definition: Proto_BoxData.H:86
Multidimensional Rectangular Array.
Definition: Proto_BoxData.H:314
void linearOut(void *const a_outBuf, const T &inputT)
Definition: Proto_PointLIO.H:67
unsigned int boxDimY
Definition: Proto_BoxData.H:288
A Linear Stencil Operation.
Definition: Proto_BoxData.H:76
Definition: Proto_MemType.H:7
BoxData< T, CC, MEM, 1, 1 > slice(const BoxData< T, C, MEM, 1, 1 > &a_src, unsigned int a_startcomp)
Vector Slice (Non-Const)
Definition: Proto_BoxData.H:88
MemType
Definition: Proto_MemType.H:7
BoxData< T, CL, MEM, DR, E > matrixProduct(const BoxData< T, CL, MEM, DL, E > &A, const BoxData< T, CR, MEM, DR, E > &B, T scale=1.0)
static int memTypeAllocation()
Definition: Proto_BoxData.H:1421
Defines discrete rotations in logically rectangular coordinate systems.
Definition: Proto_CoordPermutation.H:13
Box extrude(const Point &a_dir, int a_dist=1) const
Extrude.
std::size_t numValues() const
Definition: Proto_BoxData.H:728
Definition: Proto_BoxData.H:95
Definition: Proto_BoxData.H:81
Component-Space Interval.
Definition: Proto_CInterval.H:14
T * m_rawPtr
Raw pointer to the data.
Definition: Proto_BoxData.H:1431
FluxBoxData(const Box &a_box, bool a_doExtrude=true)
Definition: Proto_BoxData.H:1440
const Array< std::shared_ptr< BoxData< T, C, MEM, D, E > >, DIM > & array() const
Definition: Proto_BoxData.H:1485
An interval in DIM dimensional space.
Definition: Proto_Box.H:29
Definition: Proto_BoxData.H:94
size_t charsize(const ::Proto::Box &a_bx, unsigned int a_startcomp, unsigned int a_numcomps) const
Definition: Proto_BoxData.H:1405
Definition: Proto_Reduction.H:30
Definition: Proto_BoxData.H:93
Definition: Proto_BoxData.H:92
void define(const Box &a_box, bool a_doExtrude=true)
Definition: Proto_BoxData.H:1457
#define ACCEL_DECORATION
Definition: Proto_Accel.H:12
Box box() const
Definition: Proto_BoxData.H:1486
static int preAllocatable()
Definition: Proto_BoxData.H:1415
MBPoint operator+(const MBPoint &mbpoint, const Point &p)
Definition: Proto_MBProblemDomain.H:55
#define PROTO_ASSERT(stmt, args...)
Definition: Proto_PAssert.H:48
bool defined() const
Defined Query.
Definition: Proto_BoxData.H:734
size_t size(const Box &a_box, const size_t a_comps) const
Definition: Proto_BoxData.H:1397
Box box() const
Definition: Proto_BoxData.H:719
Definition: Proto_Array.H:17
uint64_t index
Definition: Proto_MBBoxPartition.H:15
const BoxData< T, C, MEM, D, E > & operator[](unsigned int a_index) const
Definition: Proto_BoxData.H:1478
Definition: Proto_BoxData.H:90
T & getValDevice(unsigned int a_c, unsigned int a_d=0, unsigned int a_e=0)
Definition: Proto_BoxData.H:144
BoxData< T, DL, MEM, DR, E > matrixProductLeftTranspose(const BoxData< T, CL, MEM, DL, E > &A, const BoxData< T, CR, MEM, DR, E > &B, T scale=1.0)
ACCEL_DECORATION Array< T, N > & operator*(int scale, Array< T, N > &arr)
Premultiplication by a scalar int.
A templated constant size array object similar to std::array, but with the ability to be used inside ...
Definition: Proto_Array.H:28
Integer Valued Vector.
Definition: Proto_Point.H:24
ACCEL_DECORATION Array< T, N > & operator-(Array< T, N > &arr)
Unary negation.
FluxBoxData(Array< std::shared_ptr< BoxData< T, C, MEM, D, E >>, DIM > &a_data)
Definition: Proto_BoxData.H:1444
BoxData< T, C, MEM, 1, 1 > plane(const BoxData< T, C, MEM, D, 1 > &a_src, unsigned int a_d)
Definition: Proto_BoxData.H:91
Box m_box
Box defining the domain of *this.
Definition: Proto_BoxData.H:1429
void linearIn(T &a_outputT, const void *const inBuf)
Definition: Proto_PointLIO.H:61
Point dir
Definition: Proto_MBBoxPartition.H:16
void null_deleter_boxdata(void *ptr)
Definition: Proto_BoxData.H:84
::std::shared_ptr< T > m_data
Data array.
Definition: Proto_BoxData.H:1430
BoxData< T, C, MEM, D, E > & operator+=(BoxData< T, C, MEM, D, E > &a_dst, const LazyInterpStencil< T, C, MEM, D, E > &&a_op)
Definition: Proto_InterpStencil.H:84
FluxBoxData(std::vector< std::shared_ptr< BoxData< T, C, MEM, D, E >>> &a_data)
Definition: Proto_BoxData.H:1448
BoxData< T, CL, MEM, CR, E > matrixProductRightTranspose(const BoxData< T, CL, MEM, DL, E > &A, const BoxData< T, CR, MEM, DR, E > &B, T scale=1.0)
Box box(int a_dir) const
Definition: Proto_BoxData.H:1487
Pointwise Variable.
Definition: Proto_BoxData.H:117
#define MEMTYPE_DEFAULT
Definition: Proto_MemType.H:24
Var< T, C, MEM, D, E > reference
Definition: Proto_BoxData.H:318
bool m_alias
was this created as an alias
Definition: Proto_BoxData.H:1427
Array< std::shared_ptr< BoxData< T, C, MEM, D, E > >, DIM > & array()
Definition: Proto_BoxData.H:1484
const BoxData< T, C, MEM, D, E > alias(const BoxData< T, C, MEM, D, E > &a_original, const Point &a_shift=Point::Zeros())
Alias (Const)
BoxData< T, C, MEM, D, E > & operator[](unsigned int a_index)
Definition: Proto_BoxData.H:1471
Definition: Proto_BoxData.H:1436