20#ifndef OPM_NONLINEAR_SYSTEM_COMPOSITIONAL_IMPL_HEADER_INCLUDED
21#define OPM_NONLINEAR_SYSTEM_COMPOSITIONAL_IMPL_HEADER_INCLUDED
23#ifndef OPM_NONLINEAR_SYSTEM_COMPOSITIONAL_HEADER_INCLUDED
28#include <dune/common/timer.hh>
30#include <opm/common/ErrorMacros.hpp>
31#include <opm/common/OpmLog/OpmLog.hpp>
39template <
class TypeTag>
43 CompWellModel<TypeTag>& wellModel,
44 const bool terminalOutput)
45 :
ParentType(simulator, param, wellModel, terminalOutput)
50template <
class TypeTag>
56 Dune::Timer perfTimer;
60 if (this->grid_.comm().size() > 1
61 && this->grid_.comm().max(lastStepFailed) != this->grid_.comm().min(lastStepFailed)) {
62 OPM_THROW(std::runtime_error,
63 "Misalignment of the parallel simulation run in prepareStep "
64 "- the previous step succeeded on some ranks but failed on others.");
68 this->wellModel().restoreLastValidState();
69 this->simulator_.model().updateFailed();
72 this->simulator_.model().advanceTimeLevel();
78 this->simulator_.problem().resetIterationForNewTimestep();
79 this->simulator_.problem().beginTimeStep();
85template <
class TypeTag>
93 ParentType::initialLinearization(report,
97 Dune::Timer perfTimer;
101 const auto residualMetrics = this->reservoirResidualMetrics();
102 const auto tolerance = this->simulator_.model().newtonMethod().tolerance();
104 for (
int compIdx = 0; compIdx < numEq; ++compIdx) {
105 const std::array<Scalar, 1> residual{residualMetrics[compIdx]};
106 const std::array<ConvergenceReport::ReservoirFailure::Type, 1> types{
109 const std::array<Scalar, 1> tolerances{tolerance};
111 this->addReservoirConvergenceMetrics(
114 this->compNames_.name(compIdx),
118 this->param_.max_residual_allowed_,
119 [
this](
const std::string& message)
121 if (this->terminal_output_) {
122 OpmLog::debug(message);
127 const auto severity = convrep.severityOfWorstFailure();
128 const bool wellConverged = this->wellModel().getWellConvergence();
129 report.converged = convrep.converged() && wellConverged &&
130 this->simulator_.problem().iterationContext().iteration() >= minIter;
132 this->convergence_reports_.back().report.push_back(std::move(convrep));
133 report.update_time += perfTimer.stop();
134 this->residual_norms_history_.push_back(residualMetrics);
137 this->failureReport_ += report;
138 OPM_THROW_PROBLEM(NumericalProblem,
"NaN residual found!");
142 this->failureReport_ += report;
143 OPM_THROW_NOLOG(NumericalProblem,
"Too large residual found!");
147template <
class TypeTag>
148template <
class NonlinearSolverType>
152 NonlinearSolverType& nonlinearSolver)
154 if (this->simulator_.problem().iterationContext().needsTimestepInit()) {
155 this->residual_norms_history_.clear();
156 this->current_relaxation_ = 1.0;
159 this->convergence_reports_.back().report.reserve(numEq);
162 auto result = this->nonlinearIterationNewton(timer, nonlinearSolver);
163 this->simulator_.problem().advanceIteration();
167template <
class TypeTag>
168template <
class NonlinearSolverType>
172 NonlinearSolverType& nonlinearSolver)
177 Dune::Timer perfTimer;
179 this->initialLinearization(report,
180 this->param_.newton_min_iter_,
181 this->param_.newton_max_iter_,
189 BVector x(this->simulator_.model().numGridDof());
190 this->linear_solve_setup_time_ = 0.0;
193 auto& linearizer = this->simulator_.model().linearizer();
194 linearizer.linearizeAuxiliaryEquations();
195 linearizer.finalize();
197 this->solveJacobianSystem(x);
208 this->failureReport_ += report;
215 auto& model = this->simulator_.model();
216 for (
unsigned auxModIdx = 0; auxModIdx < model.numAuxiliaryModules(); ++auxModIdx) {
217 model.auxiliaryModule(auxModIdx)->postSolve(x);
220 if (this->param_.use_update_stabilization_) {
221 bool isOscillate =
false;
222 bool isStagnate =
false;
223 nonlinearSolver.detectOscillations(this->residual_norms_history_,
224 this->residual_norms_history_.size() - 1,
229 this->current_relaxation_ -= nonlinearSolver.relaxIncrement();
230 this->current_relaxation_ = std::max(this->current_relaxation_, nonlinearSolver.relaxMax());
232 if (this->terminalOutputEnabled()) {
233 OpmLog::info(
" Oscillating behavior detected: Relaxation set to "
238 nonlinearSolver.stabilizeNonlinearUpdate(x, this->dx_old_, this->current_relaxation_);
241 this->updateSolution(x);
248template <
class TypeTag>
256 const auto& elemMapper = this->simulator_.model().elementMapper();
257 const auto& gridView = this->simulator_.gridView();
259 for (
const auto& elem : elements(gridView, Dune::Partitions::interior)) {
260 const unsigned globalElemIdx = elemMapper.index(elem);
261 const auto& priVarsNew = this->simulator_.model().solution(0)[globalElemIdx];
262 const auto& priVarsOld = this->simulator_.model().solution(1)[globalElemIdx];
264 for (
int pvIdx = 0; pvIdx < static_cast<int>(priVarsNew.size()); ++pvIdx) {
265 const auto delta = priVarsNew[pvIdx] - priVarsOld[pvIdx];
266 resultDelta += delta * delta;
267 resultDenom += priVarsNew[pvIdx] * priVarsNew[pvIdx];
271 resultDelta = gridView.comm().sum(resultDelta);
272 resultDenom = gridView.comm().sum(resultDenom);
274 return resultDenom > 0.0 ? resultDelta / resultDenom : 0.0;
277template <
class TypeTag>
282 auto& jacobian = this->simulator_.model().linearizer().jacobian();
283 auto& residual = this->simulator_.model().linearizer().residual();
284 auto& linSolver = this->simulator_.model().newtonMethod().linearSolver();
288 Dune::Timer perfTimer;
290 linSolver.prepare(jacobian, residual);
291 this->linear_solve_setup_time_ = perfTimer.stop();
292 linSolver.setResidual(residual);
293 linSolver.getResidual(residual);
294 linSolver.setMatrix(jacobian);
298template <
class TypeTag>
299std::vector<typename NonlinearSystemCompositional<TypeTag>::Scalar>
303 const auto& model = this->simulator_.model();
304 const auto& residual = model.linearizer().residual();
305 const auto& constraintsMap = model.linearizer().constraintsMap();
307 std::vector<Scalar> residualMetrics(numEq, 0.0);
309 for (
unsigned dofIdx = 0; dofIdx < residual.size(); ++dofIdx) {
310 if (dofIdx >= model.numGridDof() || model.dofTotalVolume(dofIdx) <= 0.0) {
314 if (constraintsMap.count(dofIdx) > 0) {
318 const auto& localResidual = residual[dofIdx];
319 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
320 residualMetrics[eqIdx] = std::max(
321 residualMetrics[eqIdx],
322 std::abs(localResidual[eqIdx] * model.eqWeight(dofIdx, eqIdx)));
326 if (this->grid_.comm().size() > 1 && !residualMetrics.empty()) {
327 this->grid_.comm().max(residualMetrics.data(), residualMetrics.size());
330 return residualMetrics;
Definition: ConvergenceReport.hpp:38
Definition: NonlinearSystemCompositional.hpp:42
SimulatorReportSingle prepareStep(const SimulatorTimerInterface &timer)
Definition: NonlinearSystemCompositional_impl.hpp:53
void initialLinearization(SimulatorReportSingle &report, int minIter, int maxIter, const SimulatorTimerInterface &timer) override
Definition: NonlinearSystemCompositional_impl.hpp:88
typename ParentType::Scalar Scalar
Definition: NonlinearSystemCompositional.hpp:49
NonlinearSystemCompositional(Simulator &simulator, const ModelParameters ¶m, CompWellModel< TypeTag > &wellModel, bool terminalOutput)
Definition: NonlinearSystemCompositional_impl.hpp:41
Dune::BlockVector< VectorBlockType > BVector
Definition: NonlinearSystemCompositional.hpp:57
Definition: NonlinearSystem.hpp:44
std::vector< StepReport > convergence_reports_
Definition: NonlinearSystem.hpp:169
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: NonlinearSystem.hpp:51
GetPropType< TypeTag, Properties::Simulator > Simulator
Definition: NonlinearSystem.hpp:47
Interface class for SimulatorTimer objects, to be improved.
Definition: SimulatorTimerInterface.hpp:34
virtual int reportStepNum() const
Current report step number. This might differ from currentStepNum in case of sub stepping.
Definition: SimulatorTimerInterface.hpp:109
virtual bool lastStepFailed() const =0
Return true if last time step failed.
virtual double currentStepLength() const =0
virtual double simulationTimeElapsed() const =0
virtual int currentStepNum() const =0
Definition: blackoilbioeffectsmodules.hh:45
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
Solver parameters for the NonlinearSystemBlackOilReservoir.
Definition: BlackoilModelParameters.hpp:201
A struct for returning timing data from a simulator to its caller.
Definition: SimulatorReport.hpp:34
double linear_solve_time
Definition: SimulatorReport.hpp:43
bool converged
Definition: SimulatorReport.hpp:55
double pre_post_time
Definition: SimulatorReport.hpp:40
double linear_solve_setup_time
Definition: SimulatorReport.hpp:42
unsigned int total_newton_iterations
Definition: SimulatorReport.hpp:50
double update_time
Definition: SimulatorReport.hpp:45
unsigned int total_linear_iterations
Definition: SimulatorReport.hpp:51