Proto  3.2
Proto_Stencil.H
Go to the documentation of this file.
1 #ifndef _PROTO_STENCIL_H_
2 #define _PROTO_STENCIL_H_
3 
4 #include <vector>
5 #include <tuple>
6 #include <iostream>
7 #include <iomanip> //for pretty printing
8 #include <set>
9 
10 #include "Proto_Timer.H"
11 #include "Proto_MemType.H"
12 #include "Proto_Point.H"
13 #include "Proto_BoxData.H"
14 #include "Proto_Math.H"
15 #ifdef PR_LAPACK
16 #include "Proto_Matrix.H"
17 #endif
18 
19 
20 //biggest stencil size I have seen:
21 #define PR_MAX_COEFFS 343
22 
23 namespace Proto {
24 
25  // Forward declarations
26  template <typename T>
27  class Stencil;
28 
29  template <typename T, unsigned int C, MemType MEMTYPE, unsigned int D, unsigned int E>
30  class BoxData;
31 
32 //=======================================================================================
33 // SHIFT ||
34 //=======++
35 
36  /** @defgroup stencil_operations Stencil Operations*/
37  /*@{*/
38 
39  /// Stencil Shift
40  /**
41  \ingroup stencil_operations
42  A shift is an alias for a Point which is used solely to provide
43  a fluent syntax for creating Stencils. Refer to the documentation
44  for Stencil for an illustrative example.
45  */
46  class Shift {
47  public:
48 
49  ///////////////////////////////////////////////////////////////////////////////////////////////
50  /** @name Constructors */
51  ///@{
52 
53  /// Default Constructor
54  Shift() : m_shift(Point::Zeros()){};
55 
56  /// Point Constructor
57  /**
58  \ingroup stencil_operations
59  Builds a Shift from a Point
60 
61  \param a_pt Point to base this Shift on
62  */
63  explicit Shift(const Point& a_pt){m_shift = a_pt;};
64 
65  /// Variadic Constructor
66  /**
67  \ingroup stencil_operations
68  More or less identical to the variadic Point constructor.
69  Builds a Shift using the first DIM arguments and ignores the rest.
70 
71  \param args At least DIM int arguments, the first DIM of which define *this
72  */
73  template<typename... vals>
74  inline explicit Shift(vals... args) : m_shift(args...) {}
75 
76  ///@}
77  ///////////////////////////////////////////////////////////////////////////////////////////////
78  /** @name Methods */
79  ///@{
80 
81  /// Basis Shift
82  /**
83  \ingroup stencil_operations
84  Shortcut for <code>Shift(Point::Basis(...))</code>
85 
86  \param a_dir Direction of basis vector in [0,DIM)
87  \param a_scale (Optional) Amount to scale the basis vector by. (Default: 1).
88  */
89  inline static Shift Basis(int a_dir, int a_scale=1) { return Shift(Point::Basis(a_dir, a_scale)); }
90 
91  /// Zero Shift
92  /**
93  \ingroup stencil_operations
94  Shortcut for <code>Shift(Point::Zeros())</code>
95  */
96  inline static Shift Zeros() { return Shift(Point::Zeros()); }
97 
98  /// Unit Shift
99  /**
100  \ingroup stencil_operations
101  Shortcut for <code>Shift(Point::Ones(...))</code>
102 
103  \param a_scale (Optional) Used to scale the output. (Default: 1).
104  */
105  inline static Shift Ones(int a_scale=1){return Shift(Point::Ones(a_scale));};
106 
107  inline static Shift X(int scale = 1) { return Shift(Point::X()*scale); }
108  inline static Shift Y(int scale = 1) { return Shift(Point::Y()*scale); }
109  inline static Shift Z(int scale = 1) { return Shift(Point::Z()*scale); }
110 
111  /// Get Shift Point
112  inline Point& point(){ return m_shift; }
113 
114  /// Scalar Multiplication
115  /**
116  \ingroup stencil_operations
117  Generates a Stencil<T> from the product of a scalar T coefficient and a Shift.
118  This operator is what allows for a fluid Stencil construction syntax:
119 
120  \param a_coef A coefficient
121 
122  Examples:
123  @code
124  // DIM == 1
125  Stencil<double> S1 = 1.0*Shift(-1) - 2.0*Shift(0) + 1.0*Shift(1);
126 
127  // DIM - independant
128  Stencil<double> S2 = (-2*DIM)*Shift::Zeros();
129  for (int dir = 0; dir < DIM; dir++)
130  {
131  S2 += 1.0*Shift::Basis(dir, -1);
132  S2 += 1.0*Shift::Basis(dir, +1);
133  }
134  @endcode
135  */
136  template<typename T>
137  inline Stencil<T> operator*(T a_coef) const { return Stencil<T>(*this,a_coef); }
138 
139  /// Convolution
140  /**
141  \ingroup stencil_operations
142  The product of two Shift objects is defined as their sum.
143 
144  \param a_shift Another Shift.
145  */
146  inline Shift operator*(const Shift& a_shift) const { return Shift(m_shift + a_shift.m_shift); }
147 
148  /// Componentwise Access
149  inline int& operator[](int a_dir)
150  {
151  PROTO_ASSERT(((a_dir >= 0) && (a_dir < DIM)),
152  "Shift::operator[] | Error: \
153  a_dir = %i is invalid. a_dir must be in [0,DIM=%i)",
154  a_dir, DIM);
155  return m_shift[a_dir];
156  }
157 
158  ///@}
159 
160  private:
161 
163 
164  }; // end class Shift
165 
166 //=======================================================================================
167 // LAZYSTENCIL ||
168 //=============++
169 
170  // forward declaration
171 
172  /// An Unevaluated Stencil Operation
173  /**
174  \ingroup stencil_operations
175  LazyStencil is an intermediate structure that holds the intermediate data for a
176  Stencil operation.
177 
178  LazyStencil is not explicitly part of the user interface, and is only public by
179  virtue of necessity.
180  */
181  template <typename T, unsigned int C, MemType MEMTYPE, unsigned int D, unsigned int E>
182  struct LazyStencil {
183 
184  inline LazyStencil() {};
185  inline LazyStencil(const Stencil<T>* a_stencil,
186  const BoxData<T,C,MEMTYPE,D,E>* a_src,
187  Box a_box, T a_scale);
188 
189  inline void apply(BoxData<T,C,MEMTYPE,D,E>& a_dest, bool a_overwrite);
190 
191  inline unsigned long long int size() const {return m_stencil.size();}
192  inline Box inferredRange() const;
193  Box m_range;
194 
195  std::vector<const Stencil<T>*> m_stencil;
196  std::vector<BoxData<T, C,MEMTYPE, D, E>*> m_src;
197  std::vector<Box> m_box;
198  std::vector<T> m_scale;
199  };
200 
201 //=======================================================================================
202 // STENCIL ||
203 //=========++
204 
205 /// A Linear Stencil Operation
206  /**
207  \ingroup stencil_operations
208  Encapsulates a linear stencil operation where coefficients are of type T.
209  Stencil objects are built and used in a way that conforms to their nature as operators.
210  For illustrative usage examples, refer to the following code snippets:
211 
212  Examples:
213  Build a Stencil from Shifts and coefficients:
214  \snippet Snippets.cpp proto_stencil_build
215  Apply a Stencil with no Source / Dest Refinement to a BoxData:
216  \snippet Snippets.cpp proto_stencil_apply
217 
218  The above examples illustrate the usage of Stencil to do computations in which the source and
219  destination arrays are at the same refinement. Stencil is also capable of "prolong" and "restrict"
220  type operations in which the destination and source respectively are refined. This functionality is
221  useful for operations such as averaging and interpolation, or for algorithms like Red-Black Gauss Seidel
222  Iteration in which it is necessary to evaluate a Stencil on "every other cell".
223 
224  To facilitate these more exotic operations, the Stencil API allows the user to designate a source and/or destination
225  refinement ratio. If these values are different from (1,...,1), then input Box object will be interpreted as an
226  "index range" instead of a physical Box domain. The following code snippets illustrate some examples of this functionality.
227 
228  Examples:
229  Non-Trivial Source Refinement Ratio
230  \snippet Snippets.cpp proto_stencil_average
231  Non-Trivial Destination Refinement Ratio
232  \snippet Snippets.cpp proto_stencil_dest_refine
233 
234  In the case of non-trivial destination refinement, an array of refRatio^DIM Stencils is often needed to fully populate the output.
235  Proto provides a convenience structure called InterpStencil which is designed to mitigate this form of pedantry. See the associated
236  documentation for additional information and example usage.
237  */
238  template <typename T>
239  class Stencil {
240 
241  public:
242 
243  // Friend declarations
244  template <typename TT, unsigned int C, MemType MEMTYPE , unsigned int D, unsigned int E>
245  friend class LazyStencil;
246 
247  template <typename TT, unsigned int C , MemType MEMTYPE, unsigned int D, unsigned int E>
248  friend class BoxData;
249 
250  template <typename TT, unsigned int C, MemType MEMTYPE, unsigned int D, unsigned int E>
253  LazyStencil<TT,C,MEMTYPE,D,E>&& a_op);
254 
255  template <typename TT, unsigned int C, MemType MEMTYPE, unsigned int D, unsigned int E>
258  LazyStencil<TT,C,MEMTYPE,D,E>&& a_op);
259 
260  ///////////////////////////////////////////////////////////////////////////////////////////
261  /** @name Constructors */
262  ///@{
263 
264  /// Default Constructor
265  Stencil();
266 
267  /// General Constructor
268  /**
269  \ingroup stencil_operations
270  Creates a Stencil with a single shift and coefficent.
271 
272  Not recommended for public use; see the Stencil class documentation for examples
273  of how to build a Stencil with Shift - coefficient syntax.
274 
275  \param a_shift Shift of this operation
276  \param a_coef Coefficient of this operation
277  \param a_destRefratio (Optional) Destination refinement ratio. [Default: (1,...,1) ]
278  \param a_destShift (Optional) Destination shift. [Default: (0,...,0) ]
279  \param a_srcRefratio (Optional) Source refinement ratio. [Default: (1,...,1) ]
280  */
281  Stencil(Shift a_shift,
282  T a_coef,
283  Point a_destRefratio = Point::Ones(),
284  Point a_destShift = Point::Zeros(),
285  Point a_srcRefratio = Point::Ones());
286 
287  // Destructor
288  ~Stencil();
289 
290  ///@}
291 
292  ///////////////////////////////////////////////////////////////////////////////////////////////
293  /** @name Operators */
294  ///@{
295 
296  /// Equality Operator
297  /**
298  \ingroup stencil_operations
299  Equality between Stencils is determined by value
300 
301  \param a_stencil Another Stencil
302  */
303  inline bool operator==(const Stencil<T>& a_stencil) const;
304 
305  /// Inquality Operator
306  /**
307  \ingroup stencil_operations
308  \param a_stencil Another Stencil
309  */
310  inline bool operator!=(const Stencil<T>& a_stencil) const {return !(*this == a_stencil);}
311 
312  /// Stencil Composition
313  /**
314  \ingroup stencil_operations
315  The product of two Stencils is defined as their composition.
316 
317  \param a_stencil Another Stencil
318  */
319  Stencil<T> operator*(const Stencil<T>& a_stencil) const;
320 
321  /// Scalar Multiplication
322  /**
323  \ingroup stencil_operations
324  The product of a Stencil S and a coefficient v results in the scaling of all
325  the coefficients of S by v.
326 
327  \param a_coef Scaling coefficient
328  */
329  Stencil<T> operator*(const T a_coef) const;
330 
331  /// In Place Stencil Composition
332  /**
333  \ingroup stencil_operations
334  \param a_stencil Another Stencil
335  */
336  void operator*=(const Stencil<T>& a_stencil);
337 
338  /// In Place Scalar Multiplication
339  void operator*=(const T a_coef);
340 
341  /// Stencil Addition
342  /**
343  \ingroup stencil_operations
344  Adding two Stencils results in a new Stencil which is the union of the coefficent-Shift pairs of the inputs.
345  If the two input Stencils share a common Shift, the associated coefficients will be added together.
346 
347  \param a_stencil Another Stencil
348  */
349  Stencil<T> operator+(const Stencil<T>& a_stencil) const;
350 
351  /// Stencil Subtraction (Convenience)
352  /**
353  \ingroup stencil_operations
354  Equivalent to adding <code> a_stencil*(-1) </code>
355 
356  \param a_stencil Another Stencil
357  */
358  Stencil<T> operator-(const Stencil<T>& a_stencil) const;
359 
360  /// In Place Stencil Addition
361  /**
362  \ingroup stencil_operations
363  \param a_stencil Another Stencil
364  */
365  void operator+=(const Stencil<T>& a_stencil);
366 
367  /// In Place Stencil Subtraction
368  /**
369  \ingroup stencil_operations
370  \param a_stencil Another Stencil
371  */
372  void operator-=(const Stencil<T>& a_stencil);
373 
374  ///@}
375 
376  ///////////////////////////////////////////////////////////////////////////////////////////////
377  /** @name Accessors and Queries*/
378  ///@{
379 
380  /// Get Vector of Coefficients
381  /**
382  \ingroup stencil_operations
383  Returned vector is read-only. Ordering corresponds to the output of Stencil::offsets()
384  */
385  inline const std::vector<T>& coefs() const {return m_coefs;};
386 
387  /// Get Vector of Coefficients (Primitive)
388  /**
389  @private
390  \ingroup stencil_operations
391  primitive version for testing purposes
392  CURRENTLY UNUSED?
393  */
394  //inline const T* devCoefs() const {return d_coeff;};
395 
396  /// Get Vector of Offsets
397  /**
398  \ingroup stencil_operations
399  Returned vector is read-only. Ordering corresponds to the output of Stencil::coefs()
400  */
401  inline const std::vector<Point>& offsets() const {return m_offsets;};
402 
403  /// Get Vector of Offsets
404  /**
405  @private
406  \ingroup stencil_operations
407  primitive version for testing purposes
408  CURRENTLY UNUSED?
409  */
410  //inline const Point* devOffsets() const {return d_offset;};
411 
412  /// Size
413  /**
414  \ingroup stencil_operations
415  Defined as the number of coefficient-offset pairs in the stencil
416  */
417  inline unsigned long long int size() const {return m_coefs.size();}
418 
419  /// Span
420  /**
421  \ingroup stencil_operations
422  Returns a Box which bounds all offsets in *this. Useful for automated ghost-cell checks.
423 
424  Example:
425  @code
426  //DIM = 2
427  using namespace Proto;
428  Stencil<T> S = 1.0*Shift(0,-1) +
429  2.0*Shift(0,2) +
430  3.0*Shift(1,3);
431  std::cout << S.span() << std::endl; //prints [(-1,0), (2,3)]
432  @endcode
433  */
434  inline Box span() const {return m_span;};
435 
436  /// Ghost
437  /**
438  Returns the span as a Point. Useful when interested only in isotropic ghost regions.
439  This function will always allow for *at least* the correct number of ghost cells, and will
440  overestimate in the case of non-isotropic spans.
441  */
442  inline Point ghost() const;
443 
444  /// Get Source Refinement Ratio
445  /**
446  \ingroup stencil_operations
447  */
448  inline Point& srcRatio(){return m_srcRefratio;};
449 
450  /// Get Source Refinement Ratio (Const)
451  /**
452  \ingroup stencil_operations
453  */
454  inline const Point& srcRatio() const {return m_srcRefratio;};
455 
456  /// Get Destination Refinement Ratio
457  /**
458  \ingroup stencil_operations
459  */
460  inline Point& destRatio(){return m_destRefratio;};
461 
462  /// Get Destination Refinement Ratio (Const)
463  /**
464  \ingroup stencil_operations
465  */
466  inline const Point& destRatio() const {return m_destRefratio;};
467 
468  /// Get Destination Shift
469  /**
470  \ingroup stencil_operations
471  */
472  inline Point& destShift(){return m_destShift;};
473 
474  /// Get Destination Shift (Const)
475  /**
476  \ingroup stencil_operations
477  */
478  inline const Point& destShift() const {return m_destShift;};
479 
480  /// Num Flops
481  /**
482  @private
483  Compute the number of FLOPS needed to evaluate this Stencil on the box <code>a_box</code>
484  */
485  inline unsigned long long int numFlops(const Box& a_box) const;
486 
487  /// Stencil Closed Query
488  /**
489  Ask if *this has been properly closed.
490  */
491  inline bool closed() const {return m_isClosed;}
492 
493  ///@}
494 
495  ///////////////////////////////////////////////////////////////////////////////////////////////
496  /** @name Stencil Binding and Application */
497  ///@{
498 
499  /// Operate on BoxData
500  /**
501  \ingroup stencil_operations
502  Operate *this on a BoxData. This function works in tandem with the namespace-defined
503  operators += and |=. See the example in the description of Stencil.
504 
505  \param a_scr Source BoxData
506  \param a_scale (Optional) Scale the output of the Stencil operation (Default: 1)
507  */
508  template<unsigned int C, MemType MEMTYPE, unsigned int D, unsigned int E>
509  inline LazyStencil <T,C,MEMTYPE,D,E>
510  operator()(const BoxData<T,C,MEMTYPE,D,E>& a_src, T a_scale = 1) const;
511 
512  /// Operate on BoxData (Overload with Box Input)
513  /**
514  \ingroup stencil_operations
515  Operate *this on a BoxData. This function works in tandem with the namespace-defined
516  operators += and |=. See the example in the description of Stencil.
517 
518  \param a_scr Source BoxData
519  \param a_box Confinement Box. Must be a subset of the allowable range of *this
520  \param a_scale (Optional) Scale the output of the Stencil operation (Default: 1)
521  */
522  template<unsigned int C, MemType MEMTYPE, unsigned int D, unsigned int E>
523  inline LazyStencil <T,C,MEMTYPE,D,E>
524  operator()(const BoxData<T,C,MEMTYPE,D,E>& a_src, Box a_box, T a_scale = 1) const;
525  ///@}
526 
527  ///////////////////////////////////////////////////////////////////////////////////////////////
528  /** @name Utility */
529  ///@{
530 
531  /// Invert Stencil
532  /**
533  \ingroup stencil_operations
534  Inverts the coefficients of this stencil across a given dimension.
535  */
536  inline void invert(int a_dir);
537 
538  /// Transpose Stencil
539  /**
540  \ingroup stencil_operations
541  Transposes *this across two directions in [0,DIM).
542  After transpose, coefficients associated with
543  the offset (a,...,b,...) will be associated instead with (b,...,a,...)
544  */
545  inline void transpose(unsigned int a, unsigned int b);
546 
547  /// Get Max Index Range
548  /**
549  @private
550  \ingroup stencil_operations
551  Given a domain, compute the largest possible iteration Box, taking source/ destination refinement into account.
552  For Stencils without source or destination refinement, this function is identical to Stencil::range.
553  This function is used primarily for Box inference and probably shouldn't be used publically.
554 
555  \param a_domain A computational domain
556  */
557  inline Box indexRange(Box a_domain) const;
558 
559  /// Get Max Index Domain
560  /**
561  @private
562  \ingroup stencil_operations
563  Given a domain, compute the largest possible iteration Box, taking source / destination refinement into account.
564  The output of this function is always a valid input for a Stencil operation.
565  For Stencils without source or destination refinement, this function is identical to Stencil::domain.
566  This function is used primarily for Box inference and probably shouldn't be used publically.
567 
568  \param a_range A computational range
569  */
570  inline Box indexDomain(Box a_range) const;
571 
572  /// Get Max Range Box
573  /**
574  \ingroup stencil_operations
575  Given a domain, compute the largest associated physical range, taking refinement AND destination shifting into account.
576  The output of this function is NOT a valid input for a Stencil operation when refinement is present.
577  This function is best used for defining output BoxData when the input domain is known.
578 
579  \param a_domain A computational domain
580  */
581  inline Box range(Box a_domain) const;
582 
583  /// Get Min Domain Box
584  /**
585  \ingroup stencil_operations
586  Given a range, compute the smallest associated physical domain, taking refinement AND destination shifting into account.
587  The output of this function is NOT a valid input for a Stencil operation when refinement is present.
588  This function is best used for defining input BoxData when the output range is known.
589 
590  \param a_range A computational range
591  */
592  inline Box domain(Box a_range) const;
593 
594  /// Get Diagonal Value
595  /**
596  \ingroup stencil_operations
597  Returns the coefficient multiplying the identity shift (0,0,...,0).
598  If *this doesn't contain the identity shift, returns 0.
599  */
600  T diagonal() const;
601 
602  /// Print
603  /**
604  \ingroup stencil_operations
605  Print *this to the command line. Useful for debugging.
606  */
607  inline void print() const;
608  ///@}
609 
610  // End of Stencil Operations Doxygen Module
611  /*@}*/
612 
613  /** @defgroup stencil_library Stencil Library*/
614  /*@{*/
615 
616  ///////////////////////////////////////////////////////////////////////////////////////////////
617  /** @name Stencil Library */
618  ///@{
619 
620  static Stencil<T> Identity() { return ((T)1.0)*Shift::Zeros(); }
621 
622  /// Stencil Library: Derivative
623  /**
624  Built in implementation of compact differentiation stencils.
625  Includes derivatives of order n >= 1 and accuracy m >= 2 where n + m <= 14.
626 
627  \param a_n Degree of derivative (e.g. nth derivative.)
628  \param a_dir Coordinate of differentiation. Must be in [0,DIM)
629  \param a_order (Optional) Order of accuracy. An unsigned int >= 2. Maximum accuracy depends on a_n. (Default: 2)
630  */
631  static Stencil<T> Derivative(int a_n, int a_dir, int a_order = 2);
632 
633  /// Stencil Library: Laplacian
634  /**
635  Built in implementation of the 2nd order 2*DIM + 1 point Laplace operator.
636  */
637  static Stencil<T> Laplacian();
638 #if DIM == 2
639  /// 9 Point Laplacian (Mehrstellen)
640  static Stencil<T> Laplacian_9();
641 #elif DIM == 3
642  /// 19 Point Laplacian (Mehrstellen)
643  static Stencil<T> Laplacian_19();
644  /// 27 Point Laplacian
645  static Stencil<T> Laplacian_27();
646 #endif
647  /// Stencil Library: Perpendicular Laplacian
648  /**
649  Built in implementation of Laplacian perpendicular to direction dir
650 
651  \param a_dir Normal direction
652  \param a_order (Optional) Order of accuracy (default: 2 | supported: 2)
653  */
654  static Stencil<T> LaplacianFace(int a_dir, int a_order = 2);
655 
656  #ifdef PR_LAPACK
657  static std::vector<double> ExtrapCoefs(const std::vector<double>& a_footprint, bool a_cellAverage = true);
658 
659  template<unsigned int C=1, MemType MEM=MEMTYPE_DEFAULT, unsigned int D=1, unsigned int E=1>
660  static void ExtrapIntoBoundary(BoxData<T, C, MEM, D, E>& data, Box interior, Point dir);
661  #endif
662 
663  /// Stencil Library: Cell to Face Interpolation
664  /**
665  Interpolates cell averaged values to face averaged values.
666  The <code>a_side</code> controls if the face averaged output is on the
667  upper or lower face of the cell at the center of the stencil.
668  For finer control of the Stencil's centering, see the functions
669  <code>CellToFaceL</code> and <code>CelltoFaceH</code>.
670 
671  \param a_dir Coordinate direction in [0, DIM)
672  \param a_side Upper or lower side (Side::Hi or Side::Lo) (default: Side::Lo)
673  \param a_order (Optional) Order of accuracy. Valid values (default 4 | supported: 4, 5)
674  */
675  static Stencil<T> CellToFace(
676  int a_dir,
677  Side::LoHiSide a_side = Side::Lo,
678  int a_order = 4);
679 
680  /// Stencil Library: Cell to Face Differentiation
681  /**
682  Computes the normal derivative of a cell-averaged quantity as a face-averaged quantity.
683 
684  \param dir Coordinate direction in [0, DIM)
685  \param side Upper or lower side (Side::Hi or Side::Lo) (default: Side::Lo)
686  \param order (Optional) Order of accuracy. Valid values (default 4 | supported: 4, 5)
687  */
688  static Stencil<T> DiffCellToFace(
689  int a_dir,
690  Side::LoHiSide a_side = Side::Lo,
691  int a_order = 4);
692 
693  /// Stencil Library: Upwind Cell to Face Interpolation
694  /**
695  Interpolates cell averaged values to face averaged values.
696  The <code>a_side</code> controls if the face averaged output is on the
697  upper or lower face of the cell at the center of the stencil.
698  For even orders, this function is identical to CellToFace.
699  For odd orders, the stencil is upwinded
700 
701  Example Stencil Footprints:
702  @code
703  // Legend | o: center stencil weight | ^: output location | x: other stencil weights
704  auto S4L = CellToFaceL(0, Side::Lo, 4);
705  // Footprint:
706  // | x | x | o | x |
707  // ^
708  auto S5L = CellToFaceL(0, Side::Lo, 5);
709  // Footprint:
710  // | x | x | x | o | x |
711  // ^
712  @endcode
713 
714  \param dir Coordinate direction in [0, DIM)
715  \param order (Optional) Order of accuracy. ( default: 4 | supported: 4, 5 )
716  */
717  static Stencil<T> CellToFaceL(
718  int a_dir,
719  int a_order = 4);
720 
721  /// Stencil Library: Upwind Cell to Face Interpolation
722  /**
723  Interpolates cell averaged values to face averaged values.
724  The <code>a_side</code> controls if the face averaged output is on the
725  upper or lower face of the cell at the center of the stencil.
726  For even orders, this function is identical to CellToFace.
727  For odd orders, the Stencil is downwinded.
728 
729  Example Stencil Footprints:
730  @code
731  // Legend | o: center stencil weight | ^: output location | x: other stencil weights
732  auto S4L = CellToFaceH(0, Side::Lo, 4);
733  // Footprint:
734  // | x | x | o | x |
735  // ^
736  auto S5L = CellToFaceH(0, Side::Lo, 5);
737  // Footprint:
738  // | x | x | o | x | x |
739  // ^
740  @endcode
741 
742  \param dir Coordinate direction in [0, DIM)
743  \param order (Optional) Order of accuracy. ( default: 4 | supported: 4, 5 )
744  */
745  static Stencil<T> CellToFaceH(
746  int a_dir,
747  int a_order = 4);
748 
749  /// Stencil Library: Simple Average
750  /**
751  Averages data from a refined grid onto a coarsened grid.
752  Refinement is assumed to be isotropic.
753  Source data is refined relative to the destination data by <code>a_refRatio</code>
754 
755  \param a_refRatio Refinement ratio.
756  */
757  static Stencil<T> AvgDown(int a_refRatio);
758 
759  /// Stencil Library: Anisotropic Average
760  /**
761  Anisotropic overload of <code>AvgDown</code>.
762 
763  \param a_refRatio Refinement ratio
764  */
765  static Stencil<T> AvgDown(Point a_refRatio);
766 
767  /// Stencil Library: Sum
768  /**
769  Undivided average (e.g. the sum of all elements).
770  Source data is refined relative to the destination data by <code>a_refRatio</code>
771 
772  \param a_refRatio Refinement ratio
773  */
774  static Stencil<T> Sum(int a_refRatio);
775 
776  /// Stencil Library: Sum
777  /**
778  Anisotropic overload of <code>Sum</code>.
779 
780  \param a_refRatio Refinement ratio
781  */
782  static Stencil<T> Sum(Point a_refRatio);
783 
784  //TODO: I don't think this does the right thing for Side::Hi. Needs better description.
785  /// Stencil Library: Simple Average over a Face
786  /**
787  Averaging operation between face-averaged data sets with normal <code>a_normDir</code>.
788 
789  \param a_normDir Normal coordinate direction
790  \param a_side Cell side to average over
791  \param a_refRatio Non-normal coordinate refinement ratios
792  */
793  static Stencil<T> AvgDownFace(int a_normDir, Side::LoHiSide a_side, int a_refRatio);
794 
795  //TODO: I don't think this does the right thing for Side::Hi. Needs better description.
796  /// Stencil Library: Simple Average over a Face
797  /**
798  Averaging operation between face-averaged data sets with normal <code>a_normDir</code>.
799 
800  \param a_normDir Normal coordinate direction
801  \param a_side Cell side to average over
802  \param a_refRatio Non-normal coordinate refinement ratios
803  */
804  static Stencil<T> AvgDownFace(int a_dir, Side::LoHiSide a_side, Point a_refRatio);
805 
806  //TODO: Give this a Side::LoHiSide argument so it can handle high-sided fluxes
807  /// Stencil Library: Flux Divergence
808  /**
809  Simple flux differencing stencil: OUT(i) = IN(i+1) - IN(i)
810  Assumes the low-side fluxes are stored in cell i.
811 
812  \param a_dir Coordinate axis in the flux normal direction.
813  */
814  static Stencil<T> FluxDivergence(int a_dir);
815  /// Interpolate from face average to cell average.
816  static Stencil<T> faceToCell(int a_dir,int a_order = 4);
817  /// Interpolate from corners to face average.
818  static Stencil<T> cornersToFaces(int a_dir,int a_order = 4);
819  /// Interpolate from corners to cell average.
820  static Stencil<T> CornersToCells(int a_order = 4);
821  ///@}
822 
823  // End of Stencil Operations Doxygen Module
824  /*@}*/
825 
826 
827  ///////////////////////////////////////////////////////////////////////////////////////////////
828  //TODO: Functional syntax convension is (output, inputs...)
829  /// Apply Stencil Helper function
830  /**
831  \ingroup stencil_operations
832  Manually apply *this to a source and destination BoxData in a functional programming style.
833  Not recommended for public use, but useful for debugging in some cases.
834 
835  \param a_src Source data
836  \param a_dest Output data
837  \param a_bx Iteration box for this computation. Can be created with indexDomain or indexRange functions.
838  \param a_replace (Optional) If true, zero out the data in a_dest and replace with the computation result. If true, solution will be added to existing data. Default false.
839  \param a_scale (Optional) Scale the computation by some value.
840  */
841  template<unsigned int C, MemType MEMTYPE, unsigned int D, unsigned int E>
842  void apply(
843  const BoxData<T,C,MEMTYPE,D,E>& a_src,
844  BoxData<T,C,MEMTYPE,D,E>& a_dest,
845  const Box& a_bx,
846  bool a_initToZero = false,
847  const T a_scale = 1) const;
848 
849  //TODO: Documentation
850  template<unsigned int C, unsigned int D, unsigned int E>
851  void protoApply(
852  const BoxData<T,C,HOST,D,E>& a_src,
853  BoxData<T,C,HOST,D,E>& a_dst,
854  const Box& a_box,
855  bool a_initToZero = false,
856  T a_scale = 1);
857 
858  //TODO: Documentation
859  template<unsigned int C, unsigned int D, unsigned int E>
860  void protoApply(
861  const BoxData<T,C,DEVICE,D,E>& a_src,
863  const Box& a_box,
864  bool a_initToZero = false,
865  T a_scale = 1);
866 
867  //TODO: Documentation
868  template<unsigned int C, unsigned int D, unsigned int E>
869  void hostApply( const BoxData<T,C,MemType::HOST,D,E>& a_src,
871  const Box& a_box,
872  bool a_initToZero = false,
873  T a_scale = 1) const;
874 
875  private:
876  /// Add Coefficient-Offset Pair
877  /**
878  @private
879  Helper function that encapsulates all of the proper checks needed
880  to add a coefficient-offset pair to a Stencil. Any new function
881  that needs to add data to an existing Stencil should call this.
882  */
883  void addCoef(T a_coef, Point a_offset);
884 
885  // Helper object for device Stencils
886  /* Appears to be unused. -CLG 4/19/2022
887  struct coeff_holder
888  {
889  T elements[64];
890  };
891  */
892  //Must be called before computations can be performed on the device
893  inline void closeForDevice();
894 
895  std::vector<T> m_coefs; ///< Coefficients of the Stencil.
896  std::vector<Point> m_offsets; ///< Offsets associated with the Stencil.
897  Point m_srcRefratio; ///< Refinement of source data
898  Point m_destRefratio; ///< Refinement of destination data
899  Point m_destShift; ///< Output shift in (refined) destination data. Meaningless without destination refinement
900  Box m_span; ///< Bounding Box defining the largest offsets of *this. Defines Stencil's spatial footprint
901 
903 #ifdef PROTO_ACCEL
904  //this copies to the device
905  T* d_coeff;
906  Point* d_offset;
907 #endif
908  // Appears to be unused. -CLG 4/19/2022
909  //Stencil<T>::coeff_holder c_coeff;
910  }; // end class Stencil
911 
912 ///////////////////////////////////////////////////////////////////////////////////////////////
913 /** @name Non-Member Functions */
914 ///@{
915 
916 /// Coefficient Shift Product "Constructor"
917 /**
918  \ingroup stencil_operations
919  Syntactical sugar that allows a Stencil to be constructed with coef*Shift(Point) syntax
920 
921  Example:
922  @code
923  Stencil<double> S = 3.7*Shift(Point::Basis(0));
924  @endcode
925 */
926 template <typename T>
927 inline Stencil<T> operator*(T a_coef, Shift a_shift) { return Stencil<T>(a_shift, a_coef); }
928 
929 /// Scalar Multiplication of Stencil Coefficients
930 /**
931  \ingroup stencil_operations
932  Allows for pre multiplication by a T scalar
933 */
934 template <typename T>
935 inline Stencil<T> operator*(T a_coef, const Stencil<T> a_stencil) { return a_stencil*a_coef; }
936 
937 /// Stencil Unary Negation
938 /**
939  \ingroup stencil_operations
940 */
941 template <typename T>
942 inline Stencil<T> operator-(Stencil<T> a_stencil) { return a_stencil*(-1); }
943 
944 /// Application by Replacement
945 /**
946  \ingroup stencil_operations
947  Applies a Stencil and REPLACES a subset of a_dest with the result:
948 
949  Usage:
950  @code
951  Stencil<double> L = Stencil<double>::Laplacian(); //2*DIM+1 point Laplacian operator
952  Box rangeBox = Box::Cube(64); //define the data range
953  Box domainBox = L.domain(rangeBox); //compute the domain from the range
954  BoxData<double> Src(domainBox);
955  BoxData<double> Dst(rangeBox);
956  // ... initialize Src ...
957  Dst |= L(Src);
958  // NB: This call computes the Laplacian of Src and replaces the values of Dst
959  // inside rangeBox with the result. Only the cells in rangeBox & Dst.box()
960  // are affected. If rangeBox & Dst.box() is empty, |= is a null-op.
961  @endcode
962 
963  TODO: These examples are missing.
964  See the main documentation for Stencil for additional examples
965 
966  \param a_dest Destination array
967  \param a_op Uncomputed Stencil operation (output of Stencil::operator())
968 */
969 template <typename T, unsigned int C, MemType MEMTYPE, unsigned int D, unsigned int E>
971  BoxData<T,C,MEMTYPE,D,E>& a_dest,
972  LazyStencil<T,C,MEMTYPE,D,E>&& a_op);
973 
974 /// Application by Increment
975 /**
976  \ingroup stencil_operations
977  Applies a Stencil and ADDS a subset of a_dest with the result
978 
979  Usage:
980  @code
981  Stencil<double> L = Stencil<double>::Laplacian(); //2*DIM+1 point Laplacian operator
982  Box rangeBox = Box::Cube(64); //define the data range
983  Box domainBox = L.domain(rangeBox); //compute the domain from the range
984  BoxData<double> Src(domainBox);
985  BoxData<double> Dst(rangeBox);
986  // ... initialize Src ...
987  Dst += L(Src);
988  // NB: This call computes the Laplacian of Src and addds the values of Dst
989  // inside rangeBox with the result. Only the cells in rangeBox & Dst.box()
990  // are affected. If rangeBox & Dst.box() is empty, |= is a null-op.
991  @endcode
992 
993  TODO: These examples are missing.
994  See the main documentation for Stencil for additional examples
995 
996  \param a_dest Destination array
997  \param a_op Uncomputed Stencil operation (output of Stencil::operator())
998 */
999 template <class T, unsigned int C, MemType MEMTYPE, unsigned int D, unsigned int E>
1000 BoxData<T,C,MEMTYPE,D,E>& operator+=(BoxData<T,C,MEMTYPE,D,E>& a_dest, LazyStencil<T,C,MEMTYPE,D,E>&& a_op);
1001 
1002 ///@}
1003 } //end Proto namespace
1004 #endif
unsigned long long int size() const
Get Vector of Offsets.
Definition: Proto_Stencil.H:417
Stencil Shift.
Definition: Proto_Stencil.H:46
static Shift Basis(int a_dir, int a_scale=1)
Basis Shift.
Definition: Proto_Stencil.H:89
LoHiSide
Side Enum.
Definition: Proto_Face.H:23
Point m_srcRefratio
Refinement of source data.
Definition: Proto_Stencil.H:897
Point & destShift()
Get Destination Shift.
Definition: Proto_Stencil.H:472
bool m_isClosed
Definition: Proto_Stencil.H:902
Multidimensional Rectangular Array.
Definition: Proto_BoxData.H:314
Low side; normal is in negative coordinate direction.
Definition: Proto_Face.H:26
Stencil< T > operator*(T a_coef) const
Scalar Multiplication.
Definition: Proto_Stencil.H:137
Point & srcRatio()
Get Source Refinement Ratio.
Definition: Proto_Stencil.H:448
Definition: Proto_Reduction.H:15
Point & destRatio()
Get Destination Refinement Ratio.
Definition: Proto_Stencil.H:460
A Linear Stencil Operation.
Definition: Proto_BoxData.H:76
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:94
const std::vector< Point > & offsets() const
Get Vector of Coefficients (Primitive)
Definition: Proto_Stencil.H:401
static ACCEL_DECORATION Point Basis(int a_dir, int a_scale=1)
Get Basis.
Point m_destShift
Output shift in (refined) destination data. Meaningless without destination refinement.
Definition: Proto_Stencil.H:899
An interval in DIM dimensional space.
Definition: Proto_Box.H:29
const Point & srcRatio() const
Get Source Refinement Ratio (Const)
Definition: Proto_Stencil.H:454
static Shift Zeros()
Zero Shift.
Definition: Proto_Stencil.H:96
const Point & destShift() const
Get Destination Shift (Const)
Definition: Proto_Stencil.H:478
bool operator!=(const Stencil< T > &a_stencil) const
Inquality Operator.
Definition: Proto_Stencil.H:310
Shift(const Point &a_pt)
Point Constructor.
Definition: Proto_Stencil.H:63
Box m_span
Bounding Box defining the largest offsets of *this. Defines Stencil&#39;s spatial footprint.
Definition: Proto_Stencil.H:900
static Stencil< T > Identity()
Definition: Proto_Stencil.H:620
int & operator[](int a_dir)
Componentwise Access.
Definition: Proto_Stencil.H:149
static Shift Y(int scale=1)
Definition: Proto_Stencil.H:108
static Shift Z(int scale=1)
Definition: Proto_Stencil.H:109
static ACCEL_DECORATION Point X()
Definition: Proto_Point.H:144
MBPoint operator+(const MBPoint &mbpoint, const Point &p)
Definition: Proto_MBProblemDomain.H:55
#define PROTO_ASSERT(stmt, args...)
Definition: Proto_PAssert.H:48
static ACCEL_DECORATION Point Ones(int a_scale=1)
Get Ones.
Point m_shift
Definition: Proto_Stencil.H:162
static ACCEL_DECORATION Point Y()
Definition: Proto_Point.H:145
const std::vector< T > & coefs() const
Get Vector of Coefficients.
Definition: Proto_Stencil.H:385
Box span() const
Span.
Definition: Proto_Stencil.H:434
static ACCEL_DECORATION Point Z()
Definition: Proto_Point.H:146
static ACCEL_DECORATION Point Zeros()
Get Zeros.
Definition: Proto_Array.H:17
Integer Valued Vector.
Definition: Proto_Point.H:24
static Shift Ones(int a_scale=1)
Unit Shift.
Definition: Proto_Stencil.H:105
ACCEL_DECORATION Array< T, N > & operator-(Array< T, N > &arr)
Unary negation.
const Point & destRatio() const
Get Destination Refinement Ratio (Const)
Definition: Proto_Stencil.H:466
std::vector< Point > m_offsets
Offsets associated with the Stencil.
Definition: Proto_Stencil.H:896
Shift()
Default Constructor.
Definition: Proto_Stencil.H:54
Point dir
Definition: Proto_MBBoxPartition.H:16
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
Shift operator*(const Shift &a_shift) const
Convolution.
Definition: Proto_Stencil.H:146
Shift(vals... args)
Variadic Constructor.
Definition: Proto_Stencil.H:74
Point m_destRefratio
Refinement of destination data.
Definition: Proto_Stencil.H:898
Point & point()
Get Shift Point.
Definition: Proto_Stencil.H:112
std::vector< T > m_coefs
Coefficients of the Stencil.
Definition: Proto_Stencil.H:895
static Shift X(int scale=1)
Definition: Proto_Stencil.H:107
bool closed() const
Stencil Closed Query.
Definition: Proto_Stencil.H:491