diff --git a/include/aspect/parameters.h b/include/aspect/parameters.h index 5154a8b7055..7f454039ee2 100644 --- a/include/aspect/parameters.h +++ b/include/aspect/parameters.h @@ -97,6 +97,38 @@ namespace aspect false; } + /** + * A struct that contains the enums to decide what to do when a nonlinear solver fails. + */ + struct NonlinearSolverFailureStrategy + { + enum Kind + { + continue_with_next_timestep, + cut_timestep_size, + abort_program + }; + + /** + * parse the enum value from a string + */ + static + Kind + parse(const std::string &input) + { + if (input == "continue with next timestep") + return continue_with_next_timestep; + else if (input == "cut timestep size") + return cut_timestep_size; + else if (input == "abort program") + return abort_program; + else + AssertThrow(false, ExcNotImplemented()); + + return Kind(); + } + }; + /** * @brief The NullspaceRemoval struct */ @@ -450,6 +482,7 @@ namespace aspect * @{ */ typename NonlinearSolver::Kind nonlinear_solver; + typename NonlinearSolverFailureStrategy::Kind nonlinear_solver_failure_strategy; typename AdvectionStabilizationMethod::Kind advection_stabilization_method; double nonlinear_tolerance; diff --git a/include/aspect/simulator.h b/include/aspect/simulator.h index 7496ef68690..e53438245f9 100644 --- a/include/aspect/simulator.h +++ b/include/aspect/simulator.h @@ -168,6 +168,14 @@ namespace aspect Tensor<1,dim> tensor_rotation; }; + /** + * Exception to be thrown when the nonlinear solver needs to many iterations to converge. + */ + DeclExceptionMsg(ExcNonlinearSolverNoConvergence, + "Nonlinear solver failed to converge in the prescribed number of steps. " + "Consider changing `Max nonlinear iterations` or `Nonlinear solver failure " + "strategy`."); + /** * This is the main class of ASPECT. It implements the overall simulation * algorithm using the numerical methods discussed in the papers and manuals diff --git a/source/simulator/core.cc b/source/simulator/core.cc index 916cd404d50..d6ea7284819 100644 --- a/source/simulator/core.cc +++ b/source/simulator/core.cc @@ -2018,15 +2018,53 @@ namespace aspect simulator_is_past_initialization = true; do { - // Only solve if we are not in pre-refinement, or we do not want to skip - // solving in pre-refinement. + // During pre-refinement, do not solve if we are asked to skip it: if (! (parameters.skip_solvers_on_initial_refinement && pre_refinement_step < parameters.initial_adaptive_refinement)) { start_timestep (); // then do the core work: assemble systems and solve - solve_timestep (); + try + { + solve_timestep (); + } + catch (...) + { + pcout << "ERROR: the solver in the current timestep failed to converge." << std::endl; + + if (parameters.nonlinear_solver_failure_strategy + == Parameters::NonlinearSolverFailureStrategy::continue_with_next_timestep) + { + // do nothing and continue + } + else if (parameters.nonlinear_solver_failure_strategy + == Parameters::NonlinearSolverFailureStrategy::cut_timestep_size) + { + if (timestep_number == 0) + { + pcout << "Note: we can not cut the timestep in step 0, so we are aborting." + << std::endl; + throw; + } + + // reduce timestep size and update time to "go back": + const double new_time_step = 0.5*time_step; + pcout << "\tReducing timestep to " << new_time_step << '\n' << std::endl; + + time -= time_step - new_time_step; + time_step = new_time_step; + continue; // skip the rest of the main loop that would advance in time + } + else if (parameters.nonlinear_solver_failure_strategy + == Parameters::NonlinearSolverFailureStrategy::abort_program) + { + // rethrow the current exception + throw; + } + else + AssertThrow(false, ExcNotImplemented()); + } } // See if we have to start over with a new adaptive refinement cycle diff --git a/source/simulator/parameters.cc b/source/simulator/parameters.cc index b8b01bb8d49..755d3375f7d 100644 --- a/source/simulator/parameters.cc +++ b/source/simulator/parameters.cc @@ -265,6 +265,14 @@ namespace aspect "The `Newton Stokes' scheme is deprecated and only allowed for reasons of " "backwards compatibility. It is the same as `iterated Advection and Newton Stokes'."); + prm.declare_entry ("Nonlinear solver failure strategy", "abort program", + Patterns::Selection("continue with next timestep|cut timestep size|abort program"), + "Select the strategy on what to do if the nonlinear solver scheme fails to " + "converge. The options are:\n" + "`continue with next timestep`: ignore error and continue to the next timestep\n" + "`cut timestep size`: reduce the current timestep size and redo the timestep\n" + "`abort program`: abort the program with an error message."); + prm.declare_entry ("Nonlinear solver tolerance", "1e-5", Patterns::Double(0., 1.), "A relative tolerance up to which the nonlinear solver will iterate. " @@ -1417,6 +1425,8 @@ namespace aspect else AssertThrow (false, ExcNotImplemented()); } + nonlinear_solver_failure_strategy = NonlinearSolverFailureStrategy::parse( + prm.get("Nonlinear solver failure strategy")); prm.enter_subsection ("Solver parameters"); { diff --git a/source/simulator/solver_schemes.cc b/source/simulator/solver_schemes.cc index 40a7aed84fd..7185dd40e12 100644 --- a/source/simulator/solver_schemes.cc +++ b/source/simulator/solver_schemes.cc @@ -814,6 +814,7 @@ namespace aspect } while (nonlinear_solver_control.check(nonlinear_iteration, relative_residual) == SolverControl::iterate); + AssertThrow(nonlinear_solver_control.last_check() != SolverControl::failure, ExcNonlinearSolverNoConvergence()); signals.post_nonlinear_solver(nonlinear_solver_control); } @@ -872,6 +873,8 @@ namespace aspect } while (nonlinear_solver_control.check(nonlinear_iteration, relative_residual) == SolverControl::iterate); + AssertThrow(nonlinear_solver_control.last_check() != SolverControl::failure, ExcNonlinearSolverNoConvergence()); + // Reset the linear tolerance to what it was at the beginning of the time step. parameters.linear_stokes_solver_tolerance = begin_linear_tolerance; @@ -942,6 +945,8 @@ namespace aspect } while (nonlinear_solver_control.check(nonlinear_iteration, relative_residual) == SolverControl::iterate); + AssertThrow(nonlinear_solver_control.last_check() != SolverControl::failure, ExcNonlinearSolverNoConvergence()); + // Reset the linear tolerance to what it was at the beginning of the time step. parameters.linear_stokes_solver_tolerance = begin_linear_tolerance; @@ -1049,6 +1054,8 @@ namespace aspect } while (nonlinear_solver_control.check(nonlinear_iteration, relative_residual) == SolverControl::iterate); + AssertThrow(nonlinear_solver_control.last_check() != SolverControl::failure, ExcNonlinearSolverNoConvergence()); + // Reset the linear tolerance to what it was at the beginning of the time step. parameters.linear_stokes_solver_tolerance = begin_linear_tolerance; @@ -1169,6 +1176,7 @@ namespace aspect } while (nonlinear_solver_control.check(nonlinear_iteration, relative_residual) == SolverControl::iterate); + AssertThrow(nonlinear_solver_control.last_check() != SolverControl::failure, ExcNonlinearSolverNoConvergence()); signals.post_nonlinear_solver(nonlinear_solver_control); } @@ -1216,6 +1224,7 @@ namespace aspect } while (nonlinear_solver_control.check(nonlinear_iteration, relative_residual) == SolverControl::iterate); + AssertThrow(nonlinear_solver_control.last_check() != SolverControl::failure, ExcNonlinearSolverNoConvergence()); signals.post_nonlinear_solver(nonlinear_solver_control); } @@ -1315,6 +1324,8 @@ namespace aspect } while (nonlinear_solver_control.check(nonlinear_iteration, relative_residual) == SolverControl::iterate); + AssertThrow(nonlinear_solver_control.last_check() != SolverControl::failure, ExcNonlinearSolverNoConvergence()); + // Reset the Newton stabilization at the end of the timestep. newton_handler->parameters.preconditioner_stabilization = starting_preconditioner_stabilization; newton_handler->parameters.velocity_block_stabilization = starting_velocity_block_stabilization; @@ -1419,6 +1430,8 @@ namespace aspect } while (nonlinear_solver_control.check(nonlinear_iteration, relative_residual) == SolverControl::iterate); + AssertThrow(nonlinear_solver_control.last_check() != SolverControl::failure, ExcNonlinearSolverNoConvergence()); + // Reset the Newton stabilization at the end of the timestep. newton_handler->parameters.preconditioner_stabilization = starting_preconditioner_stabilization; newton_handler->parameters.velocity_block_stabilization = starting_velocity_block_stabilization; diff --git a/tests/nonlinear_failure_strategy_cut.cc b/tests/nonlinear_failure_strategy_cut.cc new file mode 100644 index 00000000000..933e1b29788 --- /dev/null +++ b/tests/nonlinear_failure_strategy_cut.cc @@ -0,0 +1 @@ +#include "../benchmarks/nonlinear_channel_flow/simple_nonlinear.cc" diff --git a/tests/nonlinear_failure_strategy_cut.prm b/tests/nonlinear_failure_strategy_cut.prm new file mode 100644 index 00000000000..8aa4c485747 --- /dev/null +++ b/tests/nonlinear_failure_strategy_cut.prm @@ -0,0 +1,11 @@ +# Check that nonlinear solver strategy "cut timestep size" works +# +# Like iterated_advection_and_stokes_residual.prm + +include $ASPECT_SOURCE_DIR/tests/iterated_advection_and_stokes_residual.prm + +set Nonlinear solver failure strategy = cut timestep size +set Max nonlinear iterations = 7 + +set Dimension = 2 +set End time = 20000 diff --git a/tests/nonlinear_failure_strategy_cut/screen-output b/tests/nonlinear_failure_strategy_cut/screen-output new file mode 100644 index 00000000000..469edcba88a --- /dev/null +++ b/tests/nonlinear_failure_strategy_cut/screen-output @@ -0,0 +1,254 @@ +----------------------------------------------------------------------------- +----------------------------------------------------------------------------- + +Loading shared library <./libnonlinear_failure_strategy_cut.so> + +----------------------------------------------------------------------------- +----------------------------------------------------------------------------- +Number of active cells: 512 (on 5 levels) +Number of degrees of freedom: 9,141 (4,290+561+2,145+2,145) + +*** Timestep 0: t=0 years + Solving temperature system... 0 iterations. + Skipping porosity composition solve because RHS is zero. + Rebuilding Stokes preconditioner... + Solving Stokes system... 58+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 1.89643e-16, 0, 1 + Relative nonlinear residual (total system) after nonlinear iteration 1: 1 + + Solving temperature system... 0 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 1+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 1.89643e-16, 0, 5.20807e-13 + Relative nonlinear residual (total system) after nonlinear iteration 2: 5.20807e-13 + + + Postprocessing: + +*** Timestep 1: t=13251 years + Solving temperature system... 10 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 55+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.821377, 0, 0.75783 + Relative nonlinear residual (total system) after nonlinear iteration 1: 0.821377 + + Solving temperature system... 10 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 53+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.0977331, 0, 0.113623 + Relative nonlinear residual (total system) after nonlinear iteration 2: 0.113623 + + Solving temperature system... 9 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 49+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.0168861, 0, 0.0205037 + Relative nonlinear residual (total system) after nonlinear iteration 3: 0.0205037 + + Solving temperature system... 9 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 46+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.00320707, 0, 0.00392882 + Relative nonlinear residual (total system) after nonlinear iteration 4: 0.00392882 + + Solving temperature system... 8 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 43+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.000633249, 0, 0.000777886 + Relative nonlinear residual (total system) after nonlinear iteration 5: 0.000777886 + + Solving temperature system... 8 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 40+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.000127909, 0, 0.000157509 + Relative nonlinear residual (total system) after nonlinear iteration 6: 0.000157509 + + Solving temperature system... 7 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 37+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 2.62433e-05, 0, 3.24128e-05 + Relative nonlinear residual (total system) after nonlinear iteration 7: 3.24128e-05 + +ERROR: the solver in the current timestep failed to converge. + Reducing timestep to 2.0908e+11 + +*** Timestep 1: t=6625.49 years + Solving temperature system... 9 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 54+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.682328, 0, 0.623091 + Relative nonlinear residual (total system) after nonlinear iteration 1: 0.682328 + + Solving temperature system... 8 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 51+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.067174, 0, 0.0714663 + Relative nonlinear residual (total system) after nonlinear iteration 2: 0.0714663 + + Solving temperature system... 7 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 46+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.00881208, 0, 0.00950715 + Relative nonlinear residual (total system) after nonlinear iteration 3: 0.00950715 + + Solving temperature system... 6 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 43+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.0012324, 0, 0.00132848 + Relative nonlinear residual (total system) after nonlinear iteration 4: 0.00132848 + + Solving temperature system... 6 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 39+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.000176949, 0, 0.000190452 + Relative nonlinear residual (total system) after nonlinear iteration 5: 0.000190452 + + Solving temperature system... 5 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 35+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 2.5804e-05, 0, 2.77522e-05 + Relative nonlinear residual (total system) after nonlinear iteration 6: 2.77522e-05 + + Solving temperature system... 4 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 31+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 3.80311e-06, 0, 4.08965e-06 + Relative nonlinear residual (total system) after nonlinear iteration 7: 4.08965e-06 + + + Postprocessing: + +*** Timestep 2: t=19439.3 years + Solving temperature system... 11 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 54+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.349648, 0, 0.479292 + Relative nonlinear residual (total system) after nonlinear iteration 1: 0.479292 + + Solving temperature system... 10 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 52+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.0186076, 0, 0.0495985 + Relative nonlinear residual (total system) after nonlinear iteration 2: 0.0495985 + + Solving temperature system... 9 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 47+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.0022294, 0, 0.00863281 + Relative nonlinear residual (total system) after nonlinear iteration 3: 0.00863281 + + Solving temperature system... 8 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 44+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.000434729, 0, 0.0017423 + Relative nonlinear residual (total system) after nonlinear iteration 4: 0.0017423 + + Solving temperature system... 7 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 41+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 9.08033e-05, 0, 0.000363433 + Relative nonlinear residual (total system) after nonlinear iteration 5: 0.000363433 + + Solving temperature system... 6 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 38+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 1.92857e-05, 0, 7.7081e-05 + Relative nonlinear residual (total system) after nonlinear iteration 6: 7.7081e-05 + + Solving temperature system... 6 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 35+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 4.13709e-06, 0, 1.65133e-05 + Relative nonlinear residual (total system) after nonlinear iteration 7: 1.65133e-05 + +ERROR: the solver in the current timestep failed to converge. + Reducing timestep to 2.02182e+11 + +*** Timestep 2: t=13032.4 years + Solving temperature system... 10 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 53+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.140486, 0, 0.273969 + Relative nonlinear residual (total system) after nonlinear iteration 1: 0.273969 + + Solving temperature system... 9 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 49+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.00973167, 0, 0.0248216 + Relative nonlinear residual (total system) after nonlinear iteration 2: 0.0248216 + + Solving temperature system... 8 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 44+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.00110007, 0, 0.00289087 + Relative nonlinear residual (total system) after nonlinear iteration 3: 0.00289087 + + Solving temperature system... 7 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 40+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.000141653, 0, 0.000369765 + Relative nonlinear residual (total system) after nonlinear iteration 4: 0.000369765 + + Solving temperature system... 6 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 35+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 1.88893e-05, 0, 4.92024e-05 + Relative nonlinear residual (total system) after nonlinear iteration 5: 4.92024e-05 + + Solving temperature system... 5 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 32+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 2.56717e-06, 0, 6.69796e-06 + Relative nonlinear residual (total system) after nonlinear iteration 6: 6.69796e-06 + + + Postprocessing: + +*** Timestep 3: t=20000 years + Solving temperature system... 10 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 53+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.153077, 0, 0.374788 + Relative nonlinear residual (total system) after nonlinear iteration 1: 0.374788 + + Solving temperature system... 8 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 47+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.00697232, 0, 0.020623 + Relative nonlinear residual (total system) after nonlinear iteration 2: 0.020623 + + Solving temperature system... 7 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 43+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 0.000414911, 0, 0.00143987 + Relative nonlinear residual (total system) after nonlinear iteration 3: 0.00143987 + + Solving temperature system... 6 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 38+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 3.212e-05, 0, 0.000119257 + Relative nonlinear residual (total system) after nonlinear iteration 4: 0.000119257 + + Solving temperature system... 5 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 34+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 2.86401e-06, 0, 1.0762e-05 + Relative nonlinear residual (total system) after nonlinear iteration 5: 1.0762e-05 + + Solving temperature system... 4 iterations. + Skipping porosity composition solve because RHS is zero. + Solving Stokes system... 29+0 iterations. + Relative nonlinear residuals (temperature, compositional fields, Stokes system): 2.72973e-07, 0, 1.02263e-06 + Relative nonlinear residual (total system) after nonlinear iteration 6: 1.02263e-06 + + + Postprocessing: + +Termination requested by criterion: end time + + ++---------------------------------------------+------------+------------+ ++---------------------------------+-----------+------------+------------+ ++---------------------------------+-----------+------------+------------+ + +----------------------------------------------------------------------------- +----------------------------------------------------------------------------- diff --git a/tests/nonlinear_failure_strategy_cut/statistics b/tests/nonlinear_failure_strategy_cut/statistics new file mode 100644 index 00000000000..40d8be8b1af --- /dev/null +++ b/tests/nonlinear_failure_strategy_cut/statistics @@ -0,0 +1,17 @@ +# 1: Time step number +# 2: Time (years) +# 3: Time step size (years) +# 4: Number of mesh cells +# 5: Number of Stokes degrees of freedom +# 6: Number of temperature degrees of freedom +# 7: Number of degrees of freedom for all compositions +# 8: Number of nonlinear iterations +# 9: Iterations for temperature solver +# 10: Iterations for composition solver 1 +# 11: Iterations for Stokes solver +# 12: Velocity iterations in Stokes preconditioner +# 13: Schur complement iterations in Stokes preconditioner +0 0.000000000000e+00 0.000000000000e+00 512 4851 2145 2145 2 0 0 59 62 61 +1 6.625491997651e+03 6.625491997651e+03 512 4851 2145 2145 14 106 0 622 640 640 +2 1.303237182611e+04 6.406879828463e+03 512 4851 2145 2145 13 102 0 564 580 580 +3 2.000000000000e+04 6.967628173886e+03 512 4851 2145 2145 6 40 0 244 251 251