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>
45template <
class TypeTag>
49 CompWellModel<TypeTag>& wellModel,
50 const bool terminalOutput)
51 :
ParentType(simulator, param, wellModel, terminalOutput)
54 || Parameters::Get<Parameters::AcceleratorMode>() !=
"none") {
55 OPM_THROW(std::invalid_argument,
56 "Compositional runs solve the linear systems on the CPU only."
57 " Please use --linear-solver-accelerator=cpu and --accelerator-mode=none.");
63template <
class TypeTag>
69 Dune::Timer perfTimer;
73 if (this->grid_.comm().size() > 1
74 && this->grid_.comm().max(lastStepFailed) != this->grid_.comm().min(lastStepFailed)) {
75 OPM_THROW(std::runtime_error,
76 "Misalignment of the parallel simulation run in prepareStep "
77 "- the previous step succeeded on some ranks but failed on others.");
81 this->wellModel().restoreLastValidState();
82 this->simulator_.model().updateFailed();
85 this->simulator_.model().advanceTimeLevel();
91 this->simulator_.problem().resetIterationForNewTimestep();
92 this->simulator_.problem().beginTimeStep();
98template <
class TypeTag>
106 ParentType::initialLinearization(report,
110 Dune::Timer perfTimer;
114 const auto residualMetrics = this->reservoirResidualMetrics();
115 const auto tolerance = this->simulator_.model().newtonMethod().tolerance();
117 for (
int compIdx = 0; compIdx < numEq; ++compIdx) {
118 const std::array<Scalar, 1> residual{residualMetrics[compIdx]};
119 const std::array<ConvergenceReport::ReservoirFailure::Type, 1> types{
122 const std::array<Scalar, 1> tolerances{tolerance};
124 this->addReservoirConvergenceMetrics(
127 this->compNames_.name(compIdx),
131 this->param_.max_residual_allowed_,
132 [
this](
const std::string& message)
134 if (this->terminal_output_) {
135 OpmLog::debug(message);
140 const auto severity = convrep.severityOfWorstFailure();
141 const bool wellConverged = this->wellModel().getWellConvergence();
142 report.converged = convrep.converged() && wellConverged &&
143 this->simulator_.problem().iterationContext().iteration() >= minIter;
145 this->convergence_reports_.back().report.push_back(std::move(convrep));
146 report.update_time += perfTimer.stop();
147 this->residual_norms_history_.push_back(residualMetrics);
150 this->failureReport_ += report;
151 OPM_THROW_PROBLEM(NumericalProblem,
"NaN residual found!");
155 this->failureReport_ += report;
156 OPM_THROW_NOLOG(NumericalProblem,
"Too large residual found!");
160template <
class TypeTag>
161template <
class NonlinearSolverType>
165 NonlinearSolverType& nonlinearSolver)
167 if (this->simulator_.problem().iterationContext().needsTimestepInit()) {
168 this->residual_norms_history_.clear();
169 this->current_relaxation_ = 1.0;
172 this->convergence_reports_.back().report.reserve(numEq);
175 auto result = this->nonlinearIterationNewton(timer, nonlinearSolver);
176 this->simulator_.problem().advanceIteration();
180template <
class TypeTag>
181template <
class NonlinearSolverType>
185 NonlinearSolverType& nonlinearSolver)
190 Dune::Timer perfTimer;
192 this->initialLinearization(report,
193 this->param_.newton_min_iter_,
194 this->param_.newton_max_iter_,
202 BVector x(this->simulator_.model().numGridDof());
203 this->linear_solve_setup_time_ = 0.0;
206 auto& linearizer = this->simulator_.model().linearizer();
207 linearizer.linearizeAuxiliaryEquations();
208 linearizer.finalize();
210 this->solveJacobianSystem(x);
221 this->failureReport_ += report;
228 auto& model = this->simulator_.model();
229 for (
unsigned auxModIdx = 0; auxModIdx < model.numAuxiliaryModules(); ++auxModIdx) {
230 model.auxiliaryModule(auxModIdx)->postSolve(x);
233 if (this->param_.use_update_stabilization_) {
234 bool isOscillate =
false;
235 bool isStagnate =
false;
236 nonlinearSolver.detectOscillations(this->residual_norms_history_,
237 this->residual_norms_history_.size() - 1,
242 this->current_relaxation_ -= nonlinearSolver.relaxIncrement();
243 this->current_relaxation_ = std::max(this->current_relaxation_, nonlinearSolver.relaxMax());
245 if (this->terminalOutputEnabled()) {
246 OpmLog::info(
" Oscillating behavior detected: Relaxation set to "
251 nonlinearSolver.stabilizeNonlinearUpdate(x, this->dx_old_, this->current_relaxation_);
254 this->updateSolution(x);
261template <
class TypeTag>
269 const auto& elemMapper = this->simulator_.model().elementMapper();
270 const auto& gridView = this->simulator_.gridView();
272 for (
const auto& elem : elements(gridView, Dune::Partitions::interior)) {
273 const unsigned globalElemIdx = elemMapper.index(elem);
274 const auto& priVarsNew = this->simulator_.model().solution(0)[globalElemIdx];
275 const auto& priVarsOld = this->simulator_.model().solution(1)[globalElemIdx];
277 for (
int pvIdx = 0; pvIdx < static_cast<int>(priVarsNew.size()); ++pvIdx) {
278 const auto delta = priVarsNew[pvIdx] - priVarsOld[pvIdx];
279 resultDelta += delta * delta;
280 resultDenom += priVarsNew[pvIdx] * priVarsNew[pvIdx];
284 resultDelta = gridView.comm().sum(resultDelta);
285 resultDenom = gridView.comm().sum(resultDenom);
287 return resultDenom > 0.0 ? resultDelta / resultDenom : 0.0;
290template <
class TypeTag>
295 auto& jacobian = this->simulator_.model().linearizer().jacobian();
296 auto& residual = this->simulator_.model().linearizer().residual();
297 auto& linSolver = this->simulator_.model().newtonMethod().linearSolver();
301 this->param_.matrix_add_well_contributions_,
302 !this->wellModel().empty());
306 Dune::Timer perfTimer;
308 linSolver.prepare(jacobian, residual);
309 this->linear_solve_setup_time_ = perfTimer.stop();
310 linSolver.setResidual(residual);
311 linSolver.getResidual(residual);
312 linSolver.setMatrix(jacobian);
316template <
class TypeTag>
317std::vector<typename NonlinearSystemCompositional<TypeTag>::Scalar>
321 const auto& model = this->simulator_.model();
322 const auto& residual = model.linearizer().residual();
323 const auto& constraintsMap = model.linearizer().constraintsMap();
325 std::vector<Scalar> residualMetrics(numEq, 0.0);
329 const auto& elemMapper = model.elementMapper();
330 for (
const auto& elem : elements(this->simulator_.gridView(), Dune::Partitions::interior)) {
331 const unsigned dofIdx = elemMapper.index(elem);
332 if (dofIdx >= model.numGridDof() || model.dofTotalVolume(dofIdx) <= 0.0) {
336 if (constraintsMap.count(dofIdx) > 0) {
340 const auto& localResidual = residual[dofIdx];
341 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
342 residualMetrics[eqIdx] = std::max(
343 residualMetrics[eqIdx],
344 std::abs(localResidual[eqIdx] * model.eqWeight(dofIdx, eqIdx)));
348 if (this->grid_.comm().size() > 1 && !residualMetrics.empty()) {
349 this->grid_.comm().max(residualMetrics.data(), residualMetrics.size());
352 return residualMetrics;
Definition: ConvergenceReport.hpp:38
Definition: NonlinearSystemCompositional.hpp:42
SimulatorReportSingle prepareStep(const SimulatorTimerInterface &timer)
Definition: NonlinearSystemCompositional_impl.hpp:66
void initialLinearization(SimulatorReportSingle &report, int minIter, int maxIter, const SimulatorTimerInterface &timer) override
Definition: NonlinearSystemCompositional_impl.hpp:101
typename ParentType::Scalar Scalar
Definition: NonlinearSystemCompositional.hpp:49
NonlinearSystemCompositional(Simulator &simulator, const ModelParameters ¶m, CompWellModel< TypeTag > &wellModel, bool terminalOutput)
Definition: NonlinearSystemCompositional_impl.hpp:47
Dune::BlockVector< VectorBlockType > BVector
Definition: NonlinearSystemCompositional.hpp:57
Definition: NonlinearSystem.hpp:44
std::vector< StepReport > convergence_reports_
Definition: NonlinearSystem.hpp:170
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
LinearSolverAcceleratorType linearSolverAcceleratorTypeFromCLI()
Converts the CLI option for linear solver accelerator to a LinearSolverAcceleratorType.
Definition: LinearSolverAcceleratorType.hpp:89
Definition: blackoilbioeffectsmodules.hh:45
void checkUmfpackMatrixAddWell(const PropertyTree &prm, bool matrixAddWellContributions, bool hasWells)
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
This file provides the infrastructure to retrieve run-time parameters.
Solver parameters for the NonlinearSystemBlackOilReservoir.
Definition: BlackoilModelParameters.hpp:208
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:57
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