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 "AMReX.H"
5 #include "AMReX_MultiFab.H"
6 #include "AMReX_BCRec.H"
9 #include "ERF_DataStruct.H"
10 #include "ERF_IndexDefines.H"
11 #include "ERF_SurfaceLayer.H"
12 #include "ERF_FillPatcher.H"
13 #include "ERF_ReadBndryPlanes.H"
14 
15 /** Build one density-weighted, nonnegative WRF moisture target. */
16 AMREX_GPU_HOST_DEVICE
17 AMREX_FORCE_INLINE
20  const amrex::Real q_n,
21  const amrex::Real q_np1,
22  const amrex::Real alpha) noexcept
23 {
24  const amrex::Real q = (one - alpha) * q_n + alpha * q_np1;
25  return rho * amrex::max(q, amrex::Real(0.0));
26 }
27 
28 /** True when ERF carries all five hydrometeor mass species separately. */
29 AMREX_GPU_HOST_DEVICE
30 AMREX_FORCE_INLINE
31 bool
33 {
34  return moisture_indices.qc >= 0 && moisture_indices.qi >= 0 &&
35  moisture_indices.qr >= 0 && moisture_indices.qs >= 0 &&
36  moisture_indices.qg >= 0;
37 }
38 
39 /** Map an active conserved moisture component to its real-boundary field. */
40 inline int
42  const MoistureComponentIndices& moisture_indices,
43  const bool use_wrf_bdy_qc_qi,
44  const bool separate_hydrometeors = false)
45 {
46  if (comp == moisture_indices.qv) { return RealBdyVars::QV; }
47  if (use_wrf_bdy_qc_qi) {
48  if (comp == moisture_indices.qc) { return RealBdyVars::QC; }
49  if (moisture_indices.qi >= 0 && comp == moisture_indices.qi) {
50  return RealBdyVars::QI;
51  }
52  if (separate_hydrometeors) {
53  if (comp == moisture_indices.qr) { return RealBdyHydrometeorVars::QR; }
54  if (comp == moisture_indices.qs) { return RealBdyHydrometeorVars::QS; }
55  if (comp == moisture_indices.qg) { return RealBdyHydrometeorVars::QG; }
56  }
57  }
58  return -1;
59 }
60 
61 /*
62  * Rebalance state to satisfy both EOS and HSE one column at a time
63  */
64 void
65 rebalance_columns (amrex::MultiFab& rho,
66  amrex::MultiFab& theta,
67  const amrex::MultiFab& qt,
68  const amrex::MultiFab& qv,
69  const amrex::MultiFab* z_phys,
70  const amrex::Geometry& geom,
71  const bool& maintain_Th,
72  bool use_sfc = false);
73 
74 /*
75  * Create a new BoxArray in which every grid touches the bottom boundary
76  */
77 void ChopGrids2D (amrex::BoxArray& ba, const amrex::Box& domain, int target_size);
78 
79 /*
80  * Create a new BoxArray with exactly the number of boxes as MPI ranks.
81  * This is designed to work only on the base level which covers the entire domain.
82  */
83 amrex::BoxArray
84 ERFPostProcessBaseGrids (const amrex::Box& domain, bool decompose_in_z);
85 
86 /**
87  * Convert conservative state to primitive variables.
88  * @param[in] cons_state Conservative state MultiFab.
89  * @param[out] S_prim Primitive state MultiFab.
90  * @param[in] ng Number of ghost cells.
91  */
92 void
93 cons_to_prim(const amrex::MultiFab& cons_state, amrex::MultiFab& S_prim, int ng);
94 
95 /**
96  * Fill the ghost cells of the wall distance field, which is only computed on
97  * the valid region, so that operators reading from grown boxes do not see the
98  * sentinel value used to initialize it.
99  * @param[inout] wdist MultiFab holding the wall distance.
100  * @param[in] geom Geometry at this level.
101  */
102 void
103 fill_wall_dist_ghost_cells (amrex::MultiFab& wdist, const amrex::Geometry& geom);
104 
105 /**
106  * Compute total water mixing ratio from conservative state.
107  * @param[in] cons_state Conservative state MultiFab.
108  * @param[out] qt MultiFab to store total water.
109  * @param[in] n_qstate_into_total Number of components to include in total water.
110  */
111 void
112 make_qt(const amrex::MultiFab& cons_state, amrex::MultiFab& qt, int n_qstate_into_total);
113 
114 /*
115  * Create the Jacobian for the metric transformation when use_terrain is true
116  */
117 void make_J (const amrex::Geometry& geom,
118  amrex::MultiFab& z_phys_nd,
119  amrex::MultiFab& detJ_cc);
120 
121 void make_areas (const amrex::Geometry& geom,
122  amrex::MultiFab& z_phys_nd,
123  amrex::MultiFab& ax,
124  amrex::MultiFab& ay,
125  amrex::MultiFab& az);
126 
127 /*
128  * Average z_phys_nd on nodes to cell centers
129  */
130 void make_zcc (const amrex::Geometry& geom,
131  amrex::MultiFab& z_phys_nd,
132  amrex::MultiFab& z_phys_cc);
133 
134 /*
135  * Convert momentum to velocity by dividing by density averaged onto faces
136  */
137 void MomentumToVelocity (amrex::MultiFab& xvel_out,
138  amrex::MultiFab& yvel_out,
139  amrex::MultiFab& zvel_out,
140  const amrex::MultiFab& cons_in,
141  const amrex::MultiFab& xmom_in,
142  const amrex::MultiFab& ymom_in,
143  const amrex::MultiFab& zmom_in,
144  const amrex::Box& domain,
145  const amrex::Vector<amrex::BCRec>& domain_bcs_type_h,
146  const amrex::MultiFab* c_vfrac = nullptr // optional
147  );
148 
149 /*
150  * Convert velocity to momentum by multiplying by density averaged onto faces
151  */
152 void VelocityToMomentum (const amrex::MultiFab& xvel_in,
153  const amrex::IntVect & xvel_ngrow,
154  const amrex::MultiFab& yvel_in,
155  const amrex::IntVect & yvel_ngrow,
156  const amrex::MultiFab& zvel_in,
157  const amrex::IntVect & zvel_ngrow,
158  const amrex::MultiFab& cons_in,
159  amrex::MultiFab& xmom_out,
160  amrex::MultiFab& ymom_out,
161  amrex::MultiFab& zmom_out,
162  const amrex::Box& domain,
163  const amrex::Vector<amrex::BCRec>& domain_bcs_type_h,
164  const amrex::MultiFab* c_vfrac = nullptr // optional
165  );
166 
167 /*
168  * Convert (den_div u) to (den_mlt u) by multiplying by (den_mlt/den_div)
169  */
170 void
171 ConvertForProjection (const amrex::MultiFab& den_div, const amrex::MultiFab& den_mlt,
172  amrex::MultiFab& xmom, amrex::MultiFab& ymom, amrex::MultiFab& zmom,
173  const amrex::Box& domain, const amrex::Vector<amrex::BCRec>& domain_bcs_type_h);
174 
175 /*
176  * Compute lateral boundary mass influx/outflux from base-state-density-weighted
177  * boundary normal velocities.
178  */
179 void
180 compute_influx_outflux_bdy (amrex::FArrayBox& bdy_data_xlo, amrex::FArrayBox& bdy_data_xhi,
181  amrex::FArrayBox& bdy_data_ylo, amrex::FArrayBox& bdy_data_yhi,
182  amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& area_vec,
183  const amrex::Geometry& geom,
184  amrex::Real& influx, amrex::Real& outflux,
185  const int n);
186 
187 /*
188  * \brief Enforces solvability on lateral boundary data by scaling outflow to
189  * match with inflow.
190  */
191 void enforceInOutSolvability_bdy (const amrex::MultiFab& rho0,
192  amrex::FArrayBox& bdy_data_xlo,
193  amrex::FArrayBox& bdy_data_xhi,
194  amrex::FArrayBox& bdy_data_ylo,
195  amrex::FArrayBox& bdy_data_yhi,
196  amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& area_vec,
197  const amrex::Geometry& geom,
198  const amrex::Vector<amrex::BCRec>& domain_bcs_type_h);
199 
200 /*
201  * \brief Enforces solvability by scaling outflow to match with inflow.
202  *
203  */
205  amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& vels_vec,
206  amrex::Array<amrex::MultiFab*, AMREX_SPACEDIM>& area_vec,
207  const amrex::Geometry& geom);
208 
209 /*
210  * Compute boxes for looping over interior/exterior ghost cells
211  * for use by fillpatch, erf_slow_rhs_pre, and erf_slow_rhs_post
212  */
213 void realbdy_interior_bxs_xy (const amrex::Box& bx,
214  const amrex::Box& domain,
215  const int& width,
216  amrex::Box& bx_xlo,
217  amrex::Box& bx_xhi,
218  amrex::Box& bx_ylo,
219  amrex::Box& bx_yhi,
220  const amrex::IntVect& ng_vect=amrex::IntVect(0,0,0),
221  const bool get_int_ng=false);
222 
223 /*
224  * Compute boxes for looping over set region cells
225  * for use by fillpatch, erf_slow_rhs_pre, and erf_slow_rhs_post
226  */
227 void realbdy_bc_bxs_xy (const amrex::Box& bx,
228  const amrex::Box& domain,
229  const int& set_width,
230  amrex::Box& bx_xlo,
231  amrex::Box& bx_xhi,
232  amrex::Box& bx_ylo,
233  amrex::Box& bx_yhi,
234  const amrex::IntVect& ng_vect=amrex::IntVect(0,0,0));
235 
236 /*
237  * Compute relaxation region RHS with wrfbdy
238  */
239 void realbdy_compute_interior_ghost_rhs (const double& total_time,
240  const double& delta_t,
241  const double& start_bdy_time,
242  const double& final_bdy_time,
243  const double& bdy_time_interval,
244  const amrex::Real& nudge_factor,
245  int width,
246  const amrex::Geometry& geom,
247  amrex::Vector<amrex::MultiFab>& S_rhs,
248  amrex::Vector<amrex::MultiFab>& S_cur_data,
249  amrex::Vector<amrex::Vector<amrex::FArrayBox>>& bdy_data_xlo,
250  amrex::Vector<amrex::Vector<amrex::FArrayBox>>& bdy_data_xhi,
251  amrex::Vector<amrex::Vector<amrex::FArrayBox>>& bdy_data_ylo,
252  amrex::Vector<amrex::Vector<amrex::FArrayBox>>& bdy_data_yhi,
253  std::unique_ptr<ReadBndryPlanes>& m_r2d,
254  const amrex::Real& c_p,
255  const amrex::Real& rdOcp,
256  const bool use_wrf_bdy_density,
257  const amrex::Real& bdy_rho_nudge_factor);
258 
259 /*
260  * Compute relaxation region RHS at fine-crse interface
261  */
262 void
264  const double& delta_t,
265  const int& width,
266  const int& set_width,
267  const amrex::Geometry& geom,
268  ERFFillPatcher* FPr_c,
269  ERFFillPatcher* FPr_u,
270  ERFFillPatcher* FPr_v,
271  ERFFillPatcher* FPr_w,
272  amrex::Vector<amrex::BCRec>& domain_bcs_type,
273  amrex::Vector<amrex::MultiFab>& S_rhs_f,
274  amrex::Vector<amrex::MultiFab>& S_data_f);
275 
276 /*
277  * Accumulate time averaged velocity fields
278  */
279 void
280 Time_Avg_Vel_atCC (double dt,
281  double& t_avg_cnt,
282  amrex::MultiFab* vel_t_avg,
283  amrex::MultiFab& xvel,
284  amrex::MultiFab& yvel,
285  amrex::MultiFab& zvel);
286 
287 /**
288  * Accumulate time-weighted cell-centered velocity/theta first and second moments.
289  * @param[in] dt accumulation interval
290  * @param[in,out] t_mean_cnt accumulated time
291  * @param[in,out] interval_means ten-component moment storage
292  * @param[in] xvel x-face velocity
293  * @param[in] yvel y-face velocity
294  * @param[in] zvel z-face velocity
295  * @param[in] cons conserved cell-centered state
296  */
297 void
299  double& t_mean_cnt,
300  amrex::MultiFab* interval_means,
301  amrex::MultiFab& xvel,
302  amrex::MultiFab& yvel,
303  amrex::MultiFab& zvel,
304  amrex::MultiFab& cons);
305 
306 /**
307  * Compute the nudging relaxation
308  *
309  * @param[in] delta_t time step
310  * @param[in] icomp component offset
311  * @param[in] num_var number of variables to loop
312  * @param[in] width width of wrf bdy file
313  * @param[in] dom_lo low bound of domain
314  * @param[in] dom_hi high bound of domain
315  * @param[in] F1 drift relaxation parameter
316  * @param[in] bx_xlo box for low x relaxation
317  * @param[in] bx_xhi box for high x relaxation
318  * @param[in] bx_ylo box for low y relaxation
319  * @param[in] bx_yhi box for high y relaxation
320  * @param[in] arr_xlo array for low x relaxation
321  * @param[in] arr_xhi array for high x relaxation
322  * @param[in] arr_ylo array for low y relaxation
323  * @param[in] arr_yhi array for high y relaxation
324  * @param[in] data_arr data array
325  * @param[out] rhs_arr RHS array
326  */
327 AMREX_GPU_HOST
328 AMREX_FORCE_INLINE
329 void
330 realbdy_compute_relaxation (const int& icomp,
331  const int& num_var,
332  const int& width,
333  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& dx,
334  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbLo,
335  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbHi,
336  const amrex::Real& F1,
337  const amrex::Box& bx_xlo,
338  const amrex::Box& bx_xhi,
339  const amrex::Box& bx_ylo,
340  const amrex::Box& bx_yhi,
341  const amrex::Array4<const amrex::Real>& arr_xlo,
342  const amrex::Array4<const amrex::Real>& arr_xhi,
343  const amrex::Array4<const amrex::Real>& arr_ylo,
344  const amrex::Array4<const amrex::Real>& arr_yhi,
345  const amrex::Array4<const amrex::Real>& data_arr,
346  const amrex::Array4<amrex::Real>& rhs_arr,
347  const amrex::Real& c_p,
348  const amrex::Real& rdOcp,
349  const int bdy_moist_nudge_type=0)
350 {
351  amrex::IntVect iv = bx_xlo.type();
352  amrex::Real ioff = (iv[0]==1) ? zero : myhalf;
353  amrex::Real joff = (iv[1]==1) ? zero : myhalf;
354 
355  // These are defined in ERF_Constants.H
356  amrex::Real l_rdOcp = rdOcp;
357  amrex::Real cond_fac = lcond / c_p; // condensation
358  amrex::Real sub_fac = lsub / c_p; // sublimation
359 
360  int nq = num_var;
361 
362  amrex::ParallelFor( bx_xlo, bx_xhi,
363  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
364  {
365  // Corners with x boxes
366  amrex::Real x = ProbLo[0] + (i + ioff) * dx[0];
367  amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
368  amrex::Real x_end = ProbLo[0] + width * dx[0];
369  amrex::Real y_end = ProbLo[1] + width * dx[1];
370  amrex::Real y_strt = ProbHi[1] - width * dx[1];
371  amrex::Real xi = (x_end - x) / (x_end - ProbLo[0]);
372  amrex::Real eta_lo = (y < y_end ) ? (y_end - y) / (y_end - ProbLo[1]) : zero;
373  amrex::Real eta_hi = (y > y_strt) ? (y - y_strt) / (ProbHi[1] - y_strt) : zero;
374  amrex::Real eta = std::max(eta_lo,eta_hi);
375  amrex::Real Factor = std::max(xi*xi,eta*eta) * F1;
376 
377  if (icomp == RhoQ1_comp)
378  {
379  amrex::Real exner_pi = getExnergivenRTh(data_arr(i,j,k,RhoTheta_comp),l_rdOcp,
380  data_arr(i,j,k,RhoQ1_comp)/data_arr(i,j,k,Rho_comp));
381 
382  // qv
383  amrex::Real delta = arr_xlo(i,j,k,0) - data_arr(i,j,k,icomp);
384  rhs_arr(i,j,k,icomp) += Factor*delta;
385 
386  if (bdy_moist_nudge_type==2) {
387  // NOTE: we only operate on qv (above), qc and qi here; the
388  // precipitating species (qr/qs/qg) are left untouched.
389 
390  // qc and heat source term due to evaporation
391  delta = -data_arr(i,j,k,RhoQ2_comp); // This effectively nudges to 0
392  rhs_arr(i,j,k,RhoQ2_comp ) += Factor * delta;
393  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * cond_fac / exner_pi;
394 
395  // qi and heat source term due to sublimation
396  if (nq > 3) { // nq > 3 guarantees that RhoQ3 is ice
397  delta = -data_arr(i,j,k,RhoQ3_comp); // This effectively nudges to 0
398  rhs_arr(i,j,k,RhoQ3_comp ) += Factor * delta;
399  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * sub_fac / exner_pi;
400  }
401  } // moist_nudge_type
402  } else {
403  for (int n = 0; n < nq; n++) {
404  amrex::Real delta = arr_xlo(i,j,k,n) - data_arr(i,j,k,n+icomp);
405  rhs_arr(i,j,k,n+icomp) += Factor*delta;
406  }
407  }
408  },
409  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
410  {
411  // Corners with x boxes
412  amrex::Real x = ProbLo[0] + (i + ioff) * dx[0];
413  amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
414  amrex::Real x_strt = ProbHi[0] - width * dx[0];
415  amrex::Real y_strt = ProbHi[1] - width * dx[1];
416  amrex::Real y_end = ProbLo[1] + width * dx[1];
417  amrex::Real xi = (x - x_strt) / (ProbHi[0] - x_strt);
418  amrex::Real eta_lo = (y < y_end ) ? (y_end - y) / (y_end - ProbLo[1]) : zero;
419  amrex::Real eta_hi = (y > y_strt) ? (y - y_strt) / (ProbHi[1] - y_strt) : zero;
420  amrex::Real eta = std::max(eta_lo,eta_hi);
421  amrex::Real Factor = std::max(xi*xi,eta*eta) * F1;
422 
423  if (icomp == RhoQ1_comp)
424  {
425  amrex::Real exner_pi = getExnergivenRTh(data_arr(i,j,k,RhoTheta_comp),l_rdOcp,
426  data_arr(i,j,k,RhoQ1_comp)/data_arr(i,j,k,Rho_comp));
427 
428  // qv
429  amrex::Real delta = arr_xhi(i,j,k,0) - data_arr(i,j,k,icomp);
430  rhs_arr(i,j,k,icomp) += Factor*delta;
431 
432  if (bdy_moist_nudge_type==2) {
433  // NOTE: we only operate on qv (above), qc and qi here; the
434  // precipitating species (qr/qs/qg) are left untouched.
435 
436  // qc and heat source term due to evaporation
437  delta = -data_arr(i,j,k,RhoQ2_comp); // This effectively nudges to 0
438  rhs_arr(i,j,k,RhoQ2_comp ) += Factor*delta;
439  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * cond_fac / exner_pi;
440 
441  // qi and heat source term due to sublimation
442  if (nq > 3) { // nq > 3 guarantees that RhoQ3 is ice
443  delta = -data_arr(i,j,k,RhoQ3_comp); // This effectively nudges to 0
444  rhs_arr(i,j,k,RhoQ3_comp ) += Factor * delta;
445  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * sub_fac / exner_pi;
446  }
447  } // moist_nudge_type
448  } else {
449  for (int n = 0; n < nq; n++) {
450  amrex::Real delta = arr_xhi(i,j,k,n) - data_arr(i,j,k,n+icomp);
451  rhs_arr(i,j,k,n+icomp) += Factor*delta;
452  }
453  }
454  });
455 
456  amrex::ParallelFor( bx_ylo, bx_yhi,
457  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
458  {
459  // No corners for y boxes
460  amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
461  amrex::Real y_end = ProbLo[1] + width * dx[1];
462  amrex::Real eta = (y_end - y) / (y_end - ProbLo[1]);
463  amrex::Real Factor = eta*eta * F1;
464 
465  if (icomp == RhoQ1_comp)
466  {
467  amrex::Real exner_pi = getExnergivenRTh(data_arr(i,j,k,RhoTheta_comp),l_rdOcp,
468  data_arr(i,j,k,RhoQ1_comp)/data_arr(i,j,k,Rho_comp));
469  // qv
470  amrex::Real delta = arr_ylo(i,j,k,0) - data_arr(i,j,k,icomp);
471  rhs_arr(i,j,k,icomp) += Factor*delta;
472 
473  if (bdy_moist_nudge_type==2) {
474  // NOTE: we only operate on qv (above), qc and qi here; the
475  // precipitating species (qr/qs/qg) are left untouched.
476 
477  // qc and heat source term due to evaporation
478  delta = -data_arr(i,j,k,RhoQ2_comp); // This effectively nudges to 0
479  rhs_arr(i,j,k,RhoQ2_comp ) += Factor*delta;
480  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * cond_fac / exner_pi;
481 
482  // qi and heat source term due to sublimation
483  if (nq > 3) { // nq > 3 guarantees that RhoQ3 is ice
484  delta = -data_arr(i,j,k,RhoQ3_comp); // This effectively nudges to 0
485  rhs_arr(i,j,k,RhoQ3_comp ) += Factor * delta;
486  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * sub_fac / exner_pi;
487  }
488  } // moist_nudge_type
489  } else {
490  for (int n = 0; n < nq; n++) {
491  amrex::Real delta = arr_ylo(i,j,k,n) - data_arr(i,j,k,n+icomp);
492  rhs_arr(i,j,k,n+icomp) += Factor*delta;
493  }
494  }
495  },
496  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
497  {
498  // No corners for y boxes
499  amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
500  amrex::Real y_strt = ProbHi[1] - width * dx[1];
501  amrex::Real eta = (y - y_strt) / (ProbHi[1] - y_strt);
502  amrex::Real Factor = eta*eta * F1;
503 
504  if (icomp == RhoQ1_comp)
505  {
506  amrex::Real exner_pi = getExnergivenRTh(data_arr(i,j,k,RhoTheta_comp),l_rdOcp,
507  data_arr(i,j,k,RhoQ1_comp)/data_arr(i,j,k,Rho_comp));
508  // qv
509  amrex::Real delta = arr_yhi(i,j,k,0) - data_arr(i,j,k,icomp);
510  rhs_arr(i,j,k,icomp) += Factor*delta;
511 
512  if (bdy_moist_nudge_type==2) {
513  // NOTE: we only operate on qv (above), qc and qi here; the
514  // precipitating species (qr/qs/qg) are left untouched.
515 
516  // qc and heat source term due to evaporation
517  delta = -data_arr(i,j,k,RhoQ2_comp); // This effectively nudges to 0
518  rhs_arr(i,j,k,RhoQ2_comp ) += Factor * delta;
519  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * cond_fac / exner_pi;
520 
521  // qi and heat source term due to sublimation
522  if (nq > 3) { // nq > 3 guarantees that RhoQ3 is ice
523  delta = -data_arr(i,j,k,RhoQ3_comp); // This effectively nudges to 0
524  rhs_arr(i,j,k,RhoQ3_comp ) += Factor * delta;
525  rhs_arr(i,j,k,RhoTheta_comp) += Factor * delta * sub_fac / exner_pi;
526  }
527  } // moist_nudge_type
528  } else {
529  for (int n = 0; n < nq; n++) {
530  amrex::Real delta = arr_yhi(i,j,k,n) - data_arr(i,j,k,n+icomp);
531  rhs_arr(i,j,k,n+icomp) += Factor*delta;
532  }
533  }
534  });
535 }
536 
537 /**
538  * Apply Davies relaxation to explicitly mapped moisture components. Target
539  * component n corresponds to state component moisture_comps[n].
540  */
541 AMREX_GPU_HOST
542 AMREX_FORCE_INLINE
543 void
545  const amrex::GpuArray<int,6>& moisture_comps,
546  const int n_targets,
547  const int& width,
548  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& dx,
549  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbLo,
550  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbHi,
551  const amrex::Real& F1,
552  const amrex::Box& bx_xlo,
553  const amrex::Box& bx_xhi,
554  const amrex::Box& bx_ylo,
555  const amrex::Box& bx_yhi,
556  const amrex::Array4<const amrex::Real>& arr_xlo,
557  const amrex::Array4<const amrex::Real>& arr_xhi,
558  const amrex::Array4<const amrex::Real>& arr_ylo,
559  const amrex::Array4<const amrex::Real>& arr_yhi,
560  const amrex::Array4<const amrex::Real>& data_arr,
561  const amrex::Array4<amrex::Real>& rhs_arr)
562 {
563  const amrex::IntVect iv = bx_xlo.type();
564  const amrex::Real ioff = (iv[0] == 1) ? zero : myhalf;
565  const amrex::Real joff = (iv[1] == 1) ? zero : myhalf;
566 
567  amrex::ParallelFor(bx_xlo, bx_xhi,
568  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
569  {
570  const amrex::Real x = ProbLo[0] + (i + ioff) * dx[0];
571  const amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
572  const amrex::Real x_end = ProbLo[0] + width * dx[0];
573  const amrex::Real y_end = ProbLo[1] + width * dx[1];
574  const amrex::Real y_strt = ProbHi[1] - width * dx[1];
575  const amrex::Real xi = (x_end - x) / (x_end - ProbLo[0]);
576  const amrex::Real eta_lo = (y < y_end) ? (y_end - y) / (y_end - ProbLo[1]) : amrex::Real(0.0);
577  const amrex::Real eta_hi = (y > y_strt) ? (y - y_strt) / (ProbHi[1] - y_strt) : amrex::Real(0.0);
578  const amrex::Real factor = amrex::max(xi*xi, amrex::max(eta_lo,eta_hi)*amrex::max(eta_lo,eta_hi)) * F1;
579  for (int n = 0; n < n_targets; ++n) {
580  const int comp = moisture_comps[n];
581  if (comp >= 0) {
582  rhs_arr(i,j,k,comp) += factor * (arr_xlo(i,j,k,n) - data_arr(i,j,k,comp));
583  }
584  }
585  },
586  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
587  {
588  const amrex::Real x = ProbLo[0] + (i + ioff) * dx[0];
589  const amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
590  const amrex::Real x_strt = ProbHi[0] - width * dx[0];
591  const amrex::Real y_end = ProbLo[1] + width * dx[1];
592  const amrex::Real y_strt = ProbHi[1] - width * dx[1];
593  const amrex::Real xi = (x - x_strt) / (ProbHi[0] - x_strt);
594  const amrex::Real eta_lo = (y < y_end) ? (y_end - y) / (y_end - ProbLo[1]) : amrex::Real(0.0);
595  const amrex::Real eta_hi = (y > y_strt) ? (y - y_strt) / (ProbHi[1] - y_strt) : amrex::Real(0.0);
596  const amrex::Real eta = amrex::max(eta_lo,eta_hi);
597  const amrex::Real factor = amrex::max(xi*xi, eta*eta) * F1;
598  for (int n = 0; n < n_targets; ++n) {
599  const int comp = moisture_comps[n];
600  if (comp >= 0) {
601  rhs_arr(i,j,k,comp) += factor * (arr_xhi(i,j,k,n) - data_arr(i,j,k,comp));
602  }
603  }
604  });
605 
606  amrex::ParallelFor(bx_ylo, bx_yhi,
607  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
608  {
609  const amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
610  const amrex::Real y_end = ProbLo[1] + width * dx[1];
611  const amrex::Real eta = (y_end - y) / (y_end - ProbLo[1]);
612  const amrex::Real factor = eta*eta * F1;
613  for (int n = 0; n < n_targets; ++n) {
614  const int comp = moisture_comps[n];
615  if (comp >= 0) {
616  rhs_arr(i,j,k,comp) += factor * (arr_ylo(i,j,k,n) - data_arr(i,j,k,comp));
617  }
618  }
619  },
620  [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
621  {
622  const amrex::Real y = ProbLo[1] + (j + joff) * dx[1];
623  const amrex::Real y_strt = ProbHi[1] - width * dx[1];
624  const amrex::Real eta = (y - y_strt) / (ProbHi[1] - y_strt);
625  const amrex::Real factor = eta*eta * F1;
626  for (int n = 0; n < n_targets; ++n) {
627  const int comp = moisture_comps[n];
628  if (comp >= 0) {
629  rhs_arr(i,j,k,comp) += factor * (arr_yhi(i,j,k,n) - data_arr(i,j,k,comp));
630  }
631  }
632  });
633 }
634 
635 // Backward-compatible three-species overload used by existing unit tests and
636 // callers that only target qv/qc/qi.
637 AMREX_GPU_HOST
638 AMREX_FORCE_INLINE
639 void
641  const amrex::GpuArray<int,3>& moisture_comps,
642  const int& width,
643  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& dx,
644  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbLo,
645  const amrex::GpuArray<amrex::Real,AMREX_SPACEDIM>& ProbHi,
646  const amrex::Real& F1,
647  const amrex::Box& bx_xlo,
648  const amrex::Box& bx_xhi,
649  const amrex::Box& bx_ylo,
650  const amrex::Box& bx_yhi,
651  const amrex::Array4<const amrex::Real>& arr_xlo,
652  const amrex::Array4<const amrex::Real>& arr_xhi,
653  const amrex::Array4<const amrex::Real>& arr_ylo,
654  const amrex::Array4<const amrex::Real>& arr_yhi,
655  const amrex::Array4<const amrex::Real>& data_arr,
656  const amrex::Array4<amrex::Real>& rhs_arr)
657 {
658  const amrex::GpuArray<int,6> extended_comps = {
659  moisture_comps[0], moisture_comps[1], moisture_comps[2], -1, -1, -1};
661  extended_comps, 3, width, dx, ProbLo, ProbHi, F1,
662  bx_xlo, bx_xhi, bx_ylo, bx_yhi,
663  arr_xlo, arr_xhi, arr_ylo, arr_yhi, data_arr, rhs_arr);
664 }
665 
666 /*
667  * Effectively a Multiply for a MultiFab and an iMultiFab mask
668  */
669 AMREX_GPU_HOST
670 AMREX_FORCE_INLINE
671 void
672 ApplyMask (amrex::MultiFab& dst,
673  const amrex::iMultiFab& imask,
674  const int nghost = 0)
675 {
676  for (amrex::MFIter mfi(dst,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
677  {
678  const amrex::Box& bx = mfi.growntilebox(nghost);
679  if (bx.ok())
680  {
681  auto dstFab = dst.array(mfi);
682  const auto maskFab = imask.const_array(mfi);
683  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
684  {
685  dstFab(i,j,k) *= maskFab(i,j,k);
686  });
687  }
688  }
689 }
690 
691 /**
692  * Multiply a MultiFab by the inverse of an integer mask.
693  * @param[in,out] dst MultiFab to be masked.
694  * @param[in] imask Integer mask MultiFab.
695  * @param[in] nghost Number of ghost cells to include.
696  */
697 AMREX_GPU_HOST
698 AMREX_FORCE_INLINE
699 void
700 ApplyInvertedMask (amrex::MultiFab& dst,
701  const amrex::iMultiFab& imask,
702  const int nghost = 0)
703 {
704  for (amrex::MFIter mfi(dst,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
705  {
706  const amrex::Box& bx = mfi.growntilebox(nghost);
707  if (bx.ok())
708  {
709  auto dstFab = dst.array(mfi);
710  const auto maskFab = imask.const_array(mfi);
711  ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
712  {
713  dstFab(i,j,k) *= (1-maskFab(i,j,k));
714  });
715  }
716  }
717 }
718 
719 /**
720  * Compute the distance to thin-body walls.
721  * @param[out] wdist MultiFab to store wall distances.
722  * @param[in] xfaces Indices of x-faces forming walls.
723  * @param[in] yfaces Indices of y-faces forming walls.
724  * @param[in] zfaces Indices of z-faces forming walls.
725  * @param[in] geomdata Geometry used for physical distance.
726  * @param[in] z_phys_cc Cell-centered physical height.
727  */
728 void
729 thinbody_wall_dist (std::unique_ptr<amrex::MultiFab>& wdist,
730  amrex::Vector<amrex::IntVect>& xfaces,
731  amrex::Vector<amrex::IntVect>& yfaces,
732  amrex::Vector<amrex::IntVect>& zfaces,
733  const amrex::Geometry& geomdata,
734  std::unique_ptr<amrex::MultiFab>& z_phys_cc);
735 
736 
737 void WeatherDataInterpolation(const double time);
738 
739 /**
740  * Perform quadratic interpolation in one dimension.
741  * @param[in] z Interpolation coordinate.
742  * @param[in] z0 Coordinate of first point.
743  * @param[in] p0 Value at first point.
744  * @param[in] z1 Coordinate of second point.
745  * @param[in] p1 Value at second point.
746  * @param[in] z2 Coordinate of third point.
747  * @param[in] p2 Value at third point.
748  * @return Interpolated value.
749  */
750 AMREX_GPU_HOST_DEVICE
751 AMREX_FORCE_INLINE
755  amrex::Real z1, amrex::Real p1,
756  amrex::Real z2, amrex::Real p2)
757 {
758  return p0 * ( (z - z1) * (z - z2) ) / ( (z0 - z1) * (z0 - z2) )
759  + p1 * ( (z - z0) * (z - z2) ) / ( (z1 - z0) * (z1 - z2) )
760  + p2 * ( (z - z0) * (z - z1) ) / ( (z2 - z0) * (z2 - z1) );
761 }
762 
763 #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:39
#define RhoTheta_comp
Definition: ERF_IndexDefines.H:40
#define RhoQ2_comp
Definition: ERF_IndexDefines.H:46
#define RhoQ3_comp
Definition: ERF_IndexDefines.H:47
#define RhoQ1_comp
Definition: ERF_IndexDefines.H:45
Real z0
Definition: ERF_InitCustomPertVels_ScalarAdvDiff.H:8
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: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
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)
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)
void cons_to_prim(const amrex::MultiFab &cons_state, amrex::MultiFab &S_prim, int ng)
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE bool wrf_bdy_has_separate_hydrometeors(const MoistureComponentIndices &moisture_indices) noexcept
Definition: ERF_Utils.H:32
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:753
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:19
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:330
AMREX_GPU_HOST AMREX_FORCE_INLINE void ApplyInvertedMask(amrex::MultiFab &dst, const amrex::iMultiFab &imask, const int nghost=0)
Definition: ERF_Utils.H:700
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:41
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:672
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 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)
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:544
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:234
@ zmom
Definition: ERF_IndexDefines.H:235
@ xmom
Definition: ERF_IndexDefines.H:233
@ theta
Definition: ERF_SLM.H:19
@ rho
Definition: ERF_Kessler.H:25
@ qt
Definition: ERF_Kessler.H:30
@ qv
Definition: ERF_Kessler.H:31
@ ng
Definition: ERF_Morrison.H:50
@ QG
Definition: ERF_IndexDefines.H:144
@ QR
Definition: ERF_IndexDefines.H:142
@ QS
Definition: ERF_IndexDefines.H:143
@ QV
Definition: ERF_IndexDefines.H:129
@ QC
Definition: ERF_IndexDefines.H:131
@ QI
Definition: ERF_IndexDefines.H:132
@ xvel
Definition: ERF_IndexDefines.H:215
@ cons
Definition: ERF_IndexDefines.H:214
@ zvel
Definition: ERF_IndexDefines.H:217
@ yvel
Definition: ERF_IndexDefines.H:216
@ q
Definition: ERF_WSM6.H:273
real(c_double), parameter p0
Definition: ERF_module_model_constants.F90:40
real(kind=kind_phys), parameter, private alpha
Definition: ERF_module_mp_wdm6.F90:62
The moisture data carried by the active microphysics scheme.
Definition: ERF_DataStruct.H:223
int qs
snow
Definition: ERF_DataStruct.H:238
int qr
rain
Definition: ERF_DataStruct.H:237
int qi
cloud ice
Definition: ERF_DataStruct.H:236
int qv
water vapor
Definition: ERF_DataStruct.H:234
int qc
cloud liquid water
Definition: ERF_DataStruct.H:235
int qg
graupel
Definition: ERF_DataStruct.H:239