1 #ifndef SUPERDROPLET_PC_COALESCENCE_H_
2 #define SUPERDROPLET_PC_COALESCENCE_H_
6 #ifdef ERF_USE_PARTICLES
8 namespace SDMassChangeUtils
10 #ifdef ERF_USE_ML_UPHYS_DIAGNOSTICS
12 template <
typename RT >
21 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
22 RT operator () (
const RT a_R,
29 const RT a_N_s )
const noexcept
31 RT lambda_v = 2*a_D/std::sqrt(8*a_T*Rv/
PI);
33 RT dcf = (1+Kn) / (1+2*Kn*(1+Kn));
35 RT F_k = ( L/(Rv*a_T) - 1.0) * ((L*rho_l) / (K*a_T));
36 RT F_d = (rho_l*Rv*a_T) / (dcf*a_D*a_e_s);
39 RT R_inv_cubed = R_inv*R_inv*R_inv;
41 RT alpha = (a_S-1.0) / (F_k + F_d);
42 RT retval = alpha*R_inv;
44 RT beta = -(a_a/a_T) / (F_k + F_d);
45 retval += beta*R_inv*R_inv;
47 RT
gamma = a_b * a_N_s / (F_k + F_d);
48 retval +=
gamma*R_inv_cubed*R_inv;
57 template <
typename RT >
66 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
67 RT rhs_func (
const RT a_R_sq,
74 const RT a_N_s )
const noexcept
76 RT lambda_v = 2*a_D/std::sqrt(8*a_T*Rv/
PI);
77 RT Kn = lambda_v/std::sqrt(a_R_sq);
78 RT dcf = (1+Kn) / (1+2*Kn*(1+Kn));
80 RT F_k = ( L/(Rv*a_T) - 1.0) * ((L*rho_l) / (K*a_T));
81 RT F_d = (rho_l*Rv*a_T) / (dcf*a_D*a_e_s);
83 RT R_inv = std::exp(-0.5*std::log(a_R_sq));
84 RT R_inv_cubed = R_inv*R_inv*R_inv;
86 RT alpha = 2.0 * (a_S-1.0) / (F_k + F_d);
89 RT beta = -2.0 * (a_a/a_T) / (F_k + F_d);
92 RT
gamma = 2.0 * a_b * a_N_s / (F_k + F_d);
93 retval +=
gamma*R_inv_cubed;
99 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
100 RT rhs_jac (
const RT a_R_sq,
106 const RT a_N_s )
const noexcept
108 RT lambda_v = 2*a_D/std::sqrt(8*a_T*Rv/
PI);
109 RT Kn = lambda_v/std::sqrt(a_R_sq);
110 RT dcf = (1+Kn) / (1+2*Kn*(1+Kn));
112 RT F_k = ( L/(Rv*a_T) - 1.0) * ((L*rho_l) / (K*a_T));
113 RT F_d = (rho_l*Rv*a_T) / (dcf*a_D*a_e_s);
115 RT R_inv = 1.0/std::sqrt(a_R_sq);
116 RT R_inv_3 = R_inv*R_inv*R_inv;
117 RT R_inv_5 = R_inv_3*R_inv*R_inv;
121 RT beta = -2.0 * (a_a/a_T) / (F_k + F_d);
122 retval -= 0.5 * beta*R_inv_3;
124 RT
gamma = 2.0 * a_b * a_N_s / (F_k + F_d);
125 retval -= 0.5 * 3.0*
gamma*R_inv_5;
142 template<
typename NE ,
typename RT >
153 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
154 void operator() ( RT& a_u,
172 for (
int k = 0; k < m_maxits; k++) {
173 RT residual = a_mu * a_u
175 + m_ne.rhs_func( a_u, a_S, a_T, a_e_s, a_D, a_a, a_b, a_N_s ) );
176 a_res_norm_a = std::sqrt(residual*residual);
179 if (a_res_norm_a > 0) {
180 res_norm0 = a_res_norm_a;
185 a_res_norm_r = a_res_norm_a / res_norm0;
187 if (a_res_norm_a <= m_atol) {
191 if (a_res_norm_r <= m_rtol) {
195 if (!std::isfinite(a_res_norm_a)) {
200 RT slope = a_mu - m_ne.rhs_jac( a_u, a_T, a_e_s, a_D, a_a, a_b, a_N_s );
202 du = - residual / slope;
204 RT du_norm = std::sqrt(du*du);
205 RT u_norm = std::sqrt(a_u*a_u);
206 if (du_norm/u_norm <= m_stol) {
221 template<
typename ODE ,
222 typename NewtonSolver ,
227 const NewtonSolver m_newton;
249 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
250 void rk3bs ( RT& a_u,
251 bool& a_success )
const
256 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
257 RT dt = m_cfl / std::sqrt(tau*tau);
263 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
266 tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
267 dt = m_cfl / std::sqrt(tau*tau);
272 if ((cur_time + dt) > m_t_final) {
273 dt = m_t_final - cur_time;
275 if (!std::isfinite(dt)) {
281 bool step_success =
false;
282 while (!step_success) {
284 if ( (dt < (1.0e-12*m_cfl/std::sqrt(tau*tau)))
285 && (dt < (1.0e-12*m_t_final)) ) {
294 RT f1 = m_ode.rhs_func(u1, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
296 RT u2 = a_u + 0.5*dt*f1;
301 RT f2 = m_ode.rhs_func(u2, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
303 RT u3 = a_u + 0.75*dt*f2;
308 RT f3 = m_ode.rhs_func(u3, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
310 RT u4 = a_u + (1.0/9.0)*dt * (2.0*f1 + 3.0*f2 + 4.0*f3);
315 RT f4 = m_ode.rhs_func(u4, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
320 RT u_embed = a_u + (1.0/24.0)*dt * (7.0*f1 + 6.0*f2 + 8.0*f3 + 3.0*f4);
321 RT err = std::sqrt((u_new-u_embed)*(u_new-u_embed));
322 RT tol = m_atol + m_rtol * std::max(a_u, a_u_old);
324 dt_new = dt * std::exp((1.0/3)*std::log(1.0/E));
327 if (std::isfinite(u_new)) {
338 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
344 printf(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
345 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
347 if (snorm < m_stol) {
365 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
367 bool& a_success )
const
373 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
375 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
376 RT dt = m_cfl / std::sqrt(tau*tau);
377 if ((cur_time + dt) > m_t_final) {
378 dt = m_t_final - cur_time;
380 if (!std::isfinite(dt)) {
386 bool step_success =
false;
387 while (!step_success) {
389 if ( (dt < (1.0e-12*m_cfl/std::sqrt(tau*tau)))
390 && (dt < (1.0e-12*m_t_final)) ) {
399 RT f1 = m_ode.rhs_func(u1, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
401 RT u2 = a_u + 0.5*dt*f1;
406 RT f2 = m_ode.rhs_func(u2, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
408 RT u3 = a_u + 0.5*dt*f2;
413 RT f3 = m_ode.rhs_func(u3, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
415 RT u4 = a_u + 1.0*dt*f3;
420 RT f4 = m_ode.rhs_func(u4, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
422 u_new = a_u + dt*(f1+2.0*f2+2.0*f3+f4)/6.0;
424 if (std::isfinite(u_new)) {
435 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
440 printf(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
441 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
443 if (snorm < m_stol) {
461 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
463 bool& a_success )
const
469 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
471 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
472 RT dt = m_cfl / std::sqrt(tau*tau);
473 if ((cur_time + dt) > m_t_final) {
474 dt = m_t_final - cur_time;
476 if (!std::isfinite(dt)) {
481 RT res_norm_a = DBL_MAX;
482 RT res_norm_r = DBL_MAX;
483 bool converged =
false;
486 bool step_success =
false;
487 while (!step_success) {
489 if ( (dt < (1.0e-12*m_cfl/std::sqrt(tau*tau)))
490 && (dt < (1.0e-12*m_t_final)) ) {
497 m_newton( u_new, rhs,
mu,
498 m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s,
499 res_norm_a, res_norm_r, converged );
502 if (std::isfinite(u_new)) {
514 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
519 printf(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
520 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
521 printf(
" norms = %1.3e (abs), %1.3e (rel), converged = %s\n",
522 res_norm_a, res_norm_r,
523 (converged ?
"yes" :
"no") );
525 if (snorm < m_stol) {
543 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
545 bool& a_success )
const
551 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
553 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
554 RT dt = m_cfl / std::sqrt(tau*tau);
555 if ((cur_time + dt) > m_t_final) {
556 dt = m_t_final - cur_time;
558 if (!std::isfinite(dt)) {
563 RT res_norm_a = DBL_MAX;
564 RT res_norm_r = DBL_MAX;
565 bool converged =
false;
568 bool step_success =
false;
569 while (!step_success) {
571 if ( (dt < (1.0e-12*m_cfl/std::sqrt(tau*tau)))
572 && (dt < (1.0e-12*m_t_final)) ) {
575 RT
mu = 1.0 / (0.5*dt);
578 RT f1 = m_ode.rhs_func(u1, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
581 RT rhs =
mu * (a_u + 0.5*dt*f1);
582 m_newton( u2, rhs,
mu,
583 m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s,
584 res_norm_a, res_norm_r, converged );
589 RT f2 = m_ode.rhs_func(u2, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
591 u_new = a_u + 0.5 * dt * (f1 + f2);
594 if (std::isfinite(u_new)) {
606 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
611 printf(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
612 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
613 printf(
" norms = %1.3e (abs), %1.3e (rel), converged = %s\n",
614 res_norm_a, res_norm_r,
615 (converged ?
"yes" :
"no") );
617 if (snorm < m_stol) {
635 AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
636 void dirk212 ( RT& a_u,
637 bool& a_success )
const
643 while ((cur_time < m_t_final) && (n_step < m_max_steps)) {
645 RT tau = m_ode.rhs_jac(a_u, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
646 RT dt = m_cfl / std::sqrt(tau*tau);
647 if ((cur_time + dt) > m_t_final) {
648 dt = m_t_final - cur_time;
650 if (!std::isfinite(dt)) {
655 bool converged =
false;
656 RT res_norm_a = DBL_MAX;
657 RT res_norm_r = DBL_MAX;
660 bool step_success =
false;
661 while (!step_success) {
663 if ( (dt < (1.0e-12*m_cfl/std::sqrt(tau*tau)))
664 && (dt < (1.0e-12*m_t_final)) ) {
676 RT res_norm_a_i = DBL_MAX;
677 RT res_norm_r_i = DBL_MAX;
678 bool converged_i =
false;
679 m_newton( u1, rhs,
mu,
680 m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s,
681 res_norm_a_i, res_norm_r_i, converged_i );
682 converged = converged && converged_i;
683 res_norm_a = std::max(res_norm_a, res_norm_a_i);
684 res_norm_r = std::max(res_norm_r, res_norm_r_i);
690 RT f1 = m_ode.rhs_func(u1, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
694 RT rhs =
mu * (a_u - dt*f1);
695 RT res_norm_a_i = DBL_MAX;
696 RT res_norm_r_i = DBL_MAX;
697 bool converged_i =
false;
698 m_newton( u2, rhs,
mu,
699 m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s,
700 res_norm_a_i, res_norm_r_i, converged_i );
701 converged = converged && converged_i;
702 res_norm_a = std::max(res_norm_a, res_norm_a_i);
703 res_norm_r = std::max(res_norm_r, res_norm_r_i);
709 RT f2 = m_ode.rhs_func(u2, m_S, m_T, m_e_s, m_D, m_a, m_b, m_N_s);
711 u_new = a_u + 0.5 * dt * (f1 + f2);
714 if (std::isfinite(u_new)) {
726 RT snorm = std::sqrt((a_u-u_new)*(a_u-u_new)/(a_u*a_u));
731 printf(
"Time %1.2e, dt = %1.2e, cfl = %1.1e, radius = %1.4e, snorm = %1.1e\n",
732 cur_time, dt, dt * std::sqrt(tau*tau), std::sqrt(a_u), snorm);
733 printf(
" norms = %1.3e (abs), %1.3e (rel), converged = %s\n",
734 res_norm_a, res_norm_r,
735 (converged ?
"yes" :
"no") );
737 if (snorm < m_stol) {
constexpr amrex::Real PI
Definition: ERF_Constants.H:6
@ mu
Definition: ERF_AdvanceMorrison.cpp:87
real(c_double) function, private gamma(X)
Definition: ERF_module_mp_morr_two_moment.F90:4107