ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_EBSlopes.H
Go to the documentation of this file.
1 /**
2  * \file ERF_EBSlopes.H
3  * \brief Provides least-squares slope reconstruction helpers near EB cut cells.
4  */
5 #ifndef ERF_EBSLOPES_H_
6 #define ERF_EBSLOPES_H_
7 
8 #include <AMReX_EBCellFlag.H>
9 #include <AMReX_EB_Slopes_K.H>
10 #include <ERF_IndexDefines.H>
11 
12 /**
13  * \brief Compute least-squares slopes using EB Dirichlet data.
14  *
15  * @param[in] dx Mesh spacing in x.
16  * @param[in] dy Mesh spacing in y.
17  * @param[in] dz Mesh spacing in z.
18  * @param[in] i Cell index in x.
19  * @param[in] j Cell index in y.
20  * @param[in] k Cell index in z.
21  * @param[in] bcent_eb EB boundary centroid.
22  * @param[in] state_eb Dirichlet state at the EB boundary.
23  * @param[in] state Cell-centered state array.
24  * @param[in] ccent Cell centroid coordinates.
25  * @param[in] flag Cell-centered EB flags and connectivity.
26  */
27 AMREX_GPU_DEVICE AMREX_FORCE_INLINE
28 amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>
31  int i, int j, int k,
32  amrex::RealVect const& bcent_eb,
33  amrex::Real const state_eb,
34  amrex::Array4<amrex::Real const> const& state,
35  amrex::Array4<amrex::Real const> const& ccent,
36  amrex::Array4<amrex::EBCellFlag const> const& flag)
37 {
38  amrex::EBSlopeNormalEquation normal_eq;
39 
40  // Prevent loop unrolling to reduce register pressure.
41 #ifdef AMREX_USE_GPU
42 #pragma unroll 1
43 #endif
44  for (int kk = -1; kk <= 1; ++kk) {
45 #ifdef AMREX_USE_GPU
46 #pragma unroll 1
47 #endif
48  for (int jj = -1; jj <= 1; ++jj) {
49 #ifdef AMREX_USE_GPU
50 #pragma unroll 1
51 #endif
52  for (int ii = -1; ii <= 1; ++ii) {
53  if (flag(i,j,k).isConnected(ii,jj,kk) && !(ii == 0 && jj == 0 && kk == 0)) {
54  amrex::Real offset_x = (amrex::Real(ii) + ccent(i+ii,j+jj,k+kk,0) - bcent_eb[0]) * dx;
55  amrex::Real offset_y = (amrex::Real(jj) + ccent(i+ii,j+jj,k+kk,1) - bcent_eb[1]) * dy;
56  amrex::Real offset_z = (amrex::Real(kk) + ccent(i+ii,j+jj,k+kk,2) - bcent_eb[2]) * dz;
57  amrex::Real du = state(i+ii,j+jj,k+kk) - state_eb;
58  normal_eq.add(offset_x, offset_y, offset_z, du);
59  }
60  }}}
61 
62  return normal_eq.solve();
63 }
64 
65 /**
66  * \brief Compute least-squares slopes from staggered data using EB Dirichlet data.
67  *
68  * @tparam GridQuery Grid index for the query location.
69  * @tparam GridData Grid index for the data locations.
70  * @param[in] dx Mesh spacing in x.
71  * @param[in] dy Mesh spacing in y.
72  * @param[in] dz Mesh spacing in z.
73  * @param[in] i Cell index in x.
74  * @param[in] j Cell index in y.
75  * @param[in] k Cell index in z.
76  * @param[in] bcent_eb EB boundary centroid.
77  * @param[in] state_eb Dirichlet state at the EB boundary.
78  * @param[in] state State array on the data grid.
79  * @param[in] ccent Cell centroid coordinates.
80  * @param[in] flag EB flags on the data grid.
81  */
82 template <int GridQuery, int GridData>
83 AMREX_GPU_DEVICE AMREX_FORCE_INLINE
84 amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>
87  int i, int j, int k,
88  amrex::RealVect const& bcent_eb,
89  amrex::Real const state_eb,
90  amrex::Array4<amrex::Real const> const& state,
91  amrex::Array4<amrex::Real const> const& ccent,
92  amrex::Array4<amrex::EBCellFlag const> const& flag)
93 {
94  static_assert(GridQuery == Vars::xvel || GridQuery == Vars::yvel ||
95  GridQuery == Vars::zvel);
96  static_assert(GridData == Vars::xvel || GridData == Vars::yvel ||
97  GridData == Vars::zvel);
98 
99  // Fitting stencil
100  constexpr int ii_lo = (GridQuery == Vars::xvel) ? -2 : -1;
101  constexpr int jj_lo = (GridQuery == Vars::yvel) ? -2 : -1;
102  constexpr int kk_lo = (GridQuery == Vars::zvel) ? -2 : -1;
103  constexpr int ii_hi = (GridData == Vars::xvel) ? 2 : 1;
104  constexpr int jj_hi = (GridData == Vars::yvel) ? 2 : 1;
105  constexpr int kk_hi = (GridData == Vars::zvel) ? 2 : 1;
106 
107  // Set bias in the index space between the two staggered grids
108  amrex::RealVect bias{zero,zero,zero};
109  bias[GridQuery-1] = myhalf;
110  bias[GridData-1] = -myhalf;
111 
112  amrex::EBSlopeNormalEquation normal_eq;
113 
114  // Prevent loop unrolling to reduce register pressure.
115 #ifdef AMREX_USE_GPU
116 #pragma unroll 1
117 #endif
118  for (int kk = kk_lo; kk <= kk_hi; ++kk) {
119 #ifdef AMREX_USE_GPU
120 #pragma unroll 1
121 #endif
122  for (int jj = jj_lo; jj <= jj_hi; ++jj) {
123 #ifdef AMREX_USE_GPU
124 #pragma unroll 1
125 #endif
126  for (int ii = ii_lo; ii <= ii_hi; ++ii) {
127  if (!flag(i+ii,j+jj,k+kk).isCovered()) {
128  amrex::Real offset_x = (amrex::Real(ii) + ccent(i+ii,j+jj,k+kk,0) + bias[0] - bcent_eb[0]) * dx;
129  amrex::Real offset_y = (amrex::Real(jj) + ccent(i+ii,j+jj,k+kk,1) + bias[1] - bcent_eb[1]) * dy;
130  amrex::Real offset_z = (amrex::Real(kk) + ccent(i+ii,j+jj,k+kk,2) + bias[2] - bcent_eb[2]) * dz;
131  amrex::Real du = state(i+ii,j+jj,k+kk) - state_eb;
132  normal_eq.add(offset_x, offset_y, offset_z, du);
133  }
134  }}}
135 
136  return normal_eq.solve();
137 }
138 
139 /**
140  * \brief Compute centered least-squares slopes from cell data to a staggered query grid.
141  *
142  * @param[in] igrid_query Grid index for the staggered query location.
143  * @param[in] igrid_data Grid index for the source data locations.
144  * @param[in] dx Mesh spacing in x.
145  * @param[in] dy Mesh spacing in y.
146  * @param[in] dz Mesh spacing in z.
147  * @param[in] i Cell index in x.
148  * @param[in] j Cell index in y.
149  * @param[in] k Cell index in z.
150  * @param[in] state State array on the data grid.
151  * @param[in] ccent Cell centroid coordinates.
152  * @param[in] flag EB flags on the data grid.
153  */
154 AMREX_GPU_DEVICE AMREX_FORCE_INLINE
155 amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>
157  int igrid_data,
159  int i, int j, int k,
160  amrex::Array4<amrex::Real const> const& state,
161  amrex::Array4<amrex::Real const> const& ccent,
162  amrex::Array4<amrex::EBCellFlag const> const& flag)
163 {
164  AMREX_ASSERT((igrid_query == Vars::xvel || igrid_query == Vars::yvel || igrid_query == Vars::zvel) && igrid_data == Vars::cons);
165 
166  // Fitting stencil
167 
168  int ii_lo = -1;
169  int jj_lo = -1;
170  int kk_lo = -1;
171  int ii_hi = 1;
172  int jj_hi = 1;
173  int kk_hi = 1;
174 
175  if (igrid_query == Vars::xvel) {
176  ii_lo = -2;
177  } else if (igrid_query == Vars::yvel) {
178  jj_lo = -2;
179  } else if (igrid_query == Vars::zvel) {
180  kk_lo = -2;
181  }
182 
183  if (igrid_data == Vars::xvel) {
184  ii_hi = 2;
185  } else if (igrid_data == Vars::yvel) {
186  jj_hi = 2;
187  } else if (igrid_data == Vars::zvel) {
188  kk_hi = 2;
189  }
190 
191  // Set bias in the index space between the two staggered grids
192  amrex::RealVect bias{zero,zero,zero};
193  bias[igrid_query-1] = myhalf;
194 
195  amrex::EBSlopeNormalEquation normal_eq;
196 
197  // Prevent loop unrolling to reduce register pressure.
198 #ifdef AMREX_USE_GPU
199 #pragma unroll 1
200 #endif
201  for (int kk = kk_lo; kk <= kk_hi; ++kk) {
202 #ifdef AMREX_USE_GPU
203 #pragma unroll 1
204 #endif
205  for (int jj = jj_lo; jj <= jj_hi; ++jj) {
206 #ifdef AMREX_USE_GPU
207 #pragma unroll 1
208 #endif
209  for (int ii = ii_lo; ii <= ii_hi; ++ii) {
210  if (!flag(i+ii,j+jj,k+kk).isCovered()) {
211  amrex::Real offset_x = (amrex::Real(ii) + ccent(i+ii,j+jj,k+kk,0)
212  + bias[0] - ccent(i,j,k,0)) * dx;
213  amrex::Real offset_y = (amrex::Real(jj) + ccent(i+ii,j+jj,k+kk,1)
214  + bias[1] - ccent(i,j,k,1)) * dy;
215  amrex::Real offset_z = (amrex::Real(kk) + ccent(i+ii,j+jj,k+kk,2)
216  + bias[2] - ccent(i,j,k,2)) * dz;
217  amrex::Real du = state(i+ii,j+jj,k+kk) - state(i,j,k);
218  normal_eq.add(offset_x, offset_y, offset_z, du);
219  }
220  }}}
221 
222  return normal_eq.solve();
223 }
224 
225 /**
226  * \brief Compute upwind-biased least-squares slopes for staggered EB advection.
227  *
228  * @param[in] igrid_query Grid index for the staggered query location.
229  * @param[in] igrid_data Grid index for the source data locations.
230  * @param[in] dx Mesh spacing in x.
231  * @param[in] dy Mesh spacing in y.
232  * @param[in] dz Mesh spacing in z.
233  * @param[in] i Cell index in x.
234  * @param[in] j Cell index in y.
235  * @param[in] k Cell index in z.
236  * @param[in] vel_arr Velocity array used to choose the upwind stencil.
237  * @param[in] state State array on the data grid.
238  * @param[in] ccent Cell centroid coordinates.
239  * @param[in] flag EB flags on the data grid.
240  */
241 AMREX_GPU_DEVICE AMREX_FORCE_INLINE
242 amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>
244  [[maybe_unused]] int igrid_data,
246  int i, int j, int k,
247  const amrex::Array4<const amrex::Real>& vel_arr,
248  amrex::Array4<amrex::Real const> const& state,
249  amrex::Array4<amrex::Real const> const& ccent,
250  amrex::Array4<amrex::EBCellFlag const> const& flag)
251 {
252  AMREX_ASSERT((igrid_query == Vars::xvel || igrid_query == Vars::yvel || igrid_query == Vars::zvel) && igrid_data == Vars::cons);
253 
254  // Fitting stencil
255 
256  int ii_lo = -1;
257  int jj_lo = -1;
258  int kk_lo = -1;
259  int ii_hi = 1;
260  int jj_hi = 1;
261  int kk_hi = 1;
262 
263  if (igrid_query == Vars::xvel && vel_arr(i,j,k)>zero) {
264  ii_lo = -2;
265  ii_hi = 0;
266  }
267  if (igrid_query == Vars::yvel && vel_arr(i,j,k)>zero) {
268  jj_lo = -2;
269  jj_hi = 0;
270  }
271  if (igrid_query == Vars::zvel && vel_arr(i,j,k)>zero) {
272  kk_lo = -2;
273  kk_hi = 0;
274  }
275 
276  // Set bias in the index space between the two staggered grids
277  amrex::RealVect bias{zero,zero,zero};
278  bias[igrid_query-1] = myhalf;
279 
280  amrex::EBSlopeNormalEquation normal_eq;
281 
282  // Prevent loop unrolling to reduce register pressure.
283 #ifdef AMREX_USE_GPU
284 #pragma unroll 1
285 #endif
286  for (int kk = kk_lo; kk <= kk_hi; ++kk) {
287 #ifdef AMREX_USE_GPU
288 #pragma unroll 1
289 #endif
290  for (int jj = jj_lo; jj <= jj_hi; ++jj) {
291 #ifdef AMREX_USE_GPU
292 #pragma unroll 1
293 #endif
294  for (int ii = ii_lo; ii <= ii_hi; ++ii) {
295  if (!flag(i+ii,j+jj,k+kk).isCovered() && !(ii == 0 && jj == 0 && kk == 0)) {
296  amrex::Real offset_x = (amrex::Real(ii) + ccent(i+ii,j+jj,k+kk,0)
297  + bias[0] - ccent(i,j,k,0)) * dx;
298  amrex::Real offset_y = (amrex::Real(jj) + ccent(i+ii,j+jj,k+kk,1)
299  + bias[1] - ccent(i,j,k,1)) * dy;
300  amrex::Real offset_z = (amrex::Real(kk) + ccent(i+ii,j+jj,k+kk,2)
301  + bias[2] - ccent(i,j,k,2)) * dz;
302  amrex::Real du = state(i+ii,j+jj,k+kk) - state(i,j,k);
303  normal_eq.add(offset_x, offset_y, offset_z, du);
304  }
305  }}}
306 
307  return normal_eq.solve();
308 }
309 
310 #endif
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > erf_calc_slopes_eb_Dirichlet(amrex::Real dx, amrex::Real dy, amrex::Real dz, int i, int j, int k, amrex::RealVect const &bcent_eb, amrex::Real const state_eb, amrex::Array4< amrex::Real const > const &state, amrex::Array4< amrex::Real const > const &ccent, amrex::Array4< amrex::EBCellFlag const > const &flag)
Compute least-squares slopes using EB Dirichlet data.
Definition: ERF_EBSlopes.H:29
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > erf_calc_slopes_eb_staggered_upwind(int igrid_query, [[maybe_unused]] int igrid_data, amrex::Real dx, amrex::Real dy, amrex::Real dz, int i, int j, int k, const amrex::Array4< const amrex::Real > &vel_arr, amrex::Array4< amrex::Real const > const &state, amrex::Array4< amrex::Real const > const &ccent, amrex::Array4< amrex::EBCellFlag const > const &flag)
Compute upwind-biased least-squares slopes for staggered EB advection.
Definition: ERF_EBSlopes.H:243
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > erf_calc_slopes_eb_Dirichlet_staggered(amrex::Real dx, amrex::Real dy, amrex::Real dz, int i, int j, int k, amrex::RealVect const &bcent_eb, amrex::Real const state_eb, amrex::Array4< amrex::Real const > const &state, amrex::Array4< amrex::Real const > const &ccent, amrex::Array4< amrex::EBCellFlag const > const &flag)
Compute least-squares slopes from staggered data using EB Dirichlet data.
Definition: ERF_EBSlopes.H:85
AMREX_GPU_DEVICE AMREX_FORCE_INLINE amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > erf_calc_slopes_eb_staggered(int igrid_query, int igrid_data, amrex::Real dx, amrex::Real dy, amrex::Real dz, int i, int j, int k, amrex::Array4< amrex::Real const > const &state, amrex::Array4< amrex::Real const > const &ccent, amrex::Array4< amrex::EBCellFlag const > const &flag)
Compute centered least-squares slopes from cell data to a staggered query grid.
Definition: ERF_EBSlopes.H:156
const Real dy
Definition: ERF_InitCustomPert_ABL.H:45
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
constexpr amrex::Real zero
Definition: ERF_NumericalConstants.H:36
constexpr amrex::Real myhalf
Definition: ERF_NumericalConstants.H:41
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ xvel
Definition: ERF_IndexDefines.H:255
@ cons
Definition: ERF_IndexDefines.H:254
@ zvel
Definition: ERF_IndexDefines.H:257
@ yvel
Definition: ERF_IndexDefines.H:256
@ dz
Definition: ERF_AdvanceWDM6.cpp:273