opm-simulators
WellInterface.hpp
1 /*
2  Copyright 2017 SINTEF Digital, Mathematics and Cybernetics.
3  Copyright 2017 Statoil ASA.
4  Copyright 2017 IRIS
5  Copyright 2019 Norce
6 
7  This file is part of the Open Porous Media project (OPM).
8 
9  OPM is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  OPM is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with OPM. If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #ifndef OPM_WELLINTERFACE_HEADER_INCLUDED
24 #define OPM_WELLINTERFACE_HEADER_INCLUDED
25 
26 // NOTE: GasLiftSingleWell.hpp includes StandardWell.hpp which includes ourself
27 // (WellInterface.hpp), so we need to forward declare GasLiftSingleWell
28 // for it to be defined in this file. Similar for BlackoilWellModel
29 namespace Opm {
30  template<typename TypeTag> class GasLiftSingleWell;
31  template<typename TypeTag> class BlackoilWellModel;
32 }
33 
34 #include <opm/common/OpmLog/OpmLog.hpp>
35 #include <opm/common/ErrorMacros.hpp>
36 #include <opm/common/Exceptions.hpp>
37 
38 #include <opm/input/eclipse/Schedule/Well/WellTestState.hpp>
39 
40 #include <opm/material/fluidstates/BlackOilFluidState.hpp>
41 
43 
45 
46 #include <opm/simulators/wells/BlackoilWellModel.hpp>
47 #include <opm/simulators/wells/GasLiftGroupInfo.hpp>
48 #include <opm/simulators/wells/GasLiftSingleWell.hpp>
49 #include <opm/simulators/wells/GasLiftSingleWellGeneric.hpp>
50 #include <opm/simulators/wells/PerforationData.hpp>
51 #include <opm/simulators/wells/WellInterfaceIndices.hpp>
52 #include <opm/simulators/wells/WellProdIndexCalculator.hpp>
53 #include <opm/simulators/wells/WellState.hpp>
54 
55 #include <opm/simulators/timestepping/ConvergenceReport.hpp>
56 
57 #include <opm/simulators/utils/DeferredLogger.hpp>
58 
59 #include <dune/common/fmatrix.hh>
60 #include <dune/istl/bcrsmatrix.hh>
61 #include <dune/istl/matrixmatrix.hh>
62 
63 #include <opm/material/densead/Evaluation.hpp>
64 
65 #include <vector>
66 
67 namespace Opm
68 {
69 
70 class WellInjectionProperties;
71 class WellProductionProperties;
72 template<typename Scalar, typename IndexTraits> class GroupStateHelper;
73 
74 template<typename TypeTag>
75 class WellInterface : public WellInterfaceIndices<GetPropType<TypeTag, Properties::FluidSystem>,
76  GetPropType<TypeTag, Properties::Indices>>
77 {
78  using Base = WellInterfaceIndices<GetPropType<TypeTag, Properties::FluidSystem>,
79  GetPropType<TypeTag, Properties::Indices>>;
80 public:
81  using Grid = GetPropType<TypeTag, Properties::Grid>;
82  using Simulator = GetPropType<TypeTag, Properties::Simulator>;
83  using Scalar = GetPropType<TypeTag, Properties::Scalar>;
84  using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
85  using IndexTraits = typename FluidSystem::IndexTraitsType;
86  using Indices = GetPropType<TypeTag, Properties::Indices>;
87  using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
88  using MaterialLaw = GetPropType<TypeTag, Properties::MaterialLaw>;
89  using SparseMatrixAdapter = GetPropType<TypeTag, Properties::SparseMatrixAdapter>;
90  using RateVector = GetPropType<TypeTag, Properties::RateVector>;
91  using GasLiftSingleWell = ::Opm::GasLiftSingleWell<TypeTag>;
92  using GLiftEclWells = typename GasLiftGroupInfo<Scalar, IndexTraits>::GLiftEclWells;
93 
94  using VectorBlockType = Dune::FieldVector<Scalar, Indices::numEq>;
95  using MatrixBlockType = Dune::FieldMatrix<Scalar, Indices::numEq, Indices::numEq>;
96  using Eval = typename Base::Eval;
97  using BVector = Dune::BlockVector<VectorBlockType>;
98  using PressureMatrix = Dune::BCRSMatrix<Opm::MatrixBlock<Scalar, 1, 1>>;
99 
100  using WellStateType = WellState<Scalar, IndexTraits>;
101  using SingleWellStateType = SingleWellState<Scalar, IndexTraits>;
102  using GroupStateHelperType = GroupStateHelper<Scalar, IndexTraits>;
103 
104  using RateConverterType =
105  typename WellInterfaceFluidSystem<FluidSystem>::RateConverterType;
106 
107  using WellInterfaceFluidSystem<FluidSystem>::Gas;
108  using WellInterfaceFluidSystem<FluidSystem>::Oil;
109  using WellInterfaceFluidSystem<FluidSystem>::Water;
110 
111  using ModelParameters = typename Base::ModelParameters;
112 
113  static constexpr bool has_solvent = getPropValue<TypeTag, Properties::EnableSolvent>();
114  static constexpr bool has_zFraction = getPropValue<TypeTag, Properties::EnableExtbo>();
115  static constexpr bool has_polymer = getPropValue<TypeTag, Properties::EnablePolymer>();
116  static constexpr EnergyModules energyModuleType = getPropValue<TypeTag, Properties::EnergyModuleType>();
117  static constexpr bool has_energy = energyModuleType == EnergyModules::FullyImplicitThermal;
118 
119  // flag for polymer molecular weight related
120  static constexpr bool has_polymermw = getPropValue<TypeTag, Properties::EnablePolymerMW>();
121  static constexpr bool has_foam = getPropValue<TypeTag, Properties::EnableFoam>();
122  static constexpr bool has_brine = getPropValue<TypeTag, Properties::EnableBrine>();
123  static constexpr bool has_watVapor = getPropValue<TypeTag, Properties::EnableVapwat>();
124  static constexpr bool has_disgas_in_water = getPropValue<TypeTag, Properties::EnableDisgasInWater>();
125  static constexpr bool has_saltPrecip = getPropValue<TypeTag, Properties::EnableSaltPrecipitation>();
126  static constexpr bool has_bioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>();
127  static constexpr bool has_micp = Indices::enableMICP;
128 
129  // For the conversion between the surface volume rate and reservoir voidage rate
130  using FluidState = BlackOilFluidState<Eval,
131  FluidSystem,
132  energyModuleType != EnergyModules::NoTemperature,
133  energyModuleType == EnergyModules::FullyImplicitThermal,
134  Indices::compositionSwitchIdx >= 0,
135  has_watVapor,
136  has_brine,
137  has_saltPrecip,
138  has_disgas_in_water,
139  has_solvent,
140  Indices::numPhases >;
142  WellInterface(const Well& well,
143  const ParallelWellInfo<Scalar>& pw_info,
144  const int time_step,
145  const ModelParameters& param,
146  const RateConverterType& rate_converter,
147  const int pvtRegionIdx,
148  const int num_conservation_quantities,
149  const int num_phases,
150  const int index_of_well,
151  const std::vector<PerforationData<Scalar>>& perf_data);
152 
154  virtual ~WellInterface() = default;
155 
156  virtual void init(const std::vector<Scalar>& depth_arg,
157  const Scalar gravity_arg,
158  const std::vector<Scalar>& B_avg,
159  const bool changed_to_open_this_step);
160 
161  virtual ConvergenceReport getWellConvergence(const GroupStateHelperType& groupStateHelper,
162  const std::vector<Scalar>& B_avg,
163  const bool relax_tolerance) const = 0;
164 
165  virtual void solveEqAndUpdateWellState(const Simulator& simulator,
166  const GroupStateHelperType& groupStateHelper,
167  WellStateType& well_state) = 0;
168 
169  void assembleWellEq(const Simulator& simulator,
170  const double dt,
171  const GroupStateHelperType& groupStateHelper,
172  WellStateType& well_state);
173 
174  void assembleWellEqWithoutIteration(const Simulator& simulator,
175  const GroupStateHelperType& groupStateHelper,
176  const double dt,
177  WellStateType& well_state,
178  const bool solving_with_zero_rate);
179 
180  // TODO: better name or further refactoring the function to make it more clear
181  void prepareWellBeforeAssembling(const Simulator& simulator,
182  const double dt,
183  const GroupStateHelperType& groupStateHelper,
184  WellStateType& well_state);
185 
186  virtual void computeWellRatesWithBhp(const Simulator& ebosSimulator,
187  const Scalar& bhp,
188  std::vector<Scalar>& well_flux,
189  DeferredLogger& deferred_logger) const = 0;
190 
191  virtual std::optional<Scalar>
192  computeBhpAtThpLimitProdWithAlq(const Simulator& ebos_simulator,
193  const GroupStateHelperType& groupStateHelper,
194  const SummaryState& summary_state,
195  const Scalar alq_value,
196  bool iterate_if_no_solution) const = 0;
197 
198  std::optional<Scalar>
199  computeBhpAtThpLimitProdWithAlqUsingIPR(const Simulator& simulator,
200  const WellStateType& well_state,
201  Scalar bhp,
202  const SummaryState& summary_state,
203  const Scalar alq_value);
206  virtual void recoverWellSolutionAndUpdateWellState(const Simulator& simulator,
207  const BVector& x,
208  const GroupStateHelperType& groupStateHelper,
209  WellStateType& well_state) = 0;
210 
212  virtual void apply(const BVector& x, BVector& Ax) const = 0;
213 
215  virtual void apply(BVector& r) const = 0;
216 
217  // TODO: before we decide to put more information under mutable, this function is not const
218  virtual void computeWellPotentials(const Simulator& simulator,
219  const WellStateType& well_state,
220  const GroupStateHelperType& groupStateHelper,
221  std::vector<Scalar>& well_potentials) = 0;
222 
223  virtual void updateWellStateWithTarget(const Simulator& simulator,
224  const GroupStateHelperType& groupStateHelper,
225  WellStateType& well_state) const;
226 
227  virtual void scaleSegmentRatesAndPressure(WellStateType& well_state) const;
228 
229  virtual void computeWellRatesWithBhpIterations(const Simulator& simulator,
230  const Scalar& bhp,
231  const GroupStateHelperType& groupStateHelper,
232  std::vector<Scalar>& well_flux) const = 0;
233 
234  bool wellUnderZeroRateTarget(const GroupStateHelperType& groupStateHelper) const;
235 
236  bool stoppedOrZeroRateTarget(const GroupStateHelperType& groupStateHelper) const;
237 
238  bool updateWellStateWithTHPTargetProd(const Simulator& simulator,
239  WellStateType& well_state,
240  const GroupStateHelperType& groupStateHelper) const;
241 
242  bool wellUnderZeroGroupRateTarget(const GroupStateHelperType& groupStateHelper,
243  const std::optional<bool> group_control = std::nullopt) const;
244 
245  enum class IndividualOrGroup { Individual, Group, Both };
246  bool updateWellControl(const Simulator& simulator,
247  const IndividualOrGroup iog,
248  const GroupStateHelperType& groupStateHelper,
249  WellStateType& well_state) /* const */;
250 
251  bool updateWellControlAndStatusLocalIteration(const Simulator& simulator,
252  const GroupStateHelperType& groupStateHelper,
253  const Well::InjectionControls& inj_controls,
254  const Well::ProductionControls& prod_controls,
255  const Scalar WQTotal,
256  WellStateType& well_state,
257  const bool fixed_control,
258  const bool fixed_status,
259  const bool solving_with_zero_rate);
260 
261  virtual void updatePrimaryVariables(const GroupStateHelperType& groupStateHelper) = 0;
262 
263  virtual void calculateExplicitQuantities(const Simulator& simulator,
264  const GroupStateHelperType& groupStateHelper) = 0; // should be const?
265 
266  virtual void updateProductivityIndex(const Simulator& simulator,
267  const WellProdIndexCalculator<Scalar>& wellPICalc,
268  WellStateType& well_state,
269  DeferredLogger& deferred_logger) const = 0;
270 
271  // Add well contributions to matrix
272  virtual void addWellContributions(SparseMatrixAdapter&) const = 0;
273 
274  virtual void addWellPressureEquations(PressureMatrix& mat,
275  const BVector& x,
276  const int pressureVarIndex,
277  const bool use_well_weights,
278  const WellStateType& well_state) const = 0;
279 
280  void addCellRates(std::map<int, RateVector>& cellRates_) const;
281 
282  Scalar volumetricSurfaceRateForConnection(int cellIdx, int phaseIdx) const;
283 
284  // TODO: theoretically, it should be a const function
285  // Simulator is not const is because that assembleWellEq is non-const Simulator
286  void wellTesting(const Simulator& simulator,
287  const double simulation_time,
288  const GroupStateHelperType& groupStateHelper,
289  WellStateType& well_state,
290  WellTestState& welltest_state,
291  GLiftEclWells& ecl_well_map,
292  std::map<std::string, double>& open_times);
293 
294  void checkWellOperability(const Simulator& simulator,
295  const WellStateType& well_state,
296  const GroupStateHelperType& groupStateHelper);
297 
298  void gliftBeginTimeStepWellTestUpdateALQ(const Simulator& simulator,
299  WellStateType& well_state,
300  const GroupState<Scalar>& group_state,
301  GLiftEclWells& ecl_well_map,
302  DeferredLogger& deferred_logger);
303 
304  // check whether the well is operable under the current reservoir condition
305  // mostly related to BHP limit and THP limit
306  void updateWellOperability(const Simulator& simulator,
307  const WellStateType& well_state,
308  const GroupStateHelperType& groupStateHelper);
309 
310  bool updateWellOperabilityFromWellEq(const Simulator& simulator,
311  const GroupStateHelperType& groupStateHelper);
312 
313  // update perforation water throughput based on solved water rate
314  virtual void updateWaterThroughput(const double dt,
315  WellStateType& well_state) const = 0;
316 
319  virtual std::vector<Scalar>
320  computeCurrentWellRates(const Simulator& simulator,
321  DeferredLogger& deferred_logger) const = 0;
322 
326  void initializeProducerWellState(const Simulator& simulator,
327  WellStateType& well_state,
328  DeferredLogger& deferred_logger) const;
329 
330  void solveWellEquation(const Simulator& simulator,
331  const GroupStateHelperType& groupStateHelper,
332  WellStateType& well_state);
333 
334  const std::vector<RateVector>& connectionRates() const
335  {
336  return connectionRates_;
337  }
338 
339  void updateConnectionDFactor(const Simulator& simulator,
340  SingleWellStateType& ws) const;
341 
342  void updateConnectionTransmissibilityFactor(const Simulator& simulator,
343  SingleWellStateType& ws) const;
344 
345  virtual bool iterateWellEqWithSwitching(const Simulator& simulator,
346  const double dt,
347  const WellInjectionControls& inj_controls,
348  const WellProductionControls& prod_controls,
349  const GroupStateHelperType& groupStateHelper,
350  WellStateType& well_state,
351  const bool fixed_control,
352  const bool fixed_status,
353  const bool solving_with_zero_rate) = 0;
354 
355  virtual Scalar maxPerfPress(const Simulator& simulator) const = 0;
356 
357  virtual void updateIPRImplicit(const Simulator& simulator,
358  const GroupStateHelperType& groupStateHelper,
359  WellStateType& well_state) = 0;
360 
361 protected:
362  // simulation parameters
363  std::vector<RateVector> connectionRates_;
364  std::vector<Scalar> B_avg_;
365  bool changed_to_stopped_this_step_ = false;
366  bool thp_update_iterations = false;
367  int number_of_well_reopenings_{0};
368 
369  Scalar wpolymer() const;
370  Scalar wfoam() const;
371  Scalar wsalt() const;
372  Scalar wmicrobes() const;
373  Scalar woxygen() const;
374  Scalar wurea() const;
375 
376  virtual Scalar getRefDensity() const = 0;
377 
378  std::vector<Scalar>
379  initialWellRateFractions(const Simulator& ebosSimulator,
380  const WellStateType& well_state) const;
381 
382  // check whether the well is operable under BHP limit with current reservoir condition
383  virtual void checkOperabilityUnderBHPLimit(const WellStateType& well_state,
384  const Simulator& simulator,
385  DeferredLogger& deferred_logger) = 0;
386 
387  // check whether the well is operable under THP limit with current reservoir condition
388  virtual void checkOperabilityUnderTHPLimit(const Simulator& simulator,
389  const WellStateType& well_state,
390  const GroupStateHelperType& groupStateHelper) = 0;
391 
392  virtual void updateIPR(const Simulator& simulator,
393  DeferredLogger& deferred_logger) const = 0;
394 
395  virtual void assembleWellEqWithoutIteration(const Simulator& simulator,
396  const GroupStateHelperType& groupStateHelper,
397  const double dt,
398  const WellInjectionControls& inj_controls,
399  const WellProductionControls& prod_controls,
400  WellStateType& well_state,
401  const bool solving_with_zero_rate) = 0;
402 
403  // iterate well equations with the specified control until converged
404  virtual bool iterateWellEqWithControl(const Simulator& simulator,
405  const double dt,
406  const WellInjectionControls& inj_controls,
407  const WellProductionControls& prod_controls,
408  const GroupStateHelperType& groupStateHelper,
409  WellStateType& well_state) = 0;
410 
411  bool iterateWellEquations(const Simulator& simulator,
412  const double dt,
413  const GroupStateHelperType& groupStateHelper,
414  WellStateType& well_state);
415 
416  bool solveWellWithOperabilityCheck(const Simulator& simulator,
417  const double dt,
418  const Well::InjectionControls& inj_controls,
419  const Well::ProductionControls& prod_controls,
420  const GroupStateHelperType& groupStateHelper,
421  WellStateType& well_state);
422 
423  std::optional<Scalar>
424  estimateOperableBhp(const Simulator& ebos_simulator,
425  const double dt,
426  const GroupStateHelperType& groupStateHelper,
427  const SummaryState& summary_state,
428  WellStateType& well_state);
429 
430  bool solveWellWithBhp(const Simulator& simulator,
431  const double dt,
432  const Scalar bhp,
433  const GroupStateHelperType& groupStateHelper,
434  WellStateType& well_state);
435 
436  bool solveWellWithZeroRate(const Simulator& simulator,
437  const double dt,
438  const GroupStateHelperType& groupStateHelper,
439  WellStateType& well_state);
440 
441  bool solveWellForTesting(const Simulator& simulator,
442  const GroupStateHelperType& groupStateHelper,
443  WellStateType& well_state);
444 
445 
446  template<class GasLiftSingleWell>
447  std::unique_ptr<GasLiftSingleWell> initializeGliftWellTest_(const Simulator& simulator,
448  WellStateType& well_state,
449  const GroupState<Scalar>& group_state,
450  GLiftEclWells& ecl_well_map,
451  DeferredLogger& deferred_logger);
452 
453  Eval getPerfCellPressure(const FluidState& fs) const;
454 
455  // get the transmissibility multiplier for specific perforation
456  template<class Value, class Callback>
457  void getTransMult(Value& trans_mult,
458  const Simulator& simulator,
459  const int cell_idx,
460  Callback& extendEval) const;
461 
462  // get the well transmissibility for specific perforation
463  template<class Value>
464  void getTw(std::vector<Value>& wi,
465  const int perf,
466  const IntensiveQuantities& intQuants,
467  const Value& trans_mult,
468  const SingleWellStateType& ws) const;
469 
470  // get the mobility for specific perforation
471  template<class Value, class Callback>
472  void getMobility(const Simulator& simulator,
473  const int local_perf_index,
474  std::vector<Value>& mob,
475  Callback& extendEval,
476  [[maybe_unused]] DeferredLogger& deferred_logger) const;
477 
478  void computeConnLevelProdInd(const FluidState& fs,
479  const std::function<Scalar(const Scalar)>& connPICalc,
480  const std::vector<Scalar>& mobility,
481  Scalar* connPI) const;
482 
483  void computeConnLevelInjInd(const FluidState& fs,
484  const Phase preferred_phase,
485  const std::function<Scalar(const Scalar)>& connIICalc,
486  const std::vector<Scalar>& mobility,
487  Scalar* connII,
488  DeferredLogger& deferred_logger) const;
489 
490  Scalar computeConnectionDFactor(const int perf,
491  const IntensiveQuantities& intQuants,
492  const SingleWellStateType& ws) const;
493 };
494 
495 } // namespace Opm
496 
497 #include "WellInterface_impl.hpp"
498 
499 #endif // OPM_WELLINTERFACE_HEADER_INCLUDED
WellInterface(const Well &well, const ParallelWellInfo< Scalar > &pw_info, const int time_step, const ModelParameters &param, const RateConverterType &rate_converter, const int pvtRegionIdx, const int num_conservation_quantities, const int num_phases, const int index_of_well, const std::vector< PerforationData< Scalar >> &perf_data)
Constructor.
Definition: WellInterface_impl.hpp:59
virtual void recoverWellSolutionAndUpdateWellState(const Simulator &simulator, const BVector &x, const GroupStateHelperType &groupStateHelper, WellStateType &well_state)=0
using the solution x to recover the solution xw for wells and applying xw to update Well State ...
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
virtual std::vector< Scalar > computeCurrentWellRates(const Simulator &simulator, DeferredLogger &deferred_logger) const =0
Compute well rates based on current reservoir conditions and well variables.
Declares the properties required by the black oil model.
virtual ~WellInterface()=default
Virtual destructor.
void initializeProducerWellState(const Simulator &simulator, WellStateType &well_state, DeferredLogger &deferred_logger) const
Modify the well_state&#39;s rates if there is only one nonzero rate.
Definition: WellInterface_impl.hpp:1797
virtual void apply(const BVector &x, BVector &Ax) const =0
Ax = Ax - C D^-1 B x.
Definition: GasLiftSingleWell.hpp:37
Declares the properties required by the black oil model.