16 auto dz =
m_geom.CellSize(2);
17 auto domain =
m_geom.Domain();
18 int k_lo = domain.smallEnd(2);
19 int k_hi = domain.bigEnd(2);
22 auto ba =
tabs->boxArray();
23 auto dm =
tabs->DistributionMap();
24 fz.define(convert(ba, IntVect(0,0,1)), dm, 1, 0);
30 for ( MFIter mfi(*
tabs,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
40 const auto& tbx = mfi.tilebox();
45 ParallelFor(tbx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
47 qv_array(i,j,k) = std::max(0.0, qv_array(i,j,k));
48 qc_array(i,j,k) = std::max(0.0, qc_array(i,j,k));
49 qp_array(i,j,k) = std::max(0.0, qp_array(i,j,k));
52 Real qcc, auto_r, accrr;
54 Real dq_clwater_to_rain, dq_rain_to_vapor, dq_clwater_to_vapor, dq_vapor_to_clwater;
56 Real pressure = pres_array(i,j,k);
57 erf_qsatw(tabs_array(i,j,k), pressure, qsat);
61 amrex::Warning(
"qsat computed as non-positive; setting to 0.!");
69 dq_clwater_to_rain = 0.0;
70 dq_rain_to_vapor = 0.0;
71 dq_vapor_to_clwater = 0.0;
72 dq_clwater_to_vapor = 0.0;
79 if ( (qv_array(i,j,k) > qsat) && do_cond ) {
80 dq_vapor_to_clwater = std::min(qv_array(i,j,k), (qv_array(i,j,k)-qsat)/(1.0 + fac));
85 if ( (qv_array(i,j,k) < qsat) && (qc_array(i,j,k) > 0.0) && do_cond ) {
86 dq_clwater_to_vapor = std::min(qc_array(i,j,k), (qsat - qv_array(i,j,k))/(1.0 + fac));
89 if (( qp_array(i,j,k) > 0.0) && (qv_array(i,j,k) < qsat) ) {
90 Real C = 1.6 + 124.9*std::pow(0.001*rho_array(i,j,k)*qp_array(i,j,k),0.2046);
91 dq_rain_to_vapor = 1.0/(0.001*rho_array(i,j,k))*(1.0 - qv_array(i,j,k)/qsat)*C*std::pow(0.001*rho_array(i,j,k)*qp_array(i,j,k),0.525)/
92 (5.4e5 + 2.55e6/(pressure*qsat))*dtn;
95 dq_rain_to_vapor = std::min({qp_array(i,j,k), dq_rain_to_vapor});
101 if (qc_array(i,j,k) > 0.0) {
102 qcc = qc_array(i,j,k);
110 accrr = 2.2 * std::pow(qp_array(i,j,k) , 0.875);
111 dq_clwater_to_rain = dtn *(accrr*qcc + auto_r*(qcc -
qcw0));
114 dq_clwater_to_rain = std::min(dq_clwater_to_rain, qc_array(i,j,k));
117 qv_array(i,j,k) += -dq_vapor_to_clwater + dq_clwater_to_vapor + dq_rain_to_vapor;
118 qc_array(i,j,k) += dq_vapor_to_clwater - dq_clwater_to_vapor - dq_clwater_to_rain;
119 qp_array(i,j,k) += dq_clwater_to_rain - dq_rain_to_vapor;
121 Real theta_over_T = theta_array(i,j,k)/tabs_array(i,j,k);
122 theta_array(i,j,k) += theta_over_T * d_fac_cond * (dq_vapor_to_clwater - dq_clwater_to_vapor - dq_rain_to_vapor);
124 qv_array(i,j,k) = std::max(0.0, qv_array(i,j,k));
125 qc_array(i,j,k) = std::max(0.0, qc_array(i,j,k));
126 qp_array(i,j,k) = std::max(0.0, qp_array(i,j,k));
128 qt_array(i,j,k) = qv_array(i,j,k) + qc_array(i,j,k);
133 for ( MFIter mfi(fz, TilingIfNotGPU()); mfi.isValid(); ++mfi ){
137 auto fz_array = fz.array(mfi);
138 const Box& tbz = mfi.tilebox();
140 ParallelFor(tbz, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
142 Real rho_avg, qp_avg;
145 rho_avg = rho_array(i,j,k);
146 qp_avg = qp_array(i,j,k);
147 }
else if (k==k_hi+1) {
148 rho_avg = rho_array(i,j,k-1);
149 qp_avg = qp_array(i,j,k-1);
151 rho_avg = 0.5*(rho_array(i,j,k-1) + rho_array(i,j,k));
152 qp_avg = 0.5*(qp_array(i,j,k-1) + qp_array(i,j,k));
155 qp_avg = std::max(0.0, qp_avg);
157 Real V_terminal = 36.34*std::pow(rho_avg*0.001*qp_avg, 0.1346)*std::pow(rho_avg/1.16, -0.5);
165 fz_array(i,j,k) = rho_avg*V_terminal*qp_avg;
172 auto const& ma_fz_arr = fz.const_arrays();
173 GpuTuple<Real> max = ParReduce(TypeList<ReduceOpMax>{},
176 [=] AMREX_GPU_DEVICE (
int box_no,
int i,
int j,
int k) noexcept
179 return { ma_fz_arr[box_no](i,j,k) };
182 n_substep = int( std::ceil(wt_max * coef /
CFL_MAX) );
183 AMREX_ALWAYS_ASSERT(n_substep >= 1);
184 coef /=
Real(n_substep);
185 dtn /=
Real(n_substep);
188 for (
int nsub(0); nsub<n_substep; ++nsub) {
189 for ( MFIter mfi(*
tabs, TilingIfNotGPU()); mfi.isValid(); ++mfi ){
193 auto fz_array = fz.array(mfi);
195 const auto dJ_array = (
m_detJ_cc) ?
m_detJ_cc->const_array(mfi) : Array4<const Real>{};
197 const Box& tbx = mfi.tilebox();
198 const Box& tbz = mfi.tilebox(IntVect(0,0,1),IntVect(0));
201 ParallelFor(tbz, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
203 Real rho_avg, qp_avg;
205 rho_avg = rho_array(i,j,k);
206 qp_avg = qp_array(i,j,k);
207 }
else if (k==k_hi+1) {
208 rho_avg = rho_array(i,j,k-1);
209 qp_avg = qp_array(i,j,k-1);
211 rho_avg = 0.5*(rho_array(i,j,k-1) + rho_array(i,j,k));
212 qp_avg = 0.5*(qp_array(i,j,k-1) + qp_array(i,j,k));
215 qp_avg = std::max(0.0, qp_avg);
217 Real V_terminal = 36.34*std::pow(rho_avg*0.001*qp_avg, 0.1346)*std::pow(rho_avg/1.16, -0.5);
225 fz_array(i,j,k) = rho_avg*V_terminal*qp_avg;
228 rain_accum_array(i,j,k) = rain_accum_array(i,j,k) + rho_avg*qp_avg*V_terminal*dtn/1000.0*1000.0;
233 ParallelFor(tbx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
236 Real dJinv = (dJ_array) ? 1.0/dJ_array(i,j,k) : 1.0;
238 if(std::fabs(fz_array(i,j,k+1)) < 1e-14) fz_array(i,j,k+1) = 0.0;
239 if(std::fabs(fz_array(i,j,k )) < 1e-14) fz_array(i,j,k ) = 0.0;
240 Real dq_sed = dJinv * (1.0/rho_array(i,j,k)) * (fz_array(i,j,k+1) - fz_array(i,j,k)) * coef;
241 if(std::fabs(dq_sed) < 1e-14) dq_sed = 0.0;
243 qp_array(i,j,k) += dq_sed;
244 qp_array(i,j,k) = std::max(0.0, qp_array(i,j,k));
251 if (solverChoice.
moisture_type == MoistureType::Kessler_NoRain) {
252 if (!do_cond) {
return; }
254 for ( MFIter mfi(*
tabs,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
262 const auto& box3d = mfi.tilebox();
267 ParallelFor(box3d, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) noexcept
269 qc_array(i,j,k) = std::max(0.0, qc_array(i,j,k));
273 Real dq_clwater_to_vapor, dq_vapor_to_clwater;
275 Real pressure = pres_array(i,j,k);
276 erf_qsatw(tabs_array(i,j,k), pressure, qsat);
283 dq_vapor_to_clwater = 0.0;
284 dq_clwater_to_vapor = 0.0;
291 if (qv_array(i,j,k) > qsat){
292 dq_vapor_to_clwater = std::min(qv_array(i,j,k), (qv_array(i,j,k)-qsat)/(1.0 + fac));
296 if (qv_array(i,j,k) < qsat && qc_array(i,j,k) > 0.0){
297 dq_clwater_to_vapor = std::min(qc_array(i,j,k), (qsat - qv_array(i,j,k))/(1.0 + fac));
300 qv_array(i,j,k) += -dq_vapor_to_clwater + dq_clwater_to_vapor;
301 qc_array(i,j,k) += dq_vapor_to_clwater - dq_clwater_to_vapor;
303 Real theta_over_T = theta_array(i,j,k)/tabs_array(i,j,k);
305 theta_array(i,j,k) += theta_over_T * d_fac_cond * (dq_vapor_to_clwater - dq_clwater_to_vapor);
307 qv_array(i,j,k) = std::max(0.0, qv_array(i,j,k));
308 qc_array(i,j,k) = std::max(0.0, qc_array(i,j,k));
310 qt_array(i,j,k) = qv_array(i,j,k) + qc_array(i,j,k);
constexpr amrex::Real Cp_d
Definition: ERF_Constants.H:12
constexpr amrex::Real alphaelq
Definition: ERF_Constants.H:48
constexpr amrex::Real qcw0
Definition: ERF_Constants.H:46
constexpr amrex::Real L_v
Definition: ERF_Constants.H:16
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_dtqsatw(amrex::Real t, amrex::Real p, amrex::Real &dtqsatw)
Definition: ERF_MicrophysicsUtils.H:178
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void erf_qsatw(amrex::Real t, amrex::Real p, amrex::Real &qsatw)
Definition: ERF_MicrophysicsUtils.H:163
amrex::Real Real
Definition: ERF_ShocInterface.H:19
amrex::Geometry m_geom
Definition: ERF_Kessler.H:144
amrex::MultiFab * m_detJ_cc
Definition: ERF_Kessler.H:167
amrex::Real m_fac_cond
Definition: ERF_Kessler.H:159
bool m_do_cond
Definition: ERF_Kessler.H:163
amrex::Array< FabPtr, MicVar_Kess::NumVars > mic_fab_vars
Definition: ERF_Kessler.H:170
static constexpr amrex::Real CFL_MAX
Definition: ERF_Kessler.H:138
@ qp
Definition: ERF_Kessler.H:31
@ qcl
Definition: ERF_Kessler.H:29
@ tabs
Definition: ERF_Kessler.H:24
@ pres
Definition: ERF_Kessler.H:25
@ rho
Definition: ERF_Kessler.H:22
@ theta
Definition: ERF_Kessler.H:23
@ qt
Definition: ERF_Kessler.H:27
@ rain_accum
Definition: ERF_Kessler.H:33
@ qv
Definition: ERF_Kessler.H:28
real(c_double), parameter epsilon
Definition: ERF_module_model_constants.F90:12
MoistureType moisture_type
Definition: ERF_DataStruct.H:911