ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_AdvectionSrcForScalars.H
Go to the documentation of this file.
1 #ifndef ERF_ADVECTION_SRC_FOR_SCALARS_H_
2 #define ERF_ADVECTION_SRC_FOR_SCALARS_H_
3 
4 #include <AMReX.H>
5 
6 #include <ERF_IndexDefines.H>
7 #include <ERF_Interpolation.H>
8 
9 /**
10  * Build scalar face fluxes with a selected pair of interpolation policies.
11  *
12  * @tparam InterpType_H horizontal interpolation type
13  * @tparam InterpType_V vertical interpolation type
14  * @param[in] bx cell-centered box over which scalar fluxes are computed
15  * @param[in] scalar supplied cell-centered scalar view
16  * @param[in] scalar_comp component of the supplied scalar view to reconstruct
17  * @param[out] flx_arr face-flux views
18  * @param[in] flux_comp component of the supplied face-flux views to write
19  * @param[in] avg_xmom x-component of time-averaged mass flux
20  * @param[in] avg_ymom y-component of time-averaged mass flux
21  * @param[in] avg_zmom z-component of time-averaged mass flux
22  * @param[in] horiz_upw_frac horizontal upwind blending fraction
23  * @param[in] vert_upw_frac vertical upwind blending fraction
24  */
25 template<typename InterpType_H, typename InterpType_V>
26 inline void
28  const amrex::Box& bx,
29  const amrex::Array4<const amrex::Real>& scalar,
30  const int scalar_comp,
31  const amrex::GpuArray<const amrex::Array4<amrex::Real>, AMREX_SPACEDIM>& flx_arr,
32  const int flux_comp,
33  const amrex::Array4<const amrex::Real>& avg_xmom,
34  const amrex::Array4<const amrex::Real>& avg_ymom,
35  const amrex::Array4<const amrex::Real>& avg_zmom,
36  const amrex::Real horiz_upw_frac,
37  const amrex::Real vert_upw_frac)
38 {
39  InterpType_H interp_h(scalar, horiz_upw_frac);
40  InterpType_V interp_v(scalar, vert_upw_frac);
41 
42  const amrex::Box xbx = amrex::surroundingNodes(bx,0);
43  const amrex::Box ybx = amrex::surroundingNodes(bx,1);
44  const amrex::Box zbx = amrex::surroundingNodes(bx,2);
45 
46  amrex::ParallelFor(xbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
47  {
48  amrex::Real interpx(zero);
49  interp_h.InterpolateInX(i,j,k,scalar_comp,interpx,avg_xmom(i,j,k));
50  flx_arr[0](i,j,k,flux_comp) = avg_xmom(i,j,k) * interpx;
51  });
52  amrex::ParallelFor(ybx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
53  {
54  amrex::Real interpy(zero);
55  interp_h.InterpolateInY(i,j,k,scalar_comp,interpy,avg_ymom(i,j,k));
56  flx_arr[1](i,j,k,flux_comp) = avg_ymom(i,j,k) * interpy;
57  });
58  amrex::ParallelFor(zbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
59  {
60  amrex::Real interpz(zero);
61  interp_v.InterpolateInZ(i,j,k,scalar_comp,interpz,avg_zmom(i,j,k));
62  flx_arr[2](i,j,k,flux_comp) = avg_zmom(i,j,k) * interpz;
63  });
64 }
65 
66 /**
67  * Build centered-second-order scalar face fluxes without a reconstruction temporary.
68  *
69  * @param[in] bx cell-centered box over which scalar fluxes are computed
70  * @param[in] scalar supplied cell-centered scalar view
71  * @param[in] scalar_comp component of the supplied scalar view to reconstruct
72  * @param[out] flx_arr face-flux views
73  * @param[in] flux_comp component of the supplied face-flux views to write
74  * @param[in] avg_xmom x-component of time-averaged mass flux
75  * @param[in] avg_ymom y-component of time-averaged mass flux
76  * @param[in] avg_zmom z-component of time-averaged mass flux
77  */
78 inline void
80  const amrex::Box& bx,
81  const amrex::Array4<const amrex::Real>& scalar,
82  const int scalar_comp,
83  const amrex::GpuArray<const amrex::Array4<amrex::Real>, AMREX_SPACEDIM>& flx_arr,
84  const int flux_comp,
85  const amrex::Array4<const amrex::Real>& avg_xmom,
86  const amrex::Array4<const amrex::Real>& avg_ymom,
87  const amrex::Array4<const amrex::Real>& avg_zmom)
88 {
89  const amrex::Box xbx = amrex::surroundingNodes(bx,0);
90  const amrex::Box ybx = amrex::surroundingNodes(bx,1);
91  const amrex::Box zbx = amrex::surroundingNodes(bx,2);
92 
93  amrex::ParallelFor(xbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
94  {
95  const amrex::Real scalar_on_face = myhalf *
96  (scalar(i,j,k,scalar_comp) + scalar(i-1,j,k,scalar_comp));
97  flx_arr[0](i,j,k,flux_comp) = avg_xmom(i,j,k) * scalar_on_face;
98  });
99  amrex::ParallelFor(ybx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
100  {
101  const amrex::Real scalar_on_face = myhalf *
102  (scalar(i,j,k,scalar_comp) + scalar(i,j-1,k,scalar_comp));
103  flx_arr[1](i,j,k,flux_comp) = avg_ymom(i,j,k) * scalar_on_face;
104  });
105  amrex::ParallelFor(zbx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
106  {
107  const amrex::Real scalar_on_face = myhalf *
108  (scalar(i,j,k,scalar_comp) + scalar(i,j,k-1,scalar_comp));
109  flx_arr[2](i,j,k,flux_comp) = avg_zmom(i,j,k) * scalar_on_face;
110  });
111 }
112 
113 /**
114  * Dispatch scalar face-flux construction for a selected vertical scheme.
115  *
116  * @tparam InterpType_H horizontal interpolation type
117  * @param[in] bx cell-centered box over which scalar fluxes are computed
118  * @param[in] scalar supplied scalar view
119  * @param[in] scalar_comp component of the supplied scalar view to reconstruct
120  * @param[out] flx_arr face-flux views
121  * @param[in] flux_comp component of the supplied face-flux views to write
122  * @param[in] avg_xmom x-component of time-averaged mass flux
123  * @param[in] avg_ymom y-component of time-averaged mass flux
124  * @param[in] avg_zmom z-component of time-averaged mass flux
125  * @param[in] horiz_upw_frac horizontal upwind blending fraction
126  * @param[in] vert_upw_frac vertical upwind blending fraction
127  * @param[in] vert_adv_type vertical advection scheme
128  */
129 template<typename InterpType_H>
130 inline void
132  const amrex::Box& bx,
133  const amrex::Array4<const amrex::Real>& scalar,
134  const int scalar_comp,
135  const amrex::GpuArray<const amrex::Array4<amrex::Real>, AMREX_SPACEDIM>& flx_arr,
136  const int flux_comp,
137  const amrex::Array4<const amrex::Real>& avg_xmom,
138  const amrex::Array4<const amrex::Real>& avg_ymom,
139  const amrex::Array4<const amrex::Real>& avg_zmom,
140  const amrex::Real horiz_upw_frac,
141  const amrex::Real vert_upw_frac,
142  const AdvType vert_adv_type)
143 {
144  switch (vert_adv_type) {
146  BuildScalarAdvectionFluxesWithPolicy<InterpType_H,CENTERED2>(
147  bx, scalar, scalar_comp, flx_arr, flux_comp,
148  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
149  break;
150  case AdvType::Upwind_3rd:
151  BuildScalarAdvectionFluxesWithPolicy<InterpType_H,UPWIND3>(
152  bx, scalar, scalar_comp, flx_arr, flux_comp,
153  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
154  break;
156  BuildScalarAdvectionFluxesWithPolicy<InterpType_H,UPWIND3SL>(
157  bx, scalar, scalar_comp, flx_arr, flux_comp,
158  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
159  break;
161  BuildScalarAdvectionFluxesWithPolicy<InterpType_H,CENTERED4>(
162  bx, scalar, scalar_comp, flx_arr, flux_comp,
163  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
164  break;
165  case AdvType::Upwind_5th:
166  BuildScalarAdvectionFluxesWithPolicy<InterpType_H,UPWIND5>(
167  bx, scalar, scalar_comp, flx_arr, flux_comp,
168  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
169  break;
171  BuildScalarAdvectionFluxesWithPolicy<InterpType_H,CENTERED6>(
172  bx, scalar, scalar_comp, flx_arr, flux_comp,
173  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
174  break;
175  default:
176  // Not an assert: under NDEBUG that would compile away and leave the
177  // face fluxes unwritten, so the divergence below would silently
178  // consume whatever stale data is in this flux component. Note that
179  // the WENO schemes have no vertical-only variant -- they must be
180  // selected for both the horizontal and the vertical direction.
181  amrex::Abort("Unknown or unsupported vertical advection scheme!");
182  }
183 }
184 
185 /**
186  * Build scalar face fluxes using ERF's compile-time interpolation policies.
187  * WENO schemes intentionally use the same policy horizontally and vertically,
188  * matching the existing native scalar-advection dispatch.
189  *
190  * @param[in] bx cell-centered box over which scalar fluxes are computed
191  * @param[in] scalar supplied cell-centered scalar view
192  * @param[in] scalar_comp component of the supplied scalar view to reconstruct
193  * @param[out] flx_arr face-flux views
194  * @param[in] flux_comp component of the supplied face-flux views to write
195  * @param[in] avg_xmom x-component of time-averaged mass flux
196  * @param[in] avg_ymom y-component of time-averaged mass flux
197  * @param[in] avg_zmom z-component of time-averaged mass flux
198  * @param[in] horiz_adv_type horizontal advection scheme
199  * @param[in] vert_adv_type vertical advection scheme
200  * @param[in] horiz_upw_frac horizontal upwind blending fraction
201  * @param[in] vert_upw_frac vertical upwind blending fraction
202  */
203 inline void
205  const amrex::Box& bx,
206  const amrex::Array4<const amrex::Real>& scalar,
207  const int scalar_comp,
208  const amrex::GpuArray<const amrex::Array4<amrex::Real>, AMREX_SPACEDIM>& flx_arr,
209  const int flux_comp,
210  const amrex::Array4<const amrex::Real>& avg_xmom,
211  const amrex::Array4<const amrex::Real>& avg_ymom,
212  const amrex::Array4<const amrex::Real>& avg_zmom,
213  const AdvType horiz_adv_type,
214  const AdvType vert_adv_type,
215  const amrex::Real horiz_upw_frac,
216  const amrex::Real vert_upw_frac)
217 {
218  if (horiz_adv_type == AdvType::Centered_2nd &&
219  vert_adv_type == AdvType::Centered_2nd) {
221  bx, scalar, scalar_comp, flx_arr, flux_comp,
222  avg_xmom, avg_ymom, avg_zmom);
223  return;
224  }
225 
226  switch (horiz_adv_type) {
228  BuildScalarAdvectionFluxesVert<CENTERED2>(
229  bx, scalar, scalar_comp, flx_arr, flux_comp,
230  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac, vert_adv_type);
231  break;
232  case AdvType::Upwind_3rd:
233  BuildScalarAdvectionFluxesVert<UPWIND3>(
234  bx, scalar, scalar_comp, flx_arr, flux_comp,
235  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac, vert_adv_type);
236  break;
238  BuildScalarAdvectionFluxesVert<UPWIND3SL>(
239  bx, scalar, scalar_comp, flx_arr, flux_comp,
240  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac, vert_adv_type);
241  break;
243  BuildScalarAdvectionFluxesVert<CENTERED4>(
244  bx, scalar, scalar_comp, flx_arr, flux_comp,
245  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac, vert_adv_type);
246  break;
247  case AdvType::Upwind_5th:
248  BuildScalarAdvectionFluxesVert<UPWIND5>(
249  bx, scalar, scalar_comp, flx_arr, flux_comp,
250  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac, vert_adv_type);
251  break;
253  BuildScalarAdvectionFluxesVert<CENTERED6>(
254  bx, scalar, scalar_comp, flx_arr, flux_comp,
255  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac, vert_adv_type);
256  break;
257  case AdvType::Weno_3:
258  BuildScalarAdvectionFluxesWithPolicy<WENO3,WENO3>(
259  bx, scalar, scalar_comp, flx_arr, flux_comp,
260  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
261  break;
262  case AdvType::Weno_5:
263  BuildScalarAdvectionFluxesWithPolicy<WENO5,WENO5>(
264  bx, scalar, scalar_comp, flx_arr, flux_comp,
265  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
266  break;
267  case AdvType::Weno_7:
268  BuildScalarAdvectionFluxesWithPolicy<WENO7,WENO7>(
269  bx, scalar, scalar_comp, flx_arr, flux_comp,
270  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
271  break;
272  case AdvType::Weno_3Z:
273  BuildScalarAdvectionFluxesWithPolicy<WENO_Z3,WENO_Z3>(
274  bx, scalar, scalar_comp, flx_arr, flux_comp,
275  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
276  break;
277  case AdvType::Weno_3MZQ:
278  BuildScalarAdvectionFluxesWithPolicy<WENO_MZQ3,WENO_MZQ3>(
279  bx, scalar, scalar_comp, flx_arr, flux_comp,
280  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
281  break;
282  case AdvType::Weno_5Z:
283  BuildScalarAdvectionFluxesWithPolicy<WENO_Z5,WENO_Z5>(
284  bx, scalar, scalar_comp, flx_arr, flux_comp,
285  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
286  break;
287  case AdvType::Weno_7Z:
288  BuildScalarAdvectionFluxesWithPolicy<WENO_Z7,WENO_Z7>(
289  bx, scalar, scalar_comp, flx_arr, flux_comp,
290  avg_xmom, avg_ymom, avg_zmom, horiz_upw_frac, vert_upw_frac);
291  break;
292  default:
293  // See the note in BuildScalarAdvectionFluxesVert: an assert here would
294  // vanish under NDEBUG and leave stale fluxes in place of an error.
295  amrex::Abort("Unknown horizontal advection scheme!");
296  }
297 }
298 
299 /**
300  * Apply the mapped divergence of component-selected scalar face fluxes.
301  *
302  * @param[in] bx cell-centered box over which the tendency is computed
303  * @param[in] flx_arr face-flux views
304  * @param[in] flux_comp component of the supplied face-flux views to read
305  * @param[out] rhs supplied tendency view
306  * @param[in] rhs_comp component of the supplied tendency view to write
307  * @param[in] detJ metric Jacobian
308  * @param[in] cellSizeInv inverse grid spacing
309  * @param[in] mf_mx x map factor at cell centers
310  * @param[in] mf_my y map factor at cell centers
311  */
312 inline void
314  const amrex::Box& bx,
315  const amrex::GpuArray<const amrex::Array4<amrex::Real>, AMREX_SPACEDIM>& flx_arr,
316  const int flux_comp,
317  const amrex::Array4<amrex::Real>& rhs,
318  const int rhs_comp,
319  const amrex::Array4<const amrex::Real>& detJ,
320  const amrex::GpuArray<amrex::Real, AMREX_SPACEDIM>& cellSizeInv,
321  const amrex::Array4<const amrex::Real>& mf_mx,
322  const amrex::Array4<const amrex::Real>& mf_my)
323 {
324  const auto dxInv = cellSizeInv[0];
325  const auto dyInv = cellSizeInv[1];
326  const auto dzInv = cellSizeInv[2];
327 
328  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
329  {
330  if (detJ(i,j,k) > zero) {
331  const amrex::Real invdetJ = one / detJ(i,j,k);
332  const amrex::Real mfsq = mf_mx(i,j,0) * mf_my(i,j,0);
333  rhs(i,j,k,rhs_comp) = - invdetJ * mfsq * (
334  (flx_arr[0](i+1,j,k,flux_comp) - flx_arr[0](i,j,k,flux_comp)) * dxInv +
335  (flx_arr[1](i,j+1,k,flux_comp) - flx_arr[1](i,j,k,flux_comp)) * dyInv +
336  (flx_arr[2](i,j,k+1,flux_comp) - flx_arr[2](i,j,k,flux_comp)) * dzInv);
337  } else {
338  rhs(i,j,k,rhs_comp) = zero;
339  }
340  });
341 }
342 
343 #endif // ERF_ADVECTION_SRC_FOR_SCALARS_H_
void BuildScalarAdvectionFluxesCentered2(const amrex::Box &bx, const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::GpuArray< const amrex::Array4< amrex::Real >, AMREX_SPACEDIM > &flx_arr, const int flux_comp, const amrex::Array4< const amrex::Real > &avg_xmom, const amrex::Array4< const amrex::Real > &avg_ymom, const amrex::Array4< const amrex::Real > &avg_zmom)
Definition: ERF_AdvectionSrcForScalars.H:79
void BuildScalarAdvectionFluxes(const amrex::Box &bx, const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::GpuArray< const amrex::Array4< amrex::Real >, AMREX_SPACEDIM > &flx_arr, const int flux_comp, const amrex::Array4< const amrex::Real > &avg_xmom, const amrex::Array4< const amrex::Real > &avg_ymom, const amrex::Array4< const amrex::Real > &avg_zmom, const AdvType horiz_adv_type, const AdvType vert_adv_type, const amrex::Real horiz_upw_frac, const amrex::Real vert_upw_frac)
Definition: ERF_AdvectionSrcForScalars.H:204
void BuildScalarAdvectionFluxesWithPolicy(const amrex::Box &bx, const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::GpuArray< const amrex::Array4< amrex::Real >, AMREX_SPACEDIM > &flx_arr, const int flux_comp, const amrex::Array4< const amrex::Real > &avg_xmom, const amrex::Array4< const amrex::Real > &avg_ymom, const amrex::Array4< const amrex::Real > &avg_zmom, const amrex::Real horiz_upw_frac, const amrex::Real vert_upw_frac)
Definition: ERF_AdvectionSrcForScalars.H:27
void ApplyScalarAdvectionFluxDivergence(const amrex::Box &bx, const amrex::GpuArray< const amrex::Array4< amrex::Real >, AMREX_SPACEDIM > &flx_arr, const int flux_comp, const amrex::Array4< amrex::Real > &rhs, const int rhs_comp, const amrex::Array4< const amrex::Real > &detJ, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &cellSizeInv, const amrex::Array4< const amrex::Real > &mf_mx, const amrex::Array4< const amrex::Real > &mf_my)
Definition: ERF_AdvectionSrcForScalars.H:313
void BuildScalarAdvectionFluxesVert(const amrex::Box &bx, const amrex::Array4< const amrex::Real > &scalar, const int scalar_comp, const amrex::GpuArray< const amrex::Array4< amrex::Real >, AMREX_SPACEDIM > &flx_arr, const int flux_comp, const amrex::Array4< const amrex::Real > &avg_xmom, const amrex::Array4< const amrex::Real > &avg_ymom, const amrex::Array4< const amrex::Real > &avg_zmom, const amrex::Real horiz_upw_frac, const amrex::Real vert_upw_frac, const AdvType vert_adv_type)
Definition: ERF_AdvectionSrcForScalars.H:131
AdvType
Definition: ERF_IndexDefines.H:309
@ Upwind_3rd_SL
@ Centered_4th
@ Centered_6th
@ Centered_2nd
amrex::GpuArray< Real, AMREX_SPACEDIM > dxInv
Definition: ERF_InitCustomPertVels_ParticleTests.H:17
ParallelFor(fab_box, [=] AMREX_GPU_DEVICE(int i, int j, int k) { qrcuten_arr(i, j, k)=Real(0);qscuten_arr(i, j, k)=Real(0);qicuten_arr(i, j, k)=Real(0);})
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:30
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:29
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:34
amrex::Real Real
Definition: ERF_ShocInterface.H:19