diff --git a/opm/simulators/flow/NonlinearSolverEbos.cpp b/opm/simulators/flow/NonlinearSolverEbos.cpp index 7502cea36..1ddd5b51f 100644 --- a/opm/simulators/flow/NonlinearSolverEbos.cpp +++ b/opm/simulators/flow/NonlinearSolverEbos.cpp @@ -20,7 +20,13 @@ #include #include +#include +#include + +#include + #include +#include namespace Opm { namespace detail { @@ -59,5 +65,56 @@ void detectOscillations(const std::vector>& residualHistory, oscillate = (oscillatePhase > 1); } +template +void stabilizeNonlinearUpdate(BVector& dx, BVector& dxOld, + const double omega, + NonlinearRelaxType relaxType) +{ + // The dxOld is updated with dx. + // If omega is equal to 1., no relaxtion will be appiled. + + BVector tempDxOld = dxOld; + dxOld = dx; + + switch (relaxType) { + case NonlinearRelaxType::Dampen: { + if (omega == 1.) { + return; + } + for (auto& d : dx) { + d *= omega; + } + return; + } + case NonlinearRelaxType::SOR: { + if (omega == 1.) { + return; + } + auto i = dx.size(); + for (i = 0; i < dx.size(); ++i) { + dx[i] *= omega; + tempDxOld[i] *= (1.-omega); + dx[i] += tempDxOld[i]; + } + return; + } + default: + OPM_THROW(std::runtime_error, "Can only handle Dampen and SOR relaxation type."); + } + + return; +} + +template using BV = Dune::BlockVector>; +#define INSTANCE(Size) \ + template void stabilizeNonlinearUpdate>(BV&, BV&, \ + const double, NonlinearRelaxType); +INSTANCE(1) +INSTANCE(2) +INSTANCE(3) +INSTANCE(4) +INSTANCE(5) +INSTANCE(6) + } // namespace detail } // namespace Opm diff --git a/opm/simulators/flow/NonlinearSolverEbos.hpp b/opm/simulators/flow/NonlinearSolverEbos.hpp index 6d793da28..2f65161fb 100644 --- a/opm/simulators/flow/NonlinearSolverEbos.hpp +++ b/opm/simulators/flow/NonlinearSolverEbos.hpp @@ -80,15 +80,6 @@ struct NewtonRelaxationType { namespace Opm { -namespace detail { - -/// Detect oscillation or stagnation in a given residual history. -void detectOscillations(const std::vector>& residualHistory, - const int it, const int numPhases, const double relaxRelTol, - bool& oscillate, bool& stagnate); - -} - class WellState; // Available relaxation scheme types. @@ -97,6 +88,21 @@ enum class NonlinearRelaxType { SOR }; +namespace detail { + +/// Detect oscillation or stagnation in a given residual history. +void detectOscillations(const std::vector>& residualHistory, + const int it, const int numPhases, const double relaxRelTol, + bool& oscillate, bool& stagnate); + +/// Apply a stabilization to dx, depending on dxOld and relaxation parameters. +/// Implemention for Dune block vectors. +template +void stabilizeNonlinearUpdate(BVector& dx, BVector& dxOld, + const double omega, NonlinearRelaxType relaxType); + +} + /// A nonlinear solver class suitable for general fully-implicit models, /// as well as pressure, transport and sequential models. template @@ -298,40 +304,7 @@ enum class NonlinearRelaxType { template void stabilizeNonlinearUpdate(BVector& dx, BVector& dxOld, const double omega) const { - // The dxOld is updated with dx. - // If omega is equal to 1., no relaxtion will be appiled. - - BVector tempDxOld = dxOld; - dxOld = dx; - - switch (relaxType()) { - case NonlinearRelaxType::Dampen: { - if (omega == 1.) { - return; - } - auto i = dx.size(); - for (i = 0; i < dx.size(); ++i) { - dx[i] *= omega; - } - return; - } - case NonlinearRelaxType::SOR: { - if (omega == 1.) { - return; - } - auto i = dx.size(); - for (i = 0; i < dx.size(); ++i) { - dx[i] *= omega; - tempDxOld[i] *= (1.-omega); - dx[i] += tempDxOld[i]; - } - return; - } - default: - OPM_THROW(std::runtime_error, "Can only handle Dampen and SOR relaxation type."); - } - - return; + detail::stabilizeNonlinearUpdate(dx, dxOld, omega, this->relaxType()); } /// The greatest relaxation factor (i.e. smallest factor) allowed.