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 <limits>
66 #include <vector>
67 
68 namespace Opm
69 {
70 
71 class WellInjectionProperties;
72 class WellProductionProperties;
73 template<typename Scalar, typename IndexTraits> class GroupStateHelper;
74 
75 template<typename TypeTag>
76 class WellInterface : public WellInterfaceIndices<GetPropType<TypeTag, Properties::FluidSystem>,
77  GetPropType<TypeTag, Properties::Indices>>
78 {
79  using Base = WellInterfaceIndices<GetPropType<TypeTag, Properties::FluidSystem>,
80  GetPropType<TypeTag, Properties::Indices>>;
81 public:
82  using Grid = GetPropType<TypeTag, Properties::Grid>;
83  using Simulator = GetPropType<TypeTag, Properties::Simulator>;
84  using Scalar = GetPropType<TypeTag, Properties::Scalar>;
85  using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
86  using IndexTraits = typename FluidSystem::IndexTraitsType;
87  using Indices = GetPropType<TypeTag, Properties::Indices>;
88  using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
89  using MaterialLaw = GetPropType<TypeTag, Properties::MaterialLaw>;
90  using SparseMatrixAdapter = GetPropType<TypeTag, Properties::SparseMatrixAdapter>;
91  using RateVector = GetPropType<TypeTag, Properties::RateVector>;
92  using GasLiftSingleWell = ::Opm::GasLiftSingleWell<TypeTag>;
93  using GLiftEclWells = typename GasLiftGroupInfo<Scalar, IndexTraits>::GLiftEclWells;
94 
95  using VectorBlockType = Dune::FieldVector<Scalar, Indices::numEq>;
96  using MatrixBlockType = Dune::FieldMatrix<Scalar, Indices::numEq, Indices::numEq>;
97  using Eval = typename Base::Eval;
98  using BVector = Dune::BlockVector<VectorBlockType>;
99  using PressureMatrix = Dune::BCRSMatrix<Opm::MatrixBlock<Scalar, 1, 1>>;
100 
101  using WellStateType = WellState<Scalar, IndexTraits>;
102  using SingleWellStateType = SingleWellState<Scalar, IndexTraits>;
103  using GroupStateHelperType = GroupStateHelper<Scalar, IndexTraits>;
104 
105  using RateConverterType =
106  typename WellInterfaceFluidSystem<FluidSystem>::RateConverterType;
107 
108  using WellInterfaceFluidSystem<FluidSystem>::Gas;
109  using WellInterfaceFluidSystem<FluidSystem>::Oil;
110  using WellInterfaceFluidSystem<FluidSystem>::Water;
111 
112  using ModelParameters = typename Base::ModelParameters;
113 
114  static constexpr bool has_solvent = getPropValue<TypeTag, Properties::EnableSolvent>();
115  static constexpr bool has_zFraction = getPropValue<TypeTag, Properties::EnableExtbo>();
116  static constexpr bool has_polymer = getPropValue<TypeTag, Properties::EnablePolymer>();
117  static constexpr EnergyModules energyModuleType = getPropValue<TypeTag, Properties::EnergyModuleType>();
118  static constexpr bool has_energy = energyModuleType == EnergyModules::FullyImplicitThermal;
119 
120  // flag for polymer molecular weight related
121  static constexpr bool has_polymermw = getPropValue<TypeTag, Properties::EnablePolymerMW>();
122  static constexpr bool has_foam = getPropValue<TypeTag, Properties::EnableFoam>();
123  static constexpr bool has_brine = getPropValue<TypeTag, Properties::EnableBrine>();
124  static constexpr bool has_watVapor = getPropValue<TypeTag, Properties::EnableVapwat>();
125  static constexpr bool has_disgas_in_water = getPropValue<TypeTag, Properties::EnableDisgasInWater>();
126  static constexpr bool has_saltPrecip = getPropValue<TypeTag, Properties::EnableSaltPrecipitation>();
127  static constexpr bool has_bioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>();
128  static constexpr bool has_micp = Indices::enableMICP;
129 
130  template<class ValueType>
131  using BlackOilFluidStateType = BlackOilFluidState<ValueType,
132  FluidSystem,
133  energyModuleType != EnergyModules::NoTemperature,
134  energyModuleType == EnergyModules::FullyImplicitThermal,
135  Indices::compositionSwitchIdx != std::numeric_limits<unsigned>::max(),
136  has_watVapor,
137  has_brine,
138  has_saltPrecip,
139  has_disgas_in_water,
140  has_solvent,
141  Indices::numPhases>;
142 
143  // fluid state for the reservoir fluid
144  using FluidState = BlackOilFluidStateType<Eval>;
145 
147  WellInterface(const Well& well,
148  const ParallelWellInfo<Scalar>& pw_info,
149  const int time_step,
150  const ModelParameters& param,
151  const RateConverterType& rate_converter,
152  const int pvtRegionIdx,
153  const int num_conservation_quantities,
154  const int num_phases,
155  const int index_of_well,
156  const std::vector<PerforationData<Scalar>>& perf_data);
157 
159  virtual ~WellInterface() = default;
160 
161  virtual void init(const std::vector<Scalar>& depth_arg,
162  const Scalar gravity_arg,
163  const std::vector<Scalar>& B_avg,
164  const bool changed_to_open_this_step);
165 
166  virtual ConvergenceReport getWellConvergence(const GroupStateHelperType& groupStateHelper,
167  const std::vector<Scalar>& B_avg,
168  const bool relax_tolerance) const = 0;
169 
170  virtual void solveEqAndUpdateWellState(const Simulator& simulator,
171  const GroupStateHelperType& groupStateHelper,
172  WellStateType& well_state) = 0;
173 
174  void assembleWellEq(const Simulator& simulator,
175  const double dt,
176  const GroupStateHelperType& groupStateHelper,
177  WellStateType& well_state);
178 
179  void assembleWellEqWithoutIteration(const Simulator& simulator,
180  const GroupStateHelperType& groupStateHelper,
181  const double dt,
182  WellStateType& well_state,
183  const bool solving_with_zero_rate);
184 
185  // Convenience overload that gets scaled fractions internally
186  void updateGroupTargetFallbackFlag(WellStateType& well_state,
187  DeferredLogger& deferred_logger) const;
188 
189  // TODO: better name or further refactoring the function to make it more clear
190  void prepareWellBeforeAssembling(const Simulator& simulator,
191  const double dt,
192  const GroupStateHelperType& groupStateHelper,
193  WellStateType& well_state);
194 
195  virtual void computeWellRatesWithBhp(const Simulator& ebosSimulator,
196  const Scalar& bhp,
197  std::vector<Scalar>& well_flux,
198  DeferredLogger& deferred_logger) const = 0;
199 
200  virtual std::optional<Scalar>
201  computeBhpAtThpLimitProdWithAlq(const Simulator& ebos_simulator,
202  const GroupStateHelperType& groupStateHelper,
203  const SummaryState& summary_state,
204  const Scalar alq_value,
205  bool iterate_if_no_solution) const = 0;
206 
207  std::optional<Scalar>
208  computeBhpAtThpLimitProdWithAlqUsingIPR(const Simulator& simulator,
209  const WellStateType& well_state,
210  Scalar bhp,
211  const SummaryState& summary_state,
212  const Scalar alq_value);
215  virtual void recoverWellSolutionAndUpdateWellState(const Simulator& simulator,
216  const BVector& x,
217  const GroupStateHelperType& groupStateHelper,
218  WellStateType& well_state) = 0;
219 
221  virtual void apply(const BVector& x, BVector& Ax) const = 0;
222 
224  virtual void apply(BVector& r) const = 0;
225 
226  // TODO: before we decide to put more information under mutable, this function is not const
227  virtual void computeWellPotentials(const Simulator& simulator,
228  const WellStateType& well_state,
229  const GroupStateHelperType& groupStateHelper,
230  std::vector<Scalar>& well_potentials) = 0;
231 
232  virtual void updateWellStateWithTarget(const Simulator& simulator,
233  const GroupStateHelperType& groupStateHelper,
234  WellStateType& well_state) const;
235 
236  virtual void scaleSegmentRatesAndPressure(WellStateType& well_state) const;
237 
238  virtual void computeWellRatesWithBhpIterations(const Simulator& simulator,
239  const Scalar& bhp,
240  const GroupStateHelperType& groupStateHelper,
241  std::vector<Scalar>& well_flux) const = 0;
242 
243  bool wellUnderZeroRateTarget(const GroupStateHelperType& groupStateHelper) const;
244 
245  bool stoppedOrZeroRateTarget(const GroupStateHelperType& groupStateHelper) const;
246 
247  bool updateWellStateWithTHPTargetProd(const Simulator& simulator,
248  WellStateType& well_state,
249  const GroupStateHelperType& groupStateHelper) const;
250 
251  bool wellUnderZeroGroupRateTarget(const GroupStateHelperType& groupStateHelper,
252  const std::optional<bool> group_control = std::nullopt) const;
253 
254  enum class IndividualOrGroup { Individual, Group, Both };
255  bool updateWellControl(const Simulator& simulator,
256  const IndividualOrGroup iog,
257  const GroupStateHelperType& groupStateHelper,
258  WellStateType& well_state) /* const */;
259 
260  bool updateWellControlAndStatusLocalIteration(const Simulator& simulator,
261  const GroupStateHelperType& groupStateHelper,
262  const Well::InjectionControls& inj_controls,
263  const Well::ProductionControls& prod_controls,
264  const Scalar WQTotal,
265  WellStateType& well_state,
266  const bool fixed_control,
267  const bool fixed_status,
268  const bool solving_with_zero_rate);
269 
270  virtual void updatePrimaryVariables(const GroupStateHelperType& groupStateHelper) = 0;
271 
272  virtual void calculateExplicitQuantities(const Simulator& simulator,
273  const GroupStateHelperType& groupStateHelper) = 0; // should be const?
274 
275  virtual void updateProductivityIndex(const Simulator& simulator,
276  const WellProdIndexCalculator<Scalar>& wellPICalc,
277  WellStateType& well_state,
278  DeferredLogger& deferred_logger) const = 0;
279 
280  // Add well contributions to matrix
281  virtual void addWellContributions(SparseMatrixAdapter&) const = 0;
282 
283  virtual void addWellPressureEquations(PressureMatrix& mat,
284  const BVector& x,
285  const int pressureVarIndex,
286  const bool use_well_weights,
287  const WellStateType& well_state) const = 0;
288 
289  void addCellRates(std::map<int, RateVector>& cellRates_) const;
290 
291  Scalar volumetricSurfaceRateForConnection(int cellIdx, int phaseIdx) const;
292 
293  // TODO: theoretically, it should be a const function
294  // Simulator is not const is because that assembleWellEq is non-const Simulator
295  void wellTesting(const Simulator& simulator,
296  const double simulation_time,
297  const GroupStateHelperType& groupStateHelper,
298  WellStateType& well_state,
299  WellTestState& welltest_state,
300  GLiftEclWells& ecl_well_map,
301  std::map<std::string, double>& open_times);
302 
303  void checkWellOperability(const Simulator& simulator,
304  const WellStateType& well_state,
305  const GroupStateHelperType& groupStateHelper);
306 
307  void gliftBeginTimeStepWellTestUpdateALQ(const Simulator& simulator,
308  WellStateType& well_state,
309  const GroupState<Scalar>& group_state,
310  GLiftEclWells& ecl_well_map,
311  DeferredLogger& deferred_logger);
312 
313  // check whether the well is operable under the current reservoir condition
314  // mostly related to BHP limit and THP limit
315  void updateWellOperability(const Simulator& simulator,
316  const WellStateType& well_state,
317  const GroupStateHelperType& groupStateHelper);
318 
319  bool updateWellOperabilityFromWellEq(const Simulator& simulator,
320  const GroupStateHelperType& groupStateHelper);
321 
322  // update perforation water throughput based on solved water rate
323  virtual void updateWaterThroughput(const double dt,
324  WellStateType& well_state) const = 0;
325 
328  virtual std::vector<Scalar>
329  computeCurrentWellRates(const Simulator& simulator,
330  DeferredLogger& deferred_logger) const = 0;
331 
334  virtual void getScaledWellFractions(std::vector<Scalar>& scaled_fractions,
335  DeferredLogger& deferred_logger) const = 0;
336 
340  void initializeProducerWellState(const Simulator& simulator,
341  WellStateType& well_state,
342  DeferredLogger& deferred_logger) const;
343 
344  void solveWellEquation(const Simulator& simulator,
345  const GroupStateHelperType& groupStateHelper,
346  WellStateType& well_state);
347 
348  const std::vector<RateVector>& connectionRates() const
349  {
350  return connectionRates_;
351  }
352 
353  void updateConnectionDFactor(const Simulator& simulator,
354  SingleWellStateType& ws) const;
355 
356  void updateConnectionTransmissibilityFactor(const Simulator& simulator,
357  SingleWellStateType& ws) const;
358 
359  virtual bool iterateWellEqWithSwitching(const Simulator& simulator,
360  const double dt,
361  const WellInjectionControls& inj_controls,
362  const WellProductionControls& prod_controls,
363  const GroupStateHelperType& groupStateHelper,
364  WellStateType& well_state,
365  const bool fixed_control,
366  const bool fixed_status,
367  const bool solving_with_zero_rate) = 0;
368 
369  virtual Scalar maxPerfPress(const Simulator& simulator) const = 0;
370 
371  virtual void updateIPRImplicit(const Simulator& simulator,
372  const GroupStateHelperType& groupStateHelper,
373  WellStateType& well_state) = 0;
374 
375  static constexpr int numResDofs = Indices::numEq;
376  static constexpr int numWellDofs = numResDofs + 1; // NB will fail for for thermal for now
377  using BMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<Scalar, numWellDofs, numResDofs>>;
378  using CMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<Scalar, numResDofs, numWellDofs>>;
379  using DMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<Scalar, numWellDofs, numWellDofs>>;
380  using WVector = Dune::BlockVector<Dune::FieldVector<Scalar, numWellDofs>>;
381 
382  virtual void addBCDMatrix(std::vector<BMatrix>& b_matrices,
383  std::vector<CMatrix>& c_matrices,
384  std::vector<DMatrix>& d_matrices,
385  Opm::SparseTable<int>& wcells) const = 0;
386 
387 protected:
388  // simulation parameters
389  std::vector<RateVector> connectionRates_;
390  std::vector<Scalar> B_avg_;
391  bool changed_to_stopped_this_step_ = false;
392  bool thp_update_iterations = false;
393  int number_of_well_reopenings_{0};
394 
395  Scalar wpolymer() const;
396  Scalar wfoam() const;
397  Scalar wsalt() const;
398  Scalar wmicrobes() const;
399  Scalar woxygen() const;
400  Scalar wurea() const;
401 
402  virtual Scalar getRefDensity() const = 0;
403 
404  std::vector<Scalar>
405  initialWellRateFractions(const Simulator& ebosSimulator,
406  const WellStateType& well_state) const;
407 
408  // check whether the well is operable under BHP limit with current reservoir condition
409  virtual void checkOperabilityUnderBHPLimit(const WellStateType& well_state,
410  const Simulator& simulator,
411  DeferredLogger& deferred_logger) = 0;
412 
413  // check whether the well is operable under THP limit with current reservoir condition
414  virtual void checkOperabilityUnderTHPLimit(const Simulator& simulator,
415  const WellStateType& well_state,
416  const GroupStateHelperType& groupStateHelper) = 0;
417 
418  virtual void updateIPR(const Simulator& simulator,
419  DeferredLogger& deferred_logger) const = 0;
420 
421  virtual void assembleWellEqWithoutIteration(const Simulator& simulator,
422  const GroupStateHelperType& groupStateHelper,
423  const double dt,
424  const WellInjectionControls& inj_controls,
425  const WellProductionControls& prod_controls,
426  WellStateType& well_state,
427  const bool solving_with_zero_rate) = 0;
428 
429  // iterate well equations with the specified control until converged
430  virtual bool iterateWellEqWithControl(const Simulator& simulator,
431  const double dt,
432  const WellInjectionControls& inj_controls,
433  const WellProductionControls& prod_controls,
434  const GroupStateHelperType& groupStateHelper,
435  WellStateType& well_state) = 0;
436 
437  bool iterateWellEquations(const Simulator& simulator,
438  const double dt,
439  const GroupStateHelperType& groupStateHelper,
440  WellStateType& well_state);
441 
442  bool solveWellWithOperabilityCheck(const Simulator& simulator,
443  const double dt,
444  const Well::InjectionControls& inj_controls,
445  const Well::ProductionControls& prod_controls,
446  const GroupStateHelperType& groupStateHelper,
447  WellStateType& well_state);
448 
449  std::optional<Scalar>
450  estimateOperableBhp(const Simulator& ebos_simulator,
451  const double dt,
452  const GroupStateHelperType& groupStateHelper,
453  const SummaryState& summary_state,
454  WellStateType& well_state);
455 
456  bool solveWellWithBhp(const Simulator& simulator,
457  const double dt,
458  const Scalar bhp,
459  const GroupStateHelperType& groupStateHelper,
460  WellStateType& well_state);
461 
462  bool solveWellWithZeroRate(const Simulator& simulator,
463  const double dt,
464  const GroupStateHelperType& groupStateHelper,
465  WellStateType& well_state);
466 
467  bool solveWellForTesting(const Simulator& simulator,
468  const GroupStateHelperType& groupStateHelper,
469  WellStateType& well_state);
470 
471 
472  template<class GasLiftSingleWell>
473  std::unique_ptr<GasLiftSingleWell> initializeGliftWellTest_(const Simulator& simulator,
474  WellStateType& well_state,
475  const GroupState<Scalar>& group_state,
476  GLiftEclWells& ecl_well_map,
477  DeferredLogger& deferred_logger);
478 
479  Eval getPerfCellPressure(const FluidState& fs) const;
480 
481  // get the transmissibility multiplier for specific perforation
482  template<class Value, class Callback>
483  void getTransMult(Value& trans_mult,
484  const Simulator& simulator,
485  const int cell_idx,
486  Callback& extendEval) const;
487 
488  // get the well transmissibility for specific perforation
489  template<class Value>
490  void getTw(std::vector<Value>& wi,
491  const int perf,
492  const IntensiveQuantities& intQuants,
493  const Value& trans_mult,
494  const SingleWellStateType& ws) const;
495 
496  // get the mobility for specific perforation
497  template<class Value, class Callback>
498  void getMobility(const Simulator& simulator,
499  const int local_perf_index,
500  std::vector<Value>& mob,
501  Callback& extendEval,
502  [[maybe_unused]] DeferredLogger& deferred_logger) const;
503 
504  void computeConnLevelProdInd(const FluidState& fs,
505  const std::function<Scalar(const Scalar)>& connPICalc,
506  const std::vector<Scalar>& mobility,
507  Scalar* connPI) const;
508 
509  void computeConnLevelInjInd(const FluidState& fs,
510  const Phase preferred_phase,
511  const std::function<Scalar(const Scalar)>& connIICalc,
512  const std::vector<Scalar>& mobility,
513  Scalar* connII,
514  DeferredLogger& deferred_logger) const;
515 
516  Scalar computeConnectionDFactor(const int perf,
517  const IntensiveQuantities& intQuants,
518  const SingleWellStateType& ws) const;
519 };
520 
521 } // namespace Opm
522 
523 #include "WellInterface_impl.hpp"
524 
525 #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 ...
virtual void getScaledWellFractions(std::vector< Scalar > &scaled_fractions, DeferredLogger &deferred_logger) const =0
Get scaled well fractions from primary variables Implemented by derived classes that have access to p...
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
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:1822
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.