diff --git a/moment_kinetics/src/nonlinear_solvers.jl b/moment_kinetics/src/nonlinear_solvers.jl index 7ba24ea37..3fc169069 100644 --- a/moment_kinetics/src/nonlinear_solvers.jl +++ b/moment_kinetics/src/nonlinear_solvers.jl @@ -71,6 +71,7 @@ struct nl_solver_info{TH,TV,Tcsg,Tlig,Tprecon,Tpretype} serial_solve::Bool max_nonlinear_iterations_this_step::Base.RefValue{mk_int} max_linear_iterations_this_step::Base.RefValue{mk_int} + total_its_soft_limit::mk_int preconditioner_type::Tpretype preconditioner_update_interval::mk_int preconditioners::Tprecon @@ -98,6 +99,7 @@ function setup_nonlinear_solve(active, input_dict, coords, outer_coords=(); defa linear_restart=10, linear_max_restarts=0, preconditioner_update_interval=300, + total_its_soft_limit=50, adi_precon_iterations=1, ) @@ -278,7 +280,7 @@ function setup_nonlinear_solve(active, input_dict, coords, outer_coords=(); defa Ref(nl_solver_input.preconditioner_update_interval), Ref(mk_float(0.0)), zeros(mk_int, n_vcut_inds), zeros(mk_int, n_vcut_inds), serial_solve, Ref(0), Ref(0), - preconditioner_type, + nl_solver_input.total_its_soft_limit, preconditioner_type, nl_solver_input.preconditioner_update_interval, preconditioners) end diff --git a/moment_kinetics/src/runge_kutta.jl b/moment_kinetics/src/runge_kutta.jl index 772cda8ba..6ea53ba10 100644 --- a/moment_kinetics/src/runge_kutta.jl +++ b/moment_kinetics/src/runge_kutta.jl @@ -1058,15 +1058,17 @@ end """ adaptive_timestep_update_t_params!(t_params, CFL_limits, error_norms, total_points, error_norm_method, success, - nl_max_its_fraction, composition; - electron=false, local_max_dt::mk_float=Inf) + nl_max_its_fraction, nl_total_its_soft_limit, + composition; electron=false, + local_max_dt::mk_float=Inf) Use the calculated `CFL_limits` and `error_norms` to update the timestep in `t_params`. """ function adaptive_timestep_update_t_params!(t_params, CFL_limits, error_norms, total_points, error_norm_method, success, - nl_max_its_fraction, composition; - electron=false, local_max_dt::mk_float=Inf) + nl_max_its_fraction, nl_total_its_soft_limit, + composition; electron=false, + local_max_dt::mk_float=Inf) # Get global minimum of CFL limits CFL_limit = Ref(0.0) this_limit_caused_by = nothing @@ -1325,7 +1327,7 @@ function adaptive_timestep_update_t_params!(t_params, CFL_limits, error_norms, end end - if nl_max_its_fraction > 0.5 && t_params.previous_dt[] > 0.0 + if (nl_max_its_fraction > 0.5 || nl_total_its_soft_limit) && t_params.previous_dt[] > 0.0 # The last step took many nonlinear iterations, so do not allow the # timestep to increase. # If t_params.previous_dt[]==0.0, then the previous step failed so diff --git a/moment_kinetics/src/time_advance.jl b/moment_kinetics/src/time_advance.jl index 8f0bd9272..881a8eea3 100644 --- a/moment_kinetics/src/time_advance.jl +++ b/moment_kinetics/src/time_advance.jl @@ -2604,7 +2604,8 @@ end external_source_settings, spectral_objects, advect_objects, gyroavs, num_diss_params, nl_solver_params, advance, scratch_dummy, r, z, vperp, - vpa, vzeta, vr, vz, success, nl_max_its_fraction) + vpa, vzeta, vr, vz, success, nl_max_its_fraction, + nl_total_its_soft_limit) Check the error estimate for the embedded RK method and adjust the timestep if appropriate. @@ -2615,7 +2616,7 @@ appropriate. geometry, external_source_settings, spectral_objects, advect_objects, gyroavs, num_diss_params, nl_solver_params, advance, scratch_dummy, r, z, vperp, vpa, vzeta, vr, vz, success, - nl_max_its_fraction) = begin + nl_max_its_fraction, nl_total_its_soft_limit) = begin #error_norm_method = "Linf" error_norm_method = "L2" @@ -2925,7 +2926,7 @@ appropriate. adaptive_timestep_update_t_params!(t_params, CFL_limits, error_norms, total_points, error_norm_method, success, nl_max_its_fraction, - composition) + nl_total_its_soft_limit, composition) if composition.electron_physics ∈ (kinetic_electrons, kinetic_electrons_with_temperature_equation) @@ -3226,6 +3227,7 @@ end if t_params.adaptive nl_max_its_fraction = 0.0 + nl_total_its_soft_limit = false if t_params.implicit_electron_advance || t_params.implicit_electron_time_evolving params_to_check = (nl_solver_params.ion_advance, nl_solver_params.vpa_advection, @@ -3251,6 +3253,7 @@ end nl_max_its_fraction = max(p.max_nonlinear_iterations_this_step[] / p.nonlinear_max_iterations, nl_max_its_fraction) + nl_total_its_soft_limit = p.max_linear_iterations_this_step[] > p.total_its_soft_limit || nl_total_its_soft_limit end end adaptive_timestep_update!(scratch, scratch_implicit, scratch_electron, @@ -3259,7 +3262,8 @@ end geometry, external_source_settings, spectral_objects, advect_objects, gyroavs, num_diss_params, nl_solver_params, advance, scratch_dummy, r, z, vperp, - vpa, vzeta, vr, vz, success, nl_max_its_fraction) + vpa, vzeta, vr, vz, success, nl_max_its_fraction, + nl_total_its_soft_limit) elseif success != "" error("Implicit part of timestep failed") end