ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_Utils.H
Go to the documentation of this file.
1 #ifndef ERF_UTILS_H_
2 #define ERF_UTILS_H_
3 
4 #include <utility>
5 
6 #include "AMReX.H"
7 #include "AMReX_MultiFab.H"
8 #include "AMReX_BCRec.H"
11 #include "ERF_DataStruct.H"
12 #include "ERF_IndexDefines.H"
13 #include "ERF_SurfaceLayer.H"
14 #include "ERF_FillPatcher.H"
15 #include "ERF_ImmersedWallCell.H"
16 #include "ERF_ReadBndryPlanes.H"
17 
18 /** Build one density-weighted, nonnegative WRF moisture target. */
19 AMREX_GPU_HOST_DEVICE
20 AMREX_FORCE_INLINE
23  const amrex::Real q_n,
24  const amrex::Real q_np1,
25  const amrex::Real alpha) noexcept
26 {
27  const amrex::Real q = (one - alpha) * q_n + alpha * q_np1;
28  return rho * amrex::max(q, amrex::Real(0.0));
29 }
30 
31 /** True when ERF carries all five hydrometeor mass species separately. */
32 AMREX_GPU_HOST_DEVICE
33 AMREX_FORCE_INLINE
34 bool
36 {
37  return moisture_indices.qc >= 0 && moisture_indices.qi >= 0 &&
38  moisture_indices.qr >= 0 && moisture_indices.qs >= 0 &&
39  moisture_indices.qg >= 0;
40 }
41 
42 /** Map an active conserved moisture component to its real-boundary field. */
43 inline int
45  const MoistureComponentIndices& moisture_indices,
46  const bool use_wrf_bdy_qc_qi,
47  const bool separate_hydrometeors = false)
48 {
49  if (comp == moisture_indices.qv) { return RealBdyVars::QV; }
50  if (use_wrf_bdy_qc_qi) {
51  if (comp == moisture_indices.qc) { return RealBdyVars::QC; }
52  if (moisture_indices.qi >= 0 && comp == moisture_indices.qi) {
53  return RealBdyVars::QI;
54  }
55  if (separate_hydrometeors) {
56  if (comp == moisture_indices.qr) { return RealBdyHydrometeorVars::QR; }
57  if (comp == moisture_indices.qs) { return RealBdyHydrometeorVars::QS; }
58  if (comp == moisture_indices.qg) { return RealBdyHydrometeorVars::QG; }
59  }
60  }
61  return -1;
62 }
63 
64 /**
65  * The real-boundary maps of the conserved state, one entry per conserved
66  * component up to NVAR_max: whether the component is read from the WRF/metgrid
67  * boundary data (read), from which boundary field (map), and from which
68  * boundary-plane slot when planes are read as well (bnd, cons_bc_comp).
69  * Density is read with erf.use_wrf_bdy_density, theta and the water vapour
70  * always; passive scalars never. Hydrometeor mappings retain the upstream
71  * read flags, which do not enable hydrometeor ghost-cell fills.
72  * Built from the component layout, so every passive scalar (NSCALARS of them)
73  * sits between RhoKE_comp and RhoQ1_comp.
74  */
76 {
77  amrex::Vector<int> read;
78  amrex::Vector<int> map;
79  amrex::Vector<int> bnd;
80 };
81 
82 inline RealBdyConsMaps
83 real_bdy_cons_maps (const bool read_density,
84  const MoistureComponentIndices& moisture_indices,
85  const bool use_wrf_bdy_qc_qi,
86  const bool separate_hydrometeors)
87 {
89  m.read.assign(NVAR_max, 0);
90  m.map.resize(NVAR_max);
91  m.bnd.resize(NVAR_max);
92  for (int comp = 0; comp < NVAR_max; ++comp) {
93  m.map[comp] = comp;
94  m.bnd[comp] = cons_bc_comp(comp);
95  }
96  m.read[Rho_comp] = read_density ? 1 : 0;
97  m.map [Rho_comp] = read_density ? RealBdyVars::R : Rho_comp;
98  m.read[RhoTheta_comp] = 1;
100  m.read[RhoQ1_comp] = 1;
102  for (int comp = 0; comp < NVAR_max; ++comp) {
103  const int bdy_var = wrf_bdy_var_for_moisture_component(
104  comp, moisture_indices, use_wrf_bdy_qc_qi, separate_hydrometeors);
105  if (bdy_var >= 0) {
106  m.map[comp] = bdy_var;
107  }
108  }
109  return m;
110 }
111 
112 /*
113  * Rebalance state to satisfy both EOS and HSE one column at a time
114  */
115 void
116 rebalance_columns (amrex::MultiFab& rho,
117  amrex::MultiFab& theta,
118  const amrex::MultiFab& qt,
119  const amrex::MultiFab& qv,
120  const amrex::MultiFab* z_phys,
121  const amrex::Geometry& geom,
122  const bool& maintain_Th,
123  bool use_sfc = false);
124 
125 /*
126  * Create a new BoxArray in which every grid touches the bottom boundary
127  */
128 void ChopGrids2D (amrex::BoxArray& ba, const amrex::Box& domain, int target_size);
129 
130 /*
131  * Create a new BoxArray with exactly the number of boxes as MPI ranks.
132  * This is designed to work only on the base level which covers the entire domain.
133  */
134 amrex::BoxArray
135 ERFPostProcessBaseGrids (const amrex::Box& domain, bool decompose_in_z);
136 
137 /**
138  * Convert conservative state to primitive variables.
139  * @param[in] cons_state Conservative state MultiFab.
140  * @param[out] S_prim Primitive state MultiFab.
141  * @param[in] ng Number of ghost cells.
142  */
143 void
144 cons_to_prim (const amrex::MultiFab& cons_state, amrex::MultiFab& S_prim, int ng);
145 
146 /**
147  * Fill the ghost cells of the wall distance field, which is only computed on
148  * the valid region, so that operators reading from grown boxes do not see the
149  * sentinel value used to initialize it.
150  * @param[inout] wdist MultiFab holding the wall distance.
151  * @param[in] geom Geometry at this level.
152  */
153 void
154 fill_wall_dist_ghost_cells (amrex::MultiFab& wdist, const amrex::Geometry& geom);
155 
156 /**
157  * Compute total water mixing ratio from conservative state.
158  * @param[in] cons_state Conservative state MultiFab.
159  * @param[out] qt MultiFab to store total water.
160  * @param[in] n_qstate_into_total Number of components to include in total water.
161  */
162 void
163 make_qt (const amrex::MultiFab& cons_state, amrex::MultiFab& qt, int n_qstate_into_total);
164 
165 /**
166  * Average down a cell-centred state over immersed-forcing levels (erf.if_average_down =
167  * fluid_mass). The fine cells are weighted by their fluid mass,
168  * (rho S)_c = rho_c * sum (1 - beta_f) V_f (rho S)_f / sum (1 - beta_f) V_f rho_f,
169  * with beta the solid fraction, V the fine cell volume (detJ / (m_x m_y), the weight the plain
170  * average carries in the state) and rho_c the coarse density: the fluid-volume-weighted mean of
171  * the fine density, sum (1 - beta_f) V_f rho_f / sum (1 - beta_f) V_f, when the density is in the
172  * component range, else the coarse cell's own. The coarse value is the fluid mean over the whole
173  * coarse cell (intensive), not the sum over the fine cells. Coarse cells that are solid on their
174  * own level, or with no fluid fine cell under them, keep their value. The plain average mixes the
175  * values of solid fine cells into coarse fluid cells.
176  * @param[in] S_fine Fine state (unscaled).
177  * @param[in,out] S_crse Coarse state (unscaled); the covered cells are written.
178  * @param[in] beta_fine Fine solid fraction (terrain_blanking).
179  * @param[in] beta_crse Coarse solid fraction.
180  * @param[in] vol_fine Fine cell volume weight (any constant factor cancels).
181  * @param[in] scomp First component to average.
182  * @param[in] ncomp Number of components.
183  * @param[in] ratio Refinement ratio.
184  */
185 void
186 if_average_down (const amrex::MultiFab& S_fine, amrex::MultiFab& S_crse,
187  const amrex::MultiFab& beta_fine, const amrex::MultiFab& beta_crse,
188  const amrex::MultiFab& vol_fine,
189  int scomp, int ncomp, const amrex::IntVect& ratio);
190 
191 /**
192  * RANS wall distance over terrain represented by immersed forcing with the fraction-stress wall
193  * law (erf.if_wall_form = fraction_stress): measured vertically from the surface itself,
194  * h = z_bot + beta dz of the wall cell (the partial cell, or the fluid cell on a solid cell;
195  * ERF_ImmersedWallCell.H), the wall cell at its fluid centroid (1 - beta) dz / 2 above it and
196  * every other cell at |z_cc - h|; a column without solid measures from the bottom of the domain.
197  * A box that does not see the surface of a column (a fine box inside the solid, or above the
198  * surface without reaching the bottom) measures from the coarser level's wall height.
199  * @param[out] wdist Wall distance (valid cells; ghost cells are left untouched).
200  * @param[in] terrain_blank Cell-centred solid fraction.
201  * @param[in] z_phys_nd Node heights.
202  * @param[in] z_phys_cc Cell-centre heights.
203  * @param[in] domain Index domain of the level.
204  * @param[in] small_volfrac Solid fraction below which a cell counts as fluid.
205  * @param[out] wall_height Optional: the height measured from in each column, on the level's
206  * BoxArray flattened to the bottom cell (same DistributionMapping).
207  * @param[in] wall_height_crse Optional, fine levels: wall_height of the coarser level brought to
208  * this level's flattened BoxArray. Without it every box must hold whole columns.
209  */
210 void
211 immersed_wall_dist (amrex::MultiFab& wdist,
212  const amrex::MultiFab& terrain_blank,
213  const amrex::MultiFab& z_phys_nd,
214  const amrex::MultiFab& z_phys_cc,
215  const amrex::Box& domain,
216  amrex::Real small_volfrac,
217  amrex::MultiFab* wall_height = nullptr,
218  const amrex::MultiFab* wall_height_crse = nullptr);
219 
220 /**
221  * Wall-face masks of the fraction-stress wall law (erf.if_wall_form = fraction_stress):
222  * zero on the xz (yz) edge that is the bottom face of the wall cell of an x-face (y-face)
223  * column, the spacing factor on the face above it, one elsewhere. The vertical flux of x (y)
224  * momentum is multiplied by them, so no resolved flux crosses the wall face (see
225  * ERF_ImmersedWallCell.H).
226  * @param[in] terrain_blank Cell-centred solid fraction; needs one more ghost cell than the masks.
227  * @param[out] mask13 On convert(ba, IntVect(1,0,1)), valid and ghost cells.
228  * @param[out] mask23 On convert(ba, IntVect(0,1,1)), valid and ghost cells.
229  * @param[out] mask33 On convert(ba, IntVect(0,0,1)): the same for the cell columns, applied to
230  * the vertical diffusive fluxes of theta and TKE (zero on the bottom face of the wall cell).
231  * @param[in] domain Index domain of the level.
232  * @param[in] small_volfrac Solid fraction below which a cell counts as fluid.
233  * @param[in] spacing erf.if_wall_face_spacing (0 grid, 1 physical, 2 log): the face ABOVE the wall
234  * cell gets ib_wall::face_above_factor instead of one.
235  * @param[in] dz Cell height (constant-dz mesh).
236  * @param[in] z0 Roughness length of the wall law.
237  */
238 void
239 make_ib_wall_face_masks (const amrex::MultiFab& terrain_blank,
240  amrex::MultiFab& mask13,
241  amrex::MultiFab& mask23,
242  amrex::MultiFab& mask33,
243  const amrex::Box& domain,
244  amrex::Real small_volfrac,
245  int spacing = 0,
246  amrex::Real dz = amrex::Real(1.0),
247  amrex::Real z0 = amrex::Real(0.1));
248 
249 /**
250  * Where the coarse and fine levels disagree on an immersed surface along the lateral coarse/fine
251  * faces of the fine level (erf.if_cf_mismatch_warning): the surface on a coarse cell's mid-plane
252  * leaves the coarse cell half solid over fine cells that are all solid and all fluid. For each
253  * coarse cell covered by the fine level and next to an uncovered one, the spread (max - min) of
254  * the fine solid fractions under it is formed; cells with a spread of at least warn are counted.
255  *
256  * @param[in] fine_tb fine solid fraction (terrain_blanking)
257  * @param[in] fine_grids fine BoxArray
258  * @param[in] crse_grids coarse BoxArray
259  * @param[in] crse_dmap coarse DistributionMapping
260  * @param[in] crse_geom coarse Geometry
261  * @param[in] ratio refinement ratio
262  * @param[in] warn spread at or above which a cell is counted
263  * @return the number of counted cells over all ranks, and the largest spread along those faces
264  */
265 std::pair<int, amrex::Real>
266 if_cf_surface_mismatch (const amrex::MultiFab& fine_tb,
267  const amrex::BoxArray& fine_grids,
268  const amrex::BoxArray& crse_grids,
269  const amrex::DistributionMapping& crse_dmap,
270  const amrex::Geometry& crse_geom,
271  const amrex::IntVect& ratio,
272  amrex::Real warn);
273 
274 
275 /*
276  * Create the Jacobian for the metric transformation when use_terrain is true
277  */
278 void make_J (const amrex::Geometry& geom,
279  amrex::MultiFab& z_phys_nd,
280  amrex::MultiFab& detJ_cc);
281 
282 void make_areas (const amrex::Geometry& geom,
283  amrex::MultiFab& z_phys_nd,
284  amrex::MultiFab& ax,
285  amrex::MultiFab& ay,
286  amrex::MultiFab& az);
287 
288 /*
289  * Average z_phys_nd on nodes to cell centers
290  */
291 void make_zcc (const amrex::Geometry& geom,
292  amrex::MultiFab& z_phys_nd,
293  amrex::MultiFab& z_phys_cc);
294 
295 /*
296  * Convert momentum to velocity by dividing by density averaged onto faces
297  */
298 void MomentumToVelocity (amrex::MultiFab& xvel_out,
299  amrex::MultiFab& yvel_out,
300  amrex::MultiFab& zvel_out,
301  const amrex::MultiFab& cons_in,
302  const amrex::MultiFab& xmom_in,
303  const amrex::MultiFab& ymom_in,
304  const amrex::MultiFab& zmom_in,
305  const amrex::Box& domain,
306  const amrex::Vector<amrex::BCRec>& domain_bcs_type_h,
307  const amrex::MultiFab* c_vfrac = nullptr // optional
308  );
309 
310 /*
311  * Convert velocity to momentum by multiplying by density averaged onto faces
312  */
313 void VelocityToMomentum (const amrex::MultiFab& xvel_in,
314  const amrex::IntVect & xvel_ngrow,
315  const amrex::MultiFab& yvel_in,
316  const amrex::IntVect & yvel_ngrow,
317  const amrex::MultiFab& zvel_in,
318  const amrex::IntVect & zvel_ngrow,
319  const amrex::MultiFab& cons_in,
320  amrex::MultiFab& xmom_out,
321  amrex::MultiFab& ymom_out,
322  amrex::MultiFab& zmom_out,
323  const amrex::Box& domain,
324  const amrex::Vector<amrex::BCRec>& domain_bcs_type_h,
325  const amrex::MultiFab* c_vfrac = nullptr // optional
326  );
327 
328 /*
329  * Convert (den_div u) to (den_mlt u) by multiplying by (den_mlt/den_div)
330  */
331 void
332 ConvertForProjection (const amrex::MultiFab& den_div, const amrex::MultiFab& den_mlt,
333  amrex::MultiFab& xmom, amrex::MultiFab& ymom, amrex::MultiFab& zmom,
334  const amrex::Box& domain, const amrex::Vector<amrex::BCRec>& domain_bcs_type_h);
335 
336 /*
337  * Compute lateral boundary mass influx/outflux from base-state-density-weighted
338  * boundary normal velocities.
339  */
340 void
341 compute_influx_outflux_bdy (amrex::FArrayBox& bdy_data_xlo, amrex::FArrayBox& bdy_data_xhi,
342  amrex::FArrayBox& bdy_data_ylo, amrex::FArrayBox& bdy_data_yhi,
343  amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& area_vec,
344  const amrex::Geometry& geom,
345  amrex::Real& influx, amrex::Real& outflux,
346  const int n);
347 
348 /*
349  * \brief Enforces solvability on lateral boundary data by scaling outflow to
350  * match with inflow.
351  */
352 void enforceInOutSolvability_bdy (const amrex::MultiFab& rho0,
353  amrex::FArrayBox& bdy_data_xlo,
354  amrex::FArrayBox& bdy_data_xhi,
355  amrex::FArrayBox& bdy_data_ylo,
356  amrex::FArrayBox& bdy_data_yhi,
357  amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& area_vec,
358  const amrex::Geometry& geom,
359  const amrex::Vector<amrex::BCRec>& domain_bcs_type_h);
360 
361 /*
362  * \brief Enforces solvability by scaling outflow to match with inflow.
363  *
364  */
366  amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& vels_vec,
367  amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& area_vec,
368  const amrex::Geometry& geom);
369 
370 /*
371  * Compute boxes for looping over interior/exterior ghost cells
372  * for use by fillpatch, erf_slow_rhs_pre, and erf_slow_rhs_post
373  */
374 void realbdy_interior_bxs_xy (const amrex::Box& bx,
375  const amrex::Box& domain,
376  const int& width,
377  amrex::Box& bx_xlo,
378  amrex::Box& bx_xhi,
379  amrex::Box& bx_ylo,
380  amrex::Box& bx_yhi,
381  const amrex::IntVect& ng_vect=amrex::IntVect(0,0,0),
382  const bool get_int_ng=false);
383 
384 /*
385  * Compute boxes for looping over set region cells
386  * for use by fillpatch, erf_slow_rhs_pre, and erf_slow_rhs_post
387  */
388 void realbdy_bc_bxs_xy (const amrex::Box& bx,
389  const amrex::Box& domain,
390  const int& set_width,
391  amrex::Box& bx_xlo,
392  amrex::Box& bx_xhi,
393  amrex::Box& bx_ylo,
394  amrex::Box& bx_yhi,
395  const amrex::IntVect& ng_vect=amrex::IntVect(0,0,0));
396 
397 /*
398  * Compute relaxation region RHS with wrfbdy
399  */
400 void realbdy_compute_interior_ghost_rhs (const double& total_time,
401  const double& delta_t,
402  const double& start_bdy_time,
403  const double& final_bdy_time,
404  const double& bdy_time_interval,
405  const amrex::Real& nudge_factor,
406  int width,
407  const amrex::Geometry& geom,
408  amrex::Vector<amrex::MultiFab>& S_rhs,
409  amrex::Vector<amrex::MultiFab>& S_cur_data,
410  amrex::Vector<amrex::Vector<amrex::FArrayBox>>& bdy_data_xlo,
411  amrex::Vector<amrex::Vector<amrex::FArrayBox>>& bdy_data_xhi,
412  amrex::Vector<amrex::Vector<amrex::FArrayBox>>& bdy_data_ylo,
413  amrex::Vector<amrex::Vector<amrex::FArrayBox>>& bdy_data_yhi,
414  std::unique_ptr<ReadBndryPlanes>& m_r2d,
415  const amrex::Real& c_p,
416  const amrex::Real& rdOcp,
417  const bool use_wrf_bdy_density,
418  const amrex::Real& bdy_rho_nudge_factor);
419 
420 /*
421  * Compute relaxation region RHS at fine-crse interface
422  */
423 void
425  const double& delta_t,
426  const int& width,
427  const int& set_width,
428  const amrex::Geometry& geom,
429  ERFFillPatcher* FPr_c,
430  ERFFillPatcher* FPr_u,
431  ERFFillPatcher* FPr_v,
432  ERFFillPatcher* FPr_w,
433  amrex::Vector<amrex::BCRec>& domain_bcs_type,
434  amrex::Vector<amrex::MultiFab>& S_rhs_f,
435  amrex::Vector<amrex::MultiFab>& S_data_f);
436 
437 /*
438  * Accumulate time averaged velocity fields
439  */
440 void
441 Time_Avg_Vel_atCC (double dt,
442  double& t_avg_cnt,
443  amrex::MultiFab* vel_t_avg,
444  amrex::MultiFab& xvel,
445  amrex::MultiFab& yvel,
446  amrex::MultiFab& zvel);
447 
448 /**
449  * Accumulate time-weighted cell-centered velocity/theta first and second moments.
450  * @param[in] dt accumulation interval
451  * @param[in,out] t_mean_cnt accumulated time
452  * @param[in,out] interval_means ten-component moment storage
453  * @param[in] xvel x-face velocity
454  * @param[in] yvel y-face velocity
455  * @param[in] zvel z-face velocity
456  * @param[in] cons conserved cell-centered state
457  */
458 void
460  double& t_mean_cnt,
461  amrex::MultiFab* interval_means,
462  amrex::MultiFab& xvel,
463  amrex::MultiFab& yvel,
464  amrex::MultiFab& zvel,
465  amrex::MultiFab& cons);
466 
467 /**
468  * Compute the nudging relaxation
469  *
470  * @param[in] delta_t time step
471  * @param[in] icomp component offset
472  * @param[in] num_var number of variables to loop
473  * @param[in] width width of wrf bdy file
474  * @param[in] dom_lo low bound of domain
475  * @param[in] dom_hi high bound of domain
476  * @param[in] F1 drift relaxation parameter
477  * @param[in] bx_xlo box for low x relaxation
478  * @param[in] bx_xhi box for high x relaxation
479  * @param[in] bx_ylo box for low y relaxation
480  * @param[in] bx_yhi box for high y relaxation
481  * @param[in] arr_xlo array for low x relaxation
482  * @param[in] arr_xhi array for high x relaxation
483  * @param[in] arr_ylo array for low y relaxation
484  * @param[in] arr_yhi array for high y relaxation
485  * @param[in] data_arr data array
486  * @param[out] rhs_arr RHS array
487  */
488 AMREX_GPU_HOST
489 AMREX_FORCE_INLINE
490 void
491 realbdy_compute_relaxation (const int& icomp,
492  const int& num_var,
493  const int& width,
494  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& dx,
495  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbLo,
496  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbHi,
497  const amrex::Real& F1,
498  const amrex::Box& bx_xlo,
499  const amrex::Box& bx_xhi,
500  const amrex::Box& bx_ylo,
501  const amrex::Box& bx_yhi,
502  const amrex::Array4<const amrex::Real>& arr_xlo,
503  const amrex::Array4<const amrex::Real>& arr_xhi,
504  const amrex::Array4<const amrex::Real>& arr_ylo,
505  const amrex::Array4<const amrex::Real>& arr_yhi,
506  const amrex::Array4<const amrex::Real>& data_arr,
507  const amrex::Array4<amrex::Real>& rhs_arr,
508  const amrex::Real& c_p,
509  const amrex::Real& rdOcp,
510  const int bdy_moist_nudge_type=0)
511 {
512  amrex::IntVect iv = bx_xlo.type();
513  amrex::Real ioff = (iv[0]==1) ? zero : myhalf;
514  amrex::Real joff = (iv[1]==1) ? zero : myhalf;
515 
516  // These are defined in ERF_Constants.H
517  amrex::Real l_rdOcp = rdOcp;
518  amrex::Real cond_fac = lcond / c_p; // condensation
519  amrex::Real sub_fac = lsub / c_p; // sublimation
520 
521  int nq = num_var;
522 
523  amrex::ParallelFor( bx_xlo, bx_xhi,
524  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
525  {
526  // Corners with x boxes
527  amrex::Real x = ProbLo[0] + (i + ioff) * dx[0];
528  amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
529  amrex::Real x_end = ProbLo[0] + width * dx[0];
530  amrex::Real y_end = ProbLo[1] + width * dx[1];
531  amrex::Real y_strt = ProbHi[1] - width * dx[1];
532  amrex::Real xi = (x_end - x) / (x_end - ProbLo[0]);
533  amrex::Real eta_lo = (y < y_end ) ? (y_end - y) / (y_end - ProbLo[1]) : zero;
534  amrex::Real eta_hi = (y > y_strt) ? (y - y_strt) / (ProbHi[1] - y_strt) : zero;
535  amrex::Real eta = std::max(eta_lo,eta_hi);
536  amrex::Real Factor = std::max(xi*xi,eta*eta) * F1;
537 
538  if (icomp == RhoQ1_comp)
539  {
540  amrex::Real exner_pi = getExnergivenRTh(data_arr(i,j,k,RhoTheta_comp),l_rdOcp,
541  data_arr(i,j,k,RhoQ1_comp)/data_arr(i,j,k,Rho_comp));
542 
543  // qv
544  amrex::Real delta = arr_xlo(i,j,k,0) - data_arr(i,j,k,icomp);
545  rhs_arr(i,j,k,icomp) += Factor*delta;
546 
547  if (bdy_moist_nudge_type==2) {
548  // NOTE: we only operate on qv (above), qc and qi here; the
549  // precipitating species (qr/qs/qg) are left untouched.
550 
551  // qc and heat source term due to evaporation
552  delta = -data_arr(i,j,k,RhoQ2_comp); // This effectively nudges to 0
553  rhs_arr(i,j,k,RhoQ2_comp ) += Factor * delta;
554  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * cond_fac / exner_pi;
555 
556  // qi and heat source term due to sublimation
557  if (nq > 3) { // nq > 3 guarantees that RhoQ3 is ice
558  delta = -data_arr(i,j,k,RhoQ3_comp); // This effectively nudges to 0
559  rhs_arr(i,j,k,RhoQ3_comp ) += Factor * delta;
560  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * sub_fac / exner_pi;
561  }
562  } // moist_nudge_type
563  } else {
564  for (int n = 0; n < nq; n++) {
565  amrex::Real delta = arr_xlo(i,j,k,n) - data_arr(i,j,k,n+icomp);
566  rhs_arr(i,j,k,n+icomp) += Factor*delta;
567  }
568  }
569  },
570  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
571  {
572  // Corners with x boxes
573  amrex::Real x = ProbLo[0] + (i + ioff) * dx[0];
574  amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
575  amrex::Real x_strt = ProbHi[0] - width * dx[0];
576  amrex::Real y_strt = ProbHi[1] - width * dx[1];
577  amrex::Real y_end = ProbLo[1] + width * dx[1];
578  amrex::Real xi = (x - x_strt) / (ProbHi[0] - x_strt);
579  amrex::Real eta_lo = (y < y_end ) ? (y_end - y) / (y_end - ProbLo[1]) : zero;
580  amrex::Real eta_hi = (y > y_strt) ? (y - y_strt) / (ProbHi[1] - y_strt) : zero;
581  amrex::Real eta = std::max(eta_lo,eta_hi);
582  amrex::Real Factor = std::max(xi*xi,eta*eta) * F1;
583 
584  if (icomp == RhoQ1_comp)
585  {
586  amrex::Real exner_pi = getExnergivenRTh(data_arr(i,j,k,RhoTheta_comp),l_rdOcp,
587  data_arr(i,j,k,RhoQ1_comp)/data_arr(i,j,k,Rho_comp));
588 
589  // qv
590  amrex::Real delta = arr_xhi(i,j,k,0) - data_arr(i,j,k,icomp);
591  rhs_arr(i,j,k,icomp) += Factor*delta;
592 
593  if (bdy_moist_nudge_type==2) {
594  // NOTE: we only operate on qv (above), qc and qi here; the
595  // precipitating species (qr/qs/qg) are left untouched.
596 
597  // qc and heat source term due to evaporation
598  delta = -data_arr(i,j,k,RhoQ2_comp); // This effectively nudges to 0
599  rhs_arr(i,j,k,RhoQ2_comp ) += Factor*delta;
600  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * cond_fac / exner_pi;
601 
602  // qi and heat source term due to sublimation
603  if (nq > 3) { // nq > 3 guarantees that RhoQ3 is ice
604  delta = -data_arr(i,j,k,RhoQ3_comp); // This effectively nudges to 0
605  rhs_arr(i,j,k,RhoQ3_comp ) += Factor * delta;
606  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * sub_fac / exner_pi;
607  }
608  } // moist_nudge_type
609  } else {
610  for (int n = 0; n < nq; n++) {
611  amrex::Real delta = arr_xhi(i,j,k,n) - data_arr(i,j,k,n+icomp);
612  rhs_arr(i,j,k,n+icomp) += Factor*delta;
613  }
614  }
615  });
616 
617  amrex::ParallelFor( bx_ylo, bx_yhi,
618  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
619  {
620  // No corners for y boxes
621  amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
622  amrex::Real y_end = ProbLo[1] + width * dx[1];
623  amrex::Real eta = (y_end - y) / (y_end - ProbLo[1]);
624  amrex::Real Factor = eta*eta * F1;
625 
626  if (icomp == RhoQ1_comp)
627  {
628  amrex::Real exner_pi = getExnergivenRTh(data_arr(i,j,k,RhoTheta_comp),l_rdOcp,
629  data_arr(i,j,k,RhoQ1_comp)/data_arr(i,j,k,Rho_comp));
630  // qv
631  amrex::Real delta = arr_ylo(i,j,k,0) - data_arr(i,j,k,icomp);
632  rhs_arr(i,j,k,icomp) += Factor*delta;
633 
634  if (bdy_moist_nudge_type==2) {
635  // NOTE: we only operate on qv (above), qc and qi here; the
636  // precipitating species (qr/qs/qg) are left untouched.
637 
638  // qc and heat source term due to evaporation
639  delta = -data_arr(i,j,k,RhoQ2_comp); // This effectively nudges to 0
640  rhs_arr(i,j,k,RhoQ2_comp ) += Factor*delta;
641  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * cond_fac / exner_pi;
642 
643  // qi and heat source term due to sublimation
644  if (nq > 3) { // nq > 3 guarantees that RhoQ3 is ice
645  delta = -data_arr(i,j,k,RhoQ3_comp); // This effectively nudges to 0
646  rhs_arr(i,j,k,RhoQ3_comp ) += Factor * delta;
647  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * sub_fac / exner_pi;
648  }
649  } // moist_nudge_type
650  } else {
651  for (int n = 0; n < nq; n++) {
652  amrex::Real delta = arr_ylo(i,j,k,n) - data_arr(i,j,k,n+icomp);
653  rhs_arr(i,j,k,n+icomp) += Factor*delta;
654  }
655  }
656  },
657  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
658  {
659  // No corners for y boxes
660  amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
661  amrex::Real y_strt = ProbHi[1] - width * dx[1];
662  amrex::Real eta = (y - y_strt) / (ProbHi[1] - y_strt);
663  amrex::Real Factor = eta*eta * F1;
664 
665  if (icomp == RhoQ1_comp)
666  {
667  amrex::Real exner_pi = getExnergivenRTh(data_arr(i,j,k,RhoTheta_comp),l_rdOcp,
668  data_arr(i,j,k,RhoQ1_comp)/data_arr(i,j,k,Rho_comp));
669  // qv
670  amrex::Real delta = arr_yhi(i,j,k,0) - data_arr(i,j,k,icomp);
671  rhs_arr(i,j,k,icomp) += Factor*delta;
672 
673  if (bdy_moist_nudge_type==2) {
674  // NOTE: we only operate on qv (above), qc and qi here; the
675  // precipitating species (qr/qs/qg) are left untouched.
676 
677  // qc and heat source term due to evaporation
678  delta = -data_arr(i,j,k,RhoQ2_comp); // This effectively nudges to 0
679  rhs_arr(i,j,k,RhoQ2_comp ) += Factor * delta;
680  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * cond_fac / exner_pi;
681 
682  // qi and heat source term due to sublimation
683  if (nq > 3) { // nq > 3 guarantees that RhoQ3 is ice
684  delta = -data_arr(i,j,k,RhoQ3_comp); // This effectively nudges to 0
685  rhs_arr(i,j,k,RhoQ3_comp ) += Factor * delta;
686  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * sub_fac / exner_pi;
687  }
688  } // moist_nudge_type
689  } else {
690  for (int n = 0; n < nq; n++) {
691  amrex::Real delta = arr_yhi(i,j,k,n) - data_arr(i,j,k,n+icomp);
692  rhs_arr(i,j,k,n+icomp) += Factor*delta;
693  }
694  }
695  });
696 }
697 
698 /**
699  * Apply Davies relaxation to explicitly mapped moisture components. Target
700  * component n corresponds to state component moisture_comps[n].
701  */
702 AMREX_GPU_HOST
703 AMREX_FORCE_INLINE
704 void
706  const amrex::GpuArray<int,6>& moisture_comps,
707  const int n_targets,
708  const int& width,
709  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& dx,
710  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbLo,
711  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbHi,
712  const amrex::Real& F1,
713  const amrex::Box& bx_xlo,
714  const amrex::Box& bx_xhi,
715  const amrex::Box& bx_ylo,
716  const amrex::Box& bx_yhi,
717  const amrex::Array4<const amrex::Real>& arr_xlo,
718  const amrex::Array4<const amrex::Real>& arr_xhi,
719  const amrex::Array4<const amrex::Real>& arr_ylo,
720  const amrex::Array4<const amrex::Real>& arr_yhi,
721  const amrex::Array4<const amrex::Real>& data_arr,
722  const amrex::Array4<amrex::Real>& rhs_arr)
723 {
724  const amrex::IntVect iv = bx_xlo.type();
725  const amrex::Real ioff = (iv[0] == 1) ? zero : myhalf;
726  const amrex::Real joff = (iv[1] == 1) ? zero : myhalf;
727 
728  amrex::ParallelFor(bx_xlo, bx_xhi,
729  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
730  {
731  const amrex::Real x = ProbLo[0] + (i + ioff) * dx[0];
732  const amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
733  const amrex::Real x_end = ProbLo[0] + width * dx[0];
734  const amrex::Real y_end = ProbLo[1] + width * dx[1];
735  const amrex::Real y_strt = ProbHi[1] - width * dx[1];
736  const amrex::Real xi = (x_end - x) / (x_end - ProbLo[0]);
737  const amrex::Real eta_lo = (y < y_end) ? (y_end - y) / (y_end - ProbLo[1]) : amrex::Real(0.0);
738  const amrex::Real eta_hi = (y > y_strt) ? (y - y_strt) / (ProbHi[1] - y_strt) : amrex::Real(0.0);
739  const amrex::Real factor = amrex::max(xi*xi, amrex::max(eta_lo,eta_hi)*amrex::max(eta_lo,eta_hi)) * F1;
740  for (int n = 0; n < n_targets; ++n) {
741  const int comp = moisture_comps[n];
742  if (comp >= 0) {
743  rhs_arr(i,j,k,comp) += factor * (arr_xlo(i,j,k,n) - data_arr(i,j,k,comp));
744  }
745  }
746  },
747  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
748  {
749  const amrex::Real x = ProbLo[0] + (i + ioff) * dx[0];
750  const amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
751  const amrex::Real x_strt = ProbHi[0] - width * dx[0];
752  const amrex::Real y_end = ProbLo[1] + width * dx[1];
753  const amrex::Real y_strt = ProbHi[1] - width * dx[1];
754  const amrex::Real xi = (x - x_strt) / (ProbHi[0] - x_strt);
755  const amrex::Real eta_lo = (y < y_end) ? (y_end - y) / (y_end - ProbLo[1]) : amrex::Real(0.0);
756  const amrex::Real eta_hi = (y > y_strt) ? (y - y_strt) / (ProbHi[1] - y_strt) : amrex::Real(0.0);
757  const amrex::Real eta = amrex::max(eta_lo,eta_hi);
758  const amrex::Real factor = amrex::max(xi*xi, eta*eta) * F1;
759  for (int n = 0; n < n_targets; ++n) {
760  const int comp = moisture_comps[n];
761  if (comp >= 0) {
762  rhs_arr(i,j,k,comp) += factor * (arr_xhi(i,j,k,n) - data_arr(i,j,k,comp));
763  }
764  }
765  });
766 
767  amrex::ParallelFor(bx_ylo, bx_yhi,
768  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
769  {
770  const amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
771  const amrex::Real y_end = ProbLo[1] + width * dx[1];
772  const amrex::Real eta = (y_end - y) / (y_end - ProbLo[1]);
773  const amrex::Real factor = eta*eta * F1;
774  for (int n = 0; n < n_targets; ++n) {
775  const int comp = moisture_comps[n];
776  if (comp >= 0) {
777  rhs_arr(i,j,k,comp) += factor * (arr_ylo(i,j,k,n) - data_arr(i,j,k,comp));
778  }
779  }
780  },
781  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
782  {
783  const amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
784  const amrex::Real y_strt = ProbHi[1] - width * dx[1];
785  const amrex::Real eta = (y - y_strt) / (ProbHi[1] - y_strt);
786  const amrex::Real factor = eta*eta * F1;
787  for (int n = 0; n < n_targets; ++n) {
788  const int comp = moisture_comps[n];
789  if (comp >= 0) {
790  rhs_arr(i,j,k,comp) += factor * (arr_yhi(i,j,k,n) - data_arr(i,j,k,comp));
791  }
792  }
793  });
794 }
795 
796 // Backward-compatible three-species overload used by existing unit tests and
797 // callers that only target qv/qc/qi.
798 AMREX_GPU_HOST
799 AMREX_FORCE_INLINE
800 void
802  const amrex::GpuArray<int,3>& moisture_comps,
803  const int& width,
804  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& dx,
805  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbLo,
806  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbHi,
807  const amrex::Real& F1,
808  const amrex::Box& bx_xlo,
809  const amrex::Box& bx_xhi,
810  const amrex::Box& bx_ylo,
811  const amrex::Box& bx_yhi,
812  const amrex::Array4<const amrex::Real>& arr_xlo,
813  const amrex::Array4<const amrex::Real>& arr_xhi,
814  const amrex::Array4<const amrex::Real>& arr_ylo,
815  const amrex::Array4<const amrex::Real>& arr_yhi,
816  const amrex::Array4<const amrex::Real>& data_arr,
817  const amrex::Array4<amrex::Real>& rhs_arr)
818 {
819  const amrex::GpuArray<int,6> extended_comps = {
820  moisture_comps[0], moisture_comps[1], moisture_comps[2], -1, -1, -1};
822  extended_comps, 3, width, dx, ProbLo, ProbHi, F1,
823  bx_xlo, bx_xhi, bx_ylo, bx_yhi,
824  arr_xlo, arr_xhi, arr_ylo, arr_yhi, data_arr, rhs_arr);
825 }
826 
827 /*
828  * Effectively a Multiply for a MultiFab and an iMultiFab mask
829  */
830 AMREX_GPU_HOST
831 AMREX_FORCE_INLINE
832 void
833 ApplyMask (amrex::MultiFab& dst,
834  const amrex::iMultiFab& imask,
835  const int nghost = 0)
836 {
837  for (amrex::MFIter mfi(dst,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
838  {
839  const amrex::Box& bx = mfi.growntilebox(nghost);
840  if (bx.ok())
841  {
842  auto dstFab = dst.array(mfi);
843  const auto maskFab = imask.const_array(mfi);
844  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
845  {
846  dstFab(i,j,k) *= maskFab(i,j,k);
847  });
848  }
849  }
850 }
851 
852 /**
853  * Multiply a MultiFab by the inverse of an integer mask.
854  * @param[in,out] dst MultiFab to be masked.
855  * @param[in] imask Integer mask MultiFab.
856  * @param[in] nghost Number of ghost cells to include.
857  */
858 AMREX_GPU_HOST
859 AMREX_FORCE_INLINE
860 void
861 ApplyInvertedMask (amrex::MultiFab& dst,
862  const amrex::iMultiFab& imask,
863  const int nghost = 0)
864 {
865  for (amrex::MFIter mfi(dst,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
866  {
867  const amrex::Box& bx = mfi.growntilebox(nghost);
868  if (bx.ok())
869  {
870  auto dstFab = dst.array(mfi);
871  const auto maskFab = imask.const_array(mfi);
872  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
873  {
874  dstFab(i,j,k) *= (1-maskFab(i,j,k));
875  });
876  }
877  }
878 }
879 
880 /**
881  * Compute the distance to thin-body walls.
882  * @param[out] wdist MultiFab to store wall distances.
883  * @param[in] xfaces Indices of x-faces forming walls.
884  * @param[in] yfaces Indices of y-faces forming walls.
885  * @param[in] zfaces Indices of z-faces forming walls.
886  * @param[in] geomdata Geometry used for physical distance.
887  * @param[in] z_phys_cc Cell-centered physical height.
888  */
889 void
890 thinbody_wall_dist (std::unique_ptr<amrex::MultiFab>& wdist,
891  amrex::Vector<amrex::IntVect>& xfaces,
892  amrex::Vector<amrex::IntVect>& yfaces,
893  amrex::Vector<amrex::IntVect>& zfaces,
894  const amrex::Geometry& geomdata,
895  std::unique_ptr<amrex::MultiFab>& z_phys_cc);
896 
897 
898 void WeatherDataInterpolation (const double time);
899 
900 /**
901  * Perform quadratic interpolation in one dimension.
902  * @param[in] z Interpolation coordinate.
903  * @param[in] z0 Coordinate of first point.
904  * @param[in] p0 Value at first point.
905  * @param[in] z1 Coordinate of second point.
906  * @param[in] p1 Value at second point.
907  * @param[in] z2 Coordinate of third point.
908  * @param[in] p2 Value at third point.
909  * @return Interpolated value.
910  */
911 AMREX_GPU_HOST_DEVICE
912 AMREX_FORCE_INLINE
916  amrex::Real z1, amrex::Real p1,
917  amrex::Real z2, amrex::Real p2)
918 {
919  return p0 * ( (z - z1) * (z - z2) ) / ( (z0 - z1) * (z0 - z2) )
920  + p1 * ( (z - z0) * (z - z2) ) / ( (z1 - z0) * (z1 - z2) )
921  + p2 * ( (z - z0) * (z - z1) ) / ( (z2 - z0) * (z2 - z1) );
922 }
923 
924 /**
925  * Which time level(s) a fillpatch at a given time should draw from.
926  */
927 enum struct TimeLevelSel { Old, New, Interp };
928 
929 /**
930  * Decide whether data at time "time" should come from the old-time data, the new-time data,
931  * or an interpolation between the two.
932  *
933  * This is done in double precision, before any cast to Real, and with a single tolerance
934  * at both ends. The tolerance is a small fraction of (t_new - t_old), but never smaller than
935  * a few ulps of the times themselves, since those carry roundoff proportional to their
936  * magnitude -- which matters once the time is large (e.g. months measured in seconds).
937  *
938  * Times outside [t_old, t_new] are clamped to the nearer end rather than extrapolated.
939  * If t_old == t_new (to within the tolerance), Old is returned.
940  *
941  * @param[in] time time at which data are requested
942  * @param[in] t_old old time of the level
943  * @param[in] t_new new time of the level
944  */
945 inline TimeLevelSel
946 select_time_level (double time, double t_old, double t_new)
947 {
948  const double t_mag = std::max({std::abs(time), std::abs(t_old), std::abs(t_new)});
949  const double tol = std::max(1.e-8 * std::abs(t_new - t_old),
950  16.0 * std::numeric_limits<double>::epsilon() * t_mag);
951 
952  if (time <= t_old + tol) { return TimeLevelSel::Old; }
953  if (time >= t_new - tol) { return TimeLevelSel::New; }
954  return TimeLevelSel::Interp;
955 }
956 
957 /**
958  * The pair of MultiFabs to hand to an AMReX FillPatch routine for a given time-level selection.
959  * When only one time level is wanted it is passed twice, so that AMReX's own comparison of the
960  * (rounded) times can never bring in the other one.
961  *
962  * @param[in] sel which time level(s) to use
963  * @param[in] old_mf data at the old time
964  * @param[in] new_mf data at the new time
965  */
966 inline amrex::Vector<amrex::MultiFab*>
967 select_time_data (TimeLevelSel sel, amrex::MultiFab& old_mf, amrex::MultiFab& new_mf)
968 {
969  if (sel == TimeLevelSel::Old) { return {&old_mf, &old_mf}; }
970  if (sel == TimeLevelSel::New) { return {&new_mf, &new_mf}; }
971  return {&old_mf, &new_mf};
972 }
973 
974 #endif
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real getExnergivenRTh(const amrex::Real rhotheta, const amrex::Real rdOcp, const amrex::Real qv=amrex::Real(0))
Definition: ERF_EOS.H:156
#define Rho_comp
Definition: ERF_IndexDefines.H:53
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int cons_bc_comp(int n) noexcept
Definition: ERF_IndexDefines.H:140
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:54
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:67
#define NVAR_max
Definition: ERF_IndexDefines.H:37
#define RhoQ3_comp
Definition: ERF_IndexDefines.H:68
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:66
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:12
const Real rdOcp
Definition: ERF_InitCustomPert_ABL.H:72
const Real dx
Definition: ERF_InitCustomPert_ABL.H:44
Physical constants and tuning parameters used only by the moisture and cloud-physics code.
constexpr amrex::Real lsub
Definition: ERF_MicrophysicsConstants.H:111
constexpr amrex::Real lcond
Definition: ERF_MicrophysicsConstants.H:109
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);})
Dimensionless numeric literals and pure mathematical constants.
constexpr amrex::Real one
Definition: ERF_NumericalConstants.H:37
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
void immersed_wall_dist(amrex::MultiFab &wdist, const amrex::MultiFab &terrain_blank, const amrex::MultiFab &z_phys_nd, const amrex::MultiFab &z_phys_cc, const amrex::Box &domain, amrex::Real small_volfrac, amrex::MultiFab *wall_height=nullptr, const amrex::MultiFab *wall_height_crse=nullptr)
RealBdyConsMaps real_bdy_cons_maps(const bool read_density, const MoistureComponentIndices &moisture_indices, const bool use_wrf_bdy_qc_qi, const bool separate_hydrometeors)
Definition: ERF_Utils.H:83
void WeatherDataInterpolation(const double time)
void MomentumToVelocity(amrex::MultiFab &xvel_out, amrex::MultiFab &yvel_out, amrex::MultiFab &zvel_out, const amrex::MultiFab &cons_in, const amrex::MultiFab &xmom_in, const amrex::MultiFab &ymom_in, const amrex::MultiFab &zmom_in, const amrex::Box &domain, const amrex::Vector< amrex::BCRec > &domain_bcs_type_h, const amrex::MultiFab *c_vfrac=nullptr)
std::pair< int, amrex::Real > if_cf_surface_mismatch(const amrex::MultiFab &fine_tb, const amrex::BoxArray &fine_grids, const amrex::BoxArray &crse_grids, const amrex::DistributionMapping &crse_dmap, const amrex::Geometry &crse_geom, const amrex::IntVect &ratio, amrex::Real warn)
void compute_influx_outflux_bdy(amrex::FArrayBox &bdy_data_xlo, amrex::FArrayBox &bdy_data_xhi, amrex::FArrayBox &bdy_data_ylo, amrex::FArrayBox &bdy_data_yhi, amrex::Array< amrex::MultiFab *, AMREX_SPACEDIM > &area_vec, const amrex::Geometry &geom, amrex::Real &influx, amrex::Real &outflux, const int n)
void VelocityToMomentum(const amrex::MultiFab &xvel_in, const amrex::IntVect &xvel_ngrow, const amrex::MultiFab &yvel_in, const amrex::IntVect &yvel_ngrow, const amrex::MultiFab &zvel_in, const amrex::IntVect &zvel_ngrow, const amrex::MultiFab &cons_in, amrex::MultiFab &xmom_out, amrex::MultiFab &ymom_out, amrex::MultiFab &zmom_out, const amrex::Box &domain, const amrex::Vector< amrex::BCRec > &domain_bcs_type_h, const amrex::MultiFab *c_vfrac=nullptr)
void rebalance_columns(amrex::MultiFab &rho, amrex::MultiFab &theta, const amrex::MultiFab &qt, const amrex::MultiFab &qv, const amrex::MultiFab *z_phys, const amrex::Geometry &geom, const bool &maintain_Th, bool use_sfc=false)
amrex::Vector< amrex::MultiFab * > select_time_data(TimeLevelSel sel, amrex::MultiFab &old_mf, amrex::MultiFab &new_mf)
Definition: ERF_Utils.H:967
void cons_to_prim(const amrex::MultiFab &cons_state, amrex::MultiFab &S_prim, int ng)
void make_ib_wall_face_masks(const amrex::MultiFab &terrain_blank, amrex::MultiFab &mask13, amrex::MultiFab &mask23, amrex::MultiFab &mask33, const amrex::Box &domain, amrex::Real small_volfrac, int spacing=0, amrex::Real dz=amrex::Real(1.0), amrex::Real z0=amrex::Real(0.1))
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool wrf_bdy_has_separate_hydrometeors(const MoistureComponentIndices &moisture_indices) noexcept
Definition: ERF_Utils.H:35
void fill_wall_dist_ghost_cells(amrex::MultiFab &wdist, const amrex::Geometry &geom)
void Accumulate_Interval_Means(double dt, double &t_mean_cnt, amrex::MultiFab *interval_means, amrex::MultiFab &xvel, amrex::MultiFab &yvel, amrex::MultiFab &zvel, amrex::MultiFab &cons)
void enforceInOutSolvability_bdy(const amrex::MultiFab &rho0, amrex::FArrayBox &bdy_data_xlo, amrex::FArrayBox &bdy_data_xhi, amrex::FArrayBox &bdy_data_ylo, amrex::FArrayBox &bdy_data_yhi, amrex::Array< amrex::MultiFab *, AMREX_SPACEDIM > &area_vec, const amrex::Geometry &geom, const amrex::Vector< amrex::BCRec > &domain_bcs_type_h)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real quad_interp_1d(amrex::Real z, amrex::Real z0, amrex::Real p0, amrex::Real z1, amrex::Real p1, amrex::Real z2, amrex::Real p2)
Definition: ERF_Utils.H:914
void fine_compute_interior_ghost_rhs(const double &time, const double &delta_t, const int &width, const int &set_width, const amrex::Geometry &geom, ERFFillPatcher *FPr_c, ERFFillPatcher *FPr_u, ERFFillPatcher *FPr_v, ERFFillPatcher *FPr_w, amrex::Vector< amrex::BCRec > &domain_bcs_type, amrex::Vector< amrex::MultiFab > &S_rhs_f, amrex::Vector< amrex::MultiFab > &S_data_f)
void thinbody_wall_dist(std::unique_ptr< amrex::MultiFab > &wdist, amrex::Vector< amrex::IntVect > &xfaces, amrex::Vector< amrex::IntVect > &yfaces, amrex::Vector< amrex::IntVect > &zfaces, const amrex::Geometry &geomdata, std::unique_ptr< amrex::MultiFab > &z_phys_cc)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real wrf_moisture_target(const amrex::Real rho, const amrex::Real q_n, const amrex::Real q_np1, const amrex::Real alpha) noexcept
Definition: ERF_Utils.H:22
amrex::BoxArray ERFPostProcessBaseGrids(const amrex::Box &domain, bool decompose_in_z)
void make_zcc(const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, amrex::MultiFab &z_phys_cc)
void realbdy_bc_bxs_xy(const amrex::Box &bx, const amrex::Box &domain, const int &set_width, amrex::Box &bx_xlo, amrex::Box &bx_xhi, amrex::Box &bx_ylo, amrex::Box &bx_yhi, const amrex::IntVect &ng_vect=amrex::IntVect(0, 0, 0))
void Time_Avg_Vel_atCC(double dt, double &t_avg_cnt, amrex::MultiFab *vel_t_avg, amrex::MultiFab &xvel, amrex::MultiFab &yvel, amrex::MultiFab &zvel)
void realbdy_interior_bxs_xy(const amrex::Box &bx, const amrex::Box &domain, const int &width, amrex::Box &bx_xlo, amrex::Box &bx_xhi, amrex::Box &bx_ylo, amrex::Box &bx_yhi, const amrex::IntVect &ng_vect=amrex::IntVect(0, 0, 0), const bool get_int_ng=false)
AMREX_GPU_HOST AMREX_FORCE_INLINE void realbdy_compute_relaxation(const int &icomp, const int &num_var, const int &width, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dx, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &ProbLo, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &ProbHi, const amrex::Real &F1, const amrex::Box &bx_xlo, const amrex::Box &bx_xhi, const amrex::Box &bx_ylo, const amrex::Box &bx_yhi, const amrex::Array4< const amrex::Real > &arr_xlo, const amrex::Array4< const amrex::Real > &arr_xhi, const amrex::Array4< const amrex::Real > &arr_ylo, const amrex::Array4< const amrex::Real > &arr_yhi, const amrex::Array4< const amrex::Real > &data_arr, const amrex::Array4< amrex::Real > &rhs_arr, const amrex::Real &c_p, const amrex::Real &rdOcp, const int bdy_moist_nudge_type=0)
Definition: ERF_Utils.H:491
AMREX_GPU_HOST AMREX_FORCE_INLINE void ApplyInvertedMask(amrex::MultiFab &dst, const amrex::iMultiFab &imask, const int nghost=0)
Definition: ERF_Utils.H:861
int wrf_bdy_var_for_moisture_component(const int comp, const MoistureComponentIndices &moisture_indices, const bool use_wrf_bdy_qc_qi, const bool separate_hydrometeors=false)
Definition: ERF_Utils.H:44
void make_J(const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, amrex::MultiFab &detJ_cc)
AMREX_GPU_HOST AMREX_FORCE_INLINE void ApplyMask(amrex::MultiFab &dst, const amrex::iMultiFab &imask, const int nghost=0)
Definition: ERF_Utils.H:833
void realbdy_compute_interior_ghost_rhs(const double &total_time, const double &delta_t, const double &start_bdy_time, const double &final_bdy_time, const double &bdy_time_interval, const amrex::Real &nudge_factor, int width, const amrex::Geometry &geom, amrex::Vector< amrex::MultiFab > &S_rhs, amrex::Vector< amrex::MultiFab > &S_cur_data, amrex::Vector< amrex::Vector< amrex::FArrayBox >> &bdy_data_xlo, amrex::Vector< amrex::Vector< amrex::FArrayBox >> &bdy_data_xhi, amrex::Vector< amrex::Vector< amrex::FArrayBox >> &bdy_data_ylo, amrex::Vector< amrex::Vector< amrex::FArrayBox >> &bdy_data_yhi, std::unique_ptr< ReadBndryPlanes > &m_r2d, const amrex::Real &c_p, const amrex::Real &rdOcp, const bool use_wrf_bdy_density, const amrex::Real &bdy_rho_nudge_factor)
void if_average_down(const amrex::MultiFab &S_fine, amrex::MultiFab &S_crse, const amrex::MultiFab &beta_fine, const amrex::MultiFab &beta_crse, const amrex::MultiFab &vol_fine, int scomp, int ncomp, const amrex::IntVect &ratio)
void ConvertForProjection(const amrex::MultiFab &den_div, const amrex::MultiFab &den_mlt, amrex::MultiFab &xmom, amrex::MultiFab &ymom, amrex::MultiFab &zmom, const amrex::Box &domain, const amrex::Vector< amrex::BCRec > &domain_bcs_type_h)
void ChopGrids2D(amrex::BoxArray &ba, const amrex::Box &domain, int target_size)
void enforceInOutSolvability(int lev, amrex::Array< amrex::MultiFab *, AMREX_SPACEDIM > &vels_vec, amrex::Array< amrex::MultiFab *, AMREX_SPACEDIM > &area_vec, const amrex::Geometry &geom)
TimeLevelSel select_time_level(double time, double t_old, double t_new)
Definition: ERF_Utils.H:946
AMREX_GPU_HOST AMREX_FORCE_INLINE void realbdy_compute_moisture_relaxation(const amrex::GpuArray< int, 6 > &moisture_comps, const int n_targets, const int &width, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &dx, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &ProbLo, const amrex::GpuArray< amrex::Real, AMREX_SPACEDIM > &ProbHi, const amrex::Real &F1, const amrex::Box &bx_xlo, const amrex::Box &bx_xhi, const amrex::Box &bx_ylo, const amrex::Box &bx_yhi, const amrex::Array4< const amrex::Real > &arr_xlo, const amrex::Array4< const amrex::Real > &arr_xhi, const amrex::Array4< const amrex::Real > &arr_ylo, const amrex::Array4< const amrex::Real > &arr_yhi, const amrex::Array4< const amrex::Real > &data_arr, const amrex::Array4< amrex::Real > &rhs_arr)
Definition: ERF_Utils.H:705
TimeLevelSel
Definition: ERF_Utils.H:927
void make_areas(const amrex::Geometry &geom, amrex::MultiFab &z_phys_nd, amrex::MultiFab &ax, amrex::MultiFab &ay, amrex::MultiFab &az)
void make_qt(const amrex::MultiFab &cons_state, amrex::MultiFab &qt, int n_qstate_into_total)
Definition: ERF_FillPatcher.H:9
@ ymom
Definition: ERF_IndexDefines.H:274
@ zmom
Definition: ERF_IndexDefines.H:275
@ xmom
Definition: ERF_IndexDefines.H:273
@ rho
Definition: ERF_Kessler.H:25
@ theta
Definition: ERF_Kessler.H:26
@ qt
Definition: ERF_Kessler.H:30
@ qv
Definition: ERF_Kessler.H:31
@ ng
Definition: ERF_Morrison.H:51
@ QG
Definition: ERF_IndexDefines.H:184
@ QR
Definition: ERF_IndexDefines.H:182
@ QS
Definition: ERF_IndexDefines.H:183
@ R
Definition: ERF_IndexDefines.H:170
@ QV
Definition: ERF_IndexDefines.H:169
@ T
Definition: ERF_IndexDefines.H:168
@ QC
Definition: ERF_IndexDefines.H:171
@ QI
Definition: ERF_IndexDefines.H:172
@ alpha
Definition: ERF_SLM.H:151
@ 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
@ q
Definition: ERF_WSM6.H:294
real(c_double), parameter p0
Definition: ERF_module_model_constants.F90:40
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
The moisture data carried by the active microphysics scheme.
Definition: ERF_DataStruct.H:251
int qs
snow
Definition: ERF_DataStruct.H:266
int qr
rain
Definition: ERF_DataStruct.H:265
int qi
cloud ice
Definition: ERF_DataStruct.H:264
int qv
water vapor
Definition: ERF_DataStruct.H:262
int qc
cloud liquid water
Definition: ERF_DataStruct.H:263
int qg
graupel
Definition: ERF_DataStruct.H:267
Definition: ERF_Utils.H:76
amrex::Vector< int > map
Definition: ERF_Utils.H:78
amrex::Vector< int > bnd
Definition: ERF_Utils.H:79
amrex::Vector< int > read
Definition: ERF_Utils.H:77