diff --git a/opm/autodiff/BlackoilModelBase_impl.hpp b/opm/autodiff/BlackoilModelBase_impl.hpp index 249b4f550..f53fe75cf 100644 --- a/opm/autodiff/BlackoilModelBase_impl.hpp +++ b/opm/autodiff/BlackoilModelBase_impl.hpp @@ -248,7 +248,8 @@ namespace detail { asImpl().assemble(reservoir_state, well_state, iteration == 0); residual_norms_history_.push_back(asImpl().computeResidualNorms()); const bool converged = asImpl().getConvergence(dt, iteration); - if (!converged) { + const bool must_solve = (iteration < nonlinear_solver.minIter()) || (!converged); + if (must_solve) { // Compute the nonlinear update. V dx = asImpl().solveJacobianSystem(); @@ -271,7 +272,7 @@ namespace detail { asImpl().updateState(dx, reservoir_state, well_state); } const bool failed = false; // Not needed in this model. - const int linear_iters = converged ? 0 : asImpl().linearIterationsLastSolve(); + const int linear_iters = must_solve ? asImpl().linearIterationsLastSolve() : 0; return IterationReport{ failed, converged, linear_iters }; } diff --git a/opm/autodiff/NonlinearSolver.hpp b/opm/autodiff/NonlinearSolver.hpp index 134de8fc9..f6632a448 100644 --- a/opm/autodiff/NonlinearSolver.hpp +++ b/opm/autodiff/NonlinearSolver.hpp @@ -113,6 +113,18 @@ namespace Opm { /// The step-change size for the relaxation factor. double relaxIncrement() const { return param_.relax_increment_; } + /// The relaxation type (DAMPEN or SOR). + enum RelaxType relaxType() const { return param_.relax_type_; } + + /// The relaxation relative tolerance. + double relaxRelTol() const { return param_.relax_rel_tol_; } + + /// The maximum number of nonlinear iterations allowed. + double maxIter() const { return param_.max_iter_; } + + /// The minimum number of nonlinear iterations allowed. + double minIter() const { return param_.min_iter_; } + private: // --------- Data members --------- SolverParameters param_; @@ -121,12 +133,6 @@ namespace Opm { unsigned int linearIterations_; unsigned int nonlinearIterationsLast_; unsigned int linearIterationsLast_; - - // --------- Private methods --------- - enum RelaxType relaxType() const { return param_.relax_type_; } - double relaxRelTol() const { return param_.relax_rel_tol_; } - double maxIter() const { return param_.max_iter_; } - double minIter() const { return param_.min_iter_; } }; } // namespace Opm diff --git a/opm/autodiff/NonlinearSolver_impl.hpp b/opm/autodiff/NonlinearSolver_impl.hpp index 984b54d42..6e7dce2c9 100644 --- a/opm/autodiff/NonlinearSolver_impl.hpp +++ b/opm/autodiff/NonlinearSolver_impl.hpp @@ -93,21 +93,21 @@ namespace Opm // ---------- Main nonlinear solver loop ---------- do { + // Do the nonlinear step. If we are in a converged state, the + // model will usually do an early return without an expensive + // solve, unless the minIter() count has not been reached yet. IterationReport report = model_->nonlinearIteration(iteration, dt, *this, reservoir_state, well_state); if (report.failed) { OPM_THROW(Opm::NumericalProblem, "Failed to complete a nonlinear iteration."); } - if (report.converged) { - assert(report.linear_iterations == 0); - converged = true; - } + converged = report.converged; linIters += report.linear_iterations; ++iteration; - } while ( (!converged && (iteration <= maxIter())) || (minIter() > iteration)); + } while ( (!converged && (iteration <= maxIter())) || (iteration <= minIter())); if (!converged) { if (model_->terminalOutputEnabled()) { - std::cerr << "WARNING: Failed to compute converged solution in " << iteration << " iterations." << std::endl; + std::cerr << "WARNING: Failed to compute converged solution in " << iteration - 1 << " iterations." << std::endl; } return -1; // -1 indicates that the solver has to be restarted }