opm-simulators
BlackoilModelTPSA.hpp
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  Copyright 2025 NORCE AS
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 2 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 
21  Consult the COPYING file in the top-level source directory of this
22  module for the precise wording of the license and the list of
23  copyright holders.
24 */
25 #ifndef BLACK_OIL_MODEL_TPSA_HPP
26 #define BLACK_OIL_MODEL_TPSA_HPP
27 
28 #include <opm/common/ErrorMacros.hpp>
29 #include <opm/common/OpmLog/OpmLog.hpp>
30 
31 #include <opm/simulators/flow/BlackoilModel.hpp>
32 
33 #include <stdexcept>
34 #include <string>
35 
36 #include <fmt/format.h>
37 
38 
39 namespace Opm {
40 
44 template <class TypeTag>
45 class BlackoilModelTPSA : public BlackoilModel<TypeTag>
46 {
48 
51 
52 public:
54 
63  explicit BlackoilModelTPSA(Simulator& simulator,
64  const ModelParameters& param,
65  BlackoilWellModel<TypeTag>& well_model,
66  const bool terminal_output)
67  : ParentType(simulator, param, well_model, terminal_output)
68  {}
69 
81  template <class NonlinearSolverType>
83  NonlinearSolverType& nonlinear_solver)
84  {
85  SimulatorReportSingle report {};
86  const auto& problem = this->simulator_.problem();
87  if (problem.fixedStressScheme()) {
88  report = nonlinearIterationFixedStressTPSA(timer, nonlinear_solver);
89  }
90  else if (problem.laggedScheme()) {
91  report = nonlinearIterationLaggedTPSA(timer, nonlinear_solver);
92  }
93  else {
94  std::string msg = "Unknown Flow-TPSA coupling scheme!";
95  OpmLog::error(msg);
96  throw std::runtime_error(msg);
97  }
98  return report;
99  }
100 
109  template <class NonlinearSolverType>
111  NonlinearSolverType& nonlinear_solver)
112  {
113  // Runtime parameters
114  const auto& [minSeqIter, maxSeqIter] = this->simulator_.problem().fixedStressParameters();
115  SimulatorReportSingle reportFlow;
116 
117  // Max. no. of fixed-stress iterations reached: warn and move on
118  if (seqIter_ >= maxSeqIter) {
119  // Warning
120  std::string msg = fmt::format("TPSA: Fixed-stress scheme reached max iterations (={})!", maxSeqIter);
121  OpmLog::warning(msg);
122 
123  // Return true Flow convergence to move to next time step and reset other variables
124  reportFlow.converged = true;
125  seqIter_ = 0;
126 
127  return reportFlow;
128  }
129 
130  // Prepare before first iteration
131  if (seqIter_ == 0) {
132  this->simulator_.problem().geoMechModel().prepareTPSA();
133  }
134 
135  // Run Flow nonlinear iteration
136  reportFlow = ParentType::nonlinearIteration(timer, nonlinear_solver);
137 
138  // Solve TPSA equations if:
139  // (i) Flow has converged and run more than min number of Newton iterations
140  // (ii) we have run at least min. number of fixed-stress iterations
141  const auto iteration = this->simulator_.problem().iterationContext().iteration();
142  if (reportFlow.converged && iteration >= this->param_.newton_min_iter_) {
143  // Solve TPSA equations
144  bool tpsaConv = solveTpsaEquations();
145  ++seqIter_;
146 
147  // Fixed-stress convergence check:
148  // If the initial residual error, hence check for no. linearizations == 1, was small enough, we have
149  // convergence in the fixed-stress iterations
150  if (tpsaConv
151  && this->simulator_.problem().geoMechModel().newtonMethod().numLinearizations() == 1
152  && seqIter_ >= minSeqIter) {
153  // Info
154  std::string msg = fmt::format("TPSA: Fixed-stress scheme converged in {} iterations", seqIter_);
155  OpmLog::info(msg);
156 
157  // Reset
158  seqIter_ = 0;
159 
160  return reportFlow;
161  }
162  // Throw error if TPSA did not converge. Will force time step cuts in the outer Flow loop.
163  else if (!tpsaConv) {
164  // Reset
165  seqIter_ = 0;
166 
167  throw std::runtime_error("TPSA: Fixed stress scheme update failed!");
168  }
169 
170  // Return Flow convergence false to do another fixed-stress iteration
171  reportFlow.converged = false;
172  }
173 
174  return reportFlow;
175  }
176 
186  template <class NonlinearSolverType>
188  NonlinearSolverType& nonlinear_solver)
189  {
190  // Run Flow nonlinear iteration
191  auto reportFlow = ParentType::nonlinearIteration(timer, nonlinear_solver);
192 
193  // Update TPSA geomechanics from successful Flow run
194  const auto iteration = this->simulator_.problem().iterationContext().iteration();
195  if (reportFlow.converged && iteration >= this->param_.newton_min_iter_) {
196  // Prepare before TPSA solve
197  this->simulator_.problem().geoMechModel().prepareTPSA();
198 
199  // Solve TPSA equations
200  bool tpsaConv = solveTpsaEquations();
201 
202  // Throw error if TPSA did not converge. Will force time step cuts in the outer Flow loop.
203  if (!tpsaConv) {
204  throw std::runtime_error("TPSA: Lagged scheme update failed!");
205  }
206  }
207 
208  return reportFlow;
209  }
210 
219  {
220  // Run Newthon method for TPSA equations
221  return this->simulator_.problem().geoMechModel().newtonMethod().apply();
222  }
223 
224 private:
225  int seqIter_{0};
226 }; // class BlackoilModelTPSA
227 
228 } // namespace Opm
229 
230 #endif
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(...))
Definition: propertysystem.hh:233
Class for handling the blackoil well model.
Definition: BlackoilModelProperties.hpp:32
const ModelParameters & param() const
Returns const reference to model parameters.
Definition: BlackoilModel.hpp:329
bool solveTpsaEquations()
Solve TPSA geomechanics equations.
Definition: BlackoilModelTPSA.hpp:218
SimulatorReportSingle nonlinearIteration(const SimulatorTimerInterface &timer, NonlinearSolverType &nonlinear_solver)
Called once per nonlinear iteration.
Definition: BlackoilModel_impl.hpp:245
SimulatorReportSingle nonlinearIteration(const SimulatorTimerInterface &timer, NonlinearSolverType &nonlinear_solver)
Perform a nonlinear iteration updating Flow and TPSA geomechanics.
Definition: BlackoilModelTPSA.hpp:82
SimulatorReportSingle nonlinearIterationLaggedTPSA(const SimulatorTimerInterface &timer, NonlinearSolverType &nonlinear_solver)
Perform a nonlinear iteration updating Flow and TPSA geomechanics in a lagged scheme.
Definition: BlackoilModelTPSA.hpp:187
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Solver parameters for the BlackoilModel.
Definition: BlackoilModelParameters.hpp:193
Black oil model for coupling Flow simulations with TPSA geomechanics.
Definition: BlackoilModelTPSA.hpp:45
BlackoilModelTPSA(Simulator &simulator, const ModelParameters &param, BlackoilWellModel< TypeTag > &well_model, const bool terminal_output)
Constructor.
Definition: BlackoilModelTPSA.hpp:63
A struct for returning timing data from a simulator to its caller.
Definition: SimulatorReport.hpp:33
Interface class for SimulatorTimer objects, to be improved.
Definition: SimulatorTimerInterface.hpp:33
SimulatorReportSingle nonlinearIterationFixedStressTPSA(const SimulatorTimerInterface &timer, NonlinearSolverType &nonlinear_solver)
Perform a nonlinear iteration updating Flow and TPSA geomechanics in a fixed-stress, iterative loop.
Definition: BlackoilModelTPSA.hpp:110
A model implementation for three-phase black oil.
Definition: BlackoilModel.hpp:60