1 #ifndef SUPERDROPLET_PC_MASSCHANGE_H_
2 #define SUPERDROPLET_PC_MASSCHANGE_H_
7 #ifdef ERF_USE_PARTICLES
11 namespace SDMassChangeUtils_LV
13 #ifdef ERF_USE_ML_UPHYS_DIAGNOSTICS
15 template <
typename RT >
24 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
25 RT operator () (
const RT a_R,
32 const RT a_N_s )
const noexcept
34 RT lambda_v = 2*a_D/std::sqrt(8*a_T*Rv/
PI);
36 RT dcf = (1+Kn) / (1+2*Kn*(1+Kn));
38 RT F_k = ( L/(Rv*a_T) - RT(1.0)) * ((L*rho_l) / (K*a_T));
39 RT F_d = (rho_l*Rv*a_T) / (dcf*a_D*a_e_s);
41 RT R_inv = RT(1.0)/a_R;
42 RT R_inv_cubed = R_inv*R_inv*R_inv;
44 RT
alpha = (a_S-RT(1.0)) / (F_k + F_d);
45 RT retval =
alpha*R_inv;
47 RT
beta = -(a_a/a_T) / (F_k + F_d);
48 retval +=
beta*R_inv*R_inv;
50 RT
gamma = a_b * a_N_s / (F_k + F_d);
51 retval +=
gamma*R_inv_cubed*R_inv;
60 template <
typename RT >
69 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
70 RT rhs_func (
const RT a_R_sq,
77 const RT a_N_s )
const noexcept
79 RT lambda_v = 2*a_D/std::sqrt(8*a_T*Rv/
PI);
80 RT Kn = lambda_v/std::sqrt(a_R_sq);
81 RT dcf = (1+Kn) / (1+2*Kn*(1+Kn));
83 RT F_k = ( L/(Rv*a_T) - RT(1.0)) * ((L*rho_l) / (K*a_T));
84 RT F_d = (rho_l*Rv*a_T) / (dcf*a_D*a_e_s);
86 RT R_inv = RT(1.0)/std::sqrt(a_R_sq);
87 RT R_inv_cubed = R_inv*R_inv*R_inv;
89 RT
alpha = RT(2.0) * (a_S-RT(1.0)) / (F_k + F_d);
92 RT
beta = -RT(2.0) * (a_a/a_T) / (F_k + F_d);
95 RT
gamma = RT(2.0) * a_b * a_N_s / (F_k + F_d);
96 retval +=
gamma*R_inv_cubed;
102 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
103 RT rhs_jac (
const RT a_R_sq,
109 const RT a_N_s )
const noexcept
111 RT lambda_v = 2*a_D/std::sqrt(8*a_T*Rv/
PI);
112 RT Kn = lambda_v/std::sqrt(a_R_sq);
113 RT dcf = (1+Kn) / (1+2*Kn*(1+Kn));
115 RT F_k = ( L/(Rv*a_T) - RT(1.0)) * ((L*rho_l) / (K*a_T));
116 RT F_d = (rho_l*Rv*a_T) / (dcf*a_D*a_e_s);
118 RT R_inv = RT(1.0)/std::sqrt(a_R_sq);
119 RT R_inv_3 = R_inv*R_inv*R_inv;
120 RT R_inv_5 = R_inv_3*R_inv*R_inv;
124 RT
beta = -RT(2.0) * (a_a/a_T) / (F_k + F_d);
127 RT
gamma = RT(2.0) * a_b * a_N_s / (F_k + F_d);
145 template<
typename NE ,
typename RT >
156 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
157 void operator() ( RT& a_u,
173 RT res_norm0 = RT(0.0);
175 for (
int k = 0; k < m_maxits; k++) {
176 RT residual = a_mu * a_u
178 + m_ne.rhs_func( a_u, a_S, a_T, a_e_s, a_D, a_a, a_b, a_N_s ) );
179 a_res_norm_a = std::sqrt(residual*residual);
182 if (a_res_norm_a > 0) {
183 res_norm0 = a_res_norm_a;
188 a_res_norm_r = a_res_norm_a / res_norm0;
190 if (a_res_norm_a <= m_atol) {
194 if (a_res_norm_r <= m_rtol) {
198 if (!std::isfinite(a_res_norm_a)) {
203 RT slope = a_mu - m_ne.rhs_jac( a_u, a_T, a_e_s, a_D, a_a, a_b, a_N_s );
205 du = - residual / slope;
207 RT du_norm = std::sqrt(du*du);
208 RT u_norm = std::sqrt(a_u*a_u);
209 if (du_norm/u_norm <= m_stol) {
215 if (a_u <= RT(0.0)) {
224 template<
typename ODE ,
225 typename NewtonSolver ,
230 const NewtonSolver m_newton;
251 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
252 RT computeTimestep (
const RT& a_u)
const
254 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
255 return m_cfl / std::sqrt(tau*tau);
259 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
260 RT computeTau (
const RT& a_u)
const
262 return m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
266 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
267 RT limitTimestep (RT dt, RT cur_time)
const
269 if ((cur_time + dt) > m_t_final) {
270 dt = m_t_final - cur_time;
276 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
277 bool isTimestepTooSmall (RT dt, RT tau)
const
279 return (dt < (RT(1.0e-12) * m_cfl / std::sqrt(tau*tau)))
280 && (dt < (RT(1.0e-12) * m_t_final));
284 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
285 RT evalRHS (
const RT& a_u)
const
287 return m_ode.rhs_func(a_u, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
291 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
292 void printStepInfo (RT cur_time, RT dt, RT tau, RT radius, RT snorm)
const
295 AMREX_DEVICE_PRINTF(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
296 cur_time, dt, dt * std::sqrt(tau*tau), radius, snorm);
301 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
302 void printStepInfoNewton (RT cur_time, RT dt, RT tau, RT radius, RT snorm,
303 RT res_norm_a, RT res_norm_r,
bool converged)
const
306 AMREX_DEVICE_PRINTF(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
307 cur_time, dt, dt * std::sqrt(tau*tau), radius, snorm);
308 AMREX_DEVICE_PRINTF(
" norms = %1.3e (abs), %1.3e (rel), converged = %s\n",
309 res_norm_a, res_norm_r, (converged ?
"yes" :
"no"));
315 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
316 void rk3bs ( RT& a_u,
317 bool& a_success )
const
319 RT cur_time = RT(0.0);
322 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
323 RT dt = m_cfl / std::sqrt(tau*tau);
329 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
332 tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
333 dt = m_cfl / std::sqrt(tau*tau);
338 if ((cur_time + dt) > m_t_final) {
339 dt = m_t_final - cur_time;
341 if (!std::isfinite(dt)) {
347 bool step_success =
false;
348 while (!step_success) {
350 if ( (dt < (
amrex::Real(1.0e-12)*m_cfl/std::sqrt(tau*tau)))
360 RT f1 = m_ode.rhs_func(u1, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
362 RT u2 = a_u +
myhalf*dt*f1;
367 RT f2 = m_ode.rhs_func(u2, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
374 RT f3 = m_ode.rhs_func(u3, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
381 RT f4 = m_ode.rhs_func(u4, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
387 RT err = std::sqrt((u_new-u_embed)*(u_new-u_embed));
388 RT tol = m_atol + m_rtol * std::max(a_u, a_u_old);
390 dt_new = dt * std::exp((
one/3)*std::log(
one/E));
393 if (std::isfinite(u_new)) {
404 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
410 AMREX_DEVICE_PRINTF(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
411 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
413 if (snorm < m_stol) {
431 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
433 bool& a_success )
const
439 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
441 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
442 RT dt = m_cfl / std::sqrt(tau*tau);
443 if ((cur_time + dt) > m_t_final) {
444 dt = m_t_final - cur_time;
446 if (!std::isfinite(dt)) {
452 bool step_success =
false;
453 while (!step_success) {
455 if ( (dt < (
amrex::Real(1.0e-12)*m_cfl/std::sqrt(tau*tau)))
465 RT f1 = m_ode.rhs_func(u1, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
467 RT u2 = a_u +
myhalf*dt*f1;
472 RT f2 = m_ode.rhs_func(u2, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
474 RT u3 = a_u +
myhalf*dt*f2;
479 RT f3 = m_ode.rhs_func(u3, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
481 RT u4 = a_u +
one*dt*f3;
486 RT f4 = m_ode.rhs_func(u4, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
490 if (std::isfinite(u_new)) {
501 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
506 AMREX_DEVICE_PRINTF(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
507 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
509 if (snorm < m_stol) {
527 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
529 bool& a_success )
const
535 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
537 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
538 RT dt = m_cfl / std::sqrt(tau*tau);
539 if ((cur_time + dt) > m_t_final) {
540 dt = m_t_final - cur_time;
542 if (!std::isfinite(dt)) {
547 RT res_norm_a = DBL_MAX;
548 RT res_norm_r = DBL_MAX;
549 bool converged =
false;
552 bool step_success =
false;
553 while (!step_success) {
555 if ( (dt < (
amrex::Real(1.0e-12)*m_cfl/std::sqrt(tau*tau)))
563 m_newton( u_new, rhs,
mu,
564 m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s,
565 res_norm_a, res_norm_r, converged );
568 if (std::isfinite(u_new)) {
580 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
585 AMREX_DEVICE_PRINTF(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
586 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
587 AMREX_DEVICE_PRINTF(
" norms = %1.3e (abs), %1.3e (rel), converged = %s\n",
588 res_norm_a, res_norm_r,
589 (converged ?
"yes" :
"no") );
591 if (snorm < m_stol) {
609 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
611 bool& a_success )
const
617 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
619 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
620 RT dt = m_cfl / std::sqrt(tau*tau);
621 if ((cur_time + dt) > m_t_final) {
622 dt = m_t_final - cur_time;
624 if (!std::isfinite(dt)) {
629 RT res_norm_a = DBL_MAX;
630 RT res_norm_r = DBL_MAX;
631 bool converged =
false;
634 bool step_success =
false;
635 while (!step_success) {
637 if ( (dt < (
amrex::Real(1.0e-12)*m_cfl/std::sqrt(tau*tau)))
644 RT f1 = m_ode.rhs_func(u1, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
648 m_newton( u2, rhs,
mu,
649 m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s,
650 res_norm_a, res_norm_r, converged );
655 RT f2 = m_ode.rhs_func(u2, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
657 u_new = a_u +
myhalf * dt * (f1 + f2);
660 if (std::isfinite(u_new)) {
672 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
677 AMREX_DEVICE_PRINTF(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
678 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
679 AMREX_DEVICE_PRINTF(
" norms = %1.3e (abs), %1.3e (rel), converged = %s\n",
680 res_norm_a, res_norm_r,
681 (converged ?
"yes" :
"no") );
683 if (snorm < m_stol) {
701 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
702 void dirk212 ( RT& a_u,
703 bool& a_success )
const
709 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
711 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
712 RT dt = m_cfl / std::sqrt(tau*tau);
713 if ((cur_time + dt) > m_t_final) {
714 dt = m_t_final - cur_time;
716 if (!std::isfinite(dt)) {
721 bool converged =
false;
722 RT res_norm_a = DBL_MAX;
723 RT res_norm_r = DBL_MAX;
726 bool step_success =
false;
727 while (!step_success) {
729 if ( (dt < (
amrex::Real(1.0e-12)*m_cfl/std::sqrt(tau*tau)))
742 RT res_norm_a_i = DBL_MAX;
743 RT res_norm_r_i = DBL_MAX;
744 bool converged_i =
false;
745 m_newton( u1, rhs,
mu,
746 m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s,
747 res_norm_a_i, res_norm_r_i, converged_i );
748 converged = converged && converged_i;
749 res_norm_a = std::max(res_norm_a, res_norm_a_i);
750 res_norm_r = std::max(res_norm_r, res_norm_r_i);
756 RT f1 = m_ode.rhs_func(u1, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
760 RT rhs =
mu * (a_u - dt*f1);
761 RT res_norm_a_i = DBL_MAX;
762 RT res_norm_r_i = DBL_MAX;
763 bool converged_i =
false;
764 m_newton( u2, rhs,
mu,
765 m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s,
766 res_norm_a_i, res_norm_r_i, converged_i );
767 converged = converged && converged_i;
768 res_norm_a = std::max(res_norm_a, res_norm_a_i);
769 res_norm_r = std::max(res_norm_r, res_norm_r_i);
775 RT f2 = m_ode.rhs_func(u2, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
777 u_new = a_u +
myhalf * dt * (f1 + f2);
780 if (std::isfinite(u_new)) {
792 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
797 AMREX_DEVICE_PRINTF(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
798 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
799 AMREX_DEVICE_PRINTF(
" norms = %1.3e (abs), %1.3e (rel), converged = %s\n",
800 res_norm_a, res_norm_r,
801 (converged ?
"yes" :
"no") );
803 if (snorm < m_stol) {
constexpr amrex::Real three
Definition: ERF_Constants.H:9
constexpr amrex::Real two
Definition: ERF_Constants.H:8
constexpr amrex::Real one
Definition: ERF_Constants.H:7
constexpr amrex::Real zero
Definition: ERF_Constants.H:6
constexpr amrex::Real myhalf
Definition: ERF_Constants.H:11
constexpr amrex::Real PI
Definition: ERF_Constants.H:16
amrex::Real gamma
Definition: ERF_InitCustomPert_DataAssimilation_ISV.H:9
amrex::Real beta
Definition: ERF_InitCustomPert_DataAssimilation_ISV.H:10
amrex::Real Real
Definition: ERF_ShocInterface.H:19
@ mu
Definition: ERF_AdvanceMorrison.cpp:89
real(kind=kind_phys), parameter, public alpha
Definition: ERF_module_mp_wsm6.F90:44