opm-simulators
StandardWell.hpp
1 /*
2  Copyright 2017 SINTEF Digital, Mathematics and Cybernetics.
3  Copyright 2017 Statoil ASA.
4  Copyright 2016 - 2017 IRIS 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 3 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 
22 
23 #ifndef OPM_STANDARDWELL_HEADER_INCLUDED
24 #define OPM_STANDARDWELL_HEADER_INCLUDED
25 
26 #include <opm/simulators/timestepping/ConvergenceReport.hpp>
28 #include <opm/simulators/wells/RatioCalculator.hpp>
29 #include <opm/simulators/wells/VFPInjProperties.hpp>
30 #include <opm/simulators/wells/VFPProdProperties.hpp>
31 #include <opm/simulators/wells/WellInterface.hpp>
32 #include <opm/simulators/wells/WellProdIndexCalculator.hpp>
33 #include <opm/simulators/wells/ParallelWellInfo.hpp>
34 
36 
37 #include <opm/material/densead/Evaluation.hpp>
38 #include <opm/input/eclipse/Schedule/ScheduleTypes.hpp>
39 
40 #include <opm/simulators/wells/StandardWellEval.hpp>
41 
42 #include <dune/common/dynvector.hh>
43 #include <dune/common/dynmatrix.hh>
44 
45 #include <memory>
46 #include <optional>
47 
48 namespace Opm
49 {
50 
51  template<typename TypeTag>
52  class StandardWell : public WellInterface<TypeTag>
53  , public StandardWellEval<GetPropType<TypeTag, Properties::FluidSystem>,
54  GetPropType<TypeTag, Properties::Indices>>
55  {
56 
57  public:
61 
62  // TODO: some functions working with AD variables handles only with values (double) without
63  // dealing with derivatives. It can be beneficial to make functions can work with either AD or scalar value.
64  // And also, it can also be beneficial to make these functions hanle different types of AD variables.
65  using typename Base::Simulator;
66  using typename Base::IntensiveQuantities;
67  using typename Base::FluidSystem;
68  using typename Base::MaterialLaw;
69  using typename Base::ModelParameters;
70  using typename Base::Indices;
71  using typename Base::RateConverterType;
72  using typename Base::SparseMatrixAdapter;
73  using typename Base::FluidState;
74  using typename Base::RateVector;
75  using typename Base::GroupStateHelperType;
76 
77  using Base::has_solvent;
78  using Base::has_zFraction;
79  using Base::has_polymer;
80  using Base::has_polymermw;
81  using Base::has_foam;
82  using Base::has_brine;
83  using Base::has_energy;
84  using Base::has_bioeffects;
85  using Base::has_micp;
86 
88  using PolymerModule = BlackOilPolymerModule<TypeTag, has_polymer>;
89  using typename Base::PressureMatrix;
90 
91  // number of the conservation equations
92  static constexpr int numWellConservationEq = Indices::numPhases + Indices::numSolvents;
93  // number of the well control equations
94  static constexpr int numWellControlEq = 1;
95  // number of the well equations that will always be used
96  // based on the solution strategy, there might be other well equations be introduced
97  static constexpr int numStaticWellEq = numWellConservationEq + numWellControlEq;
98 
99  // the index for Bhp in primary variables and also the index of well control equation
100  // they both will be the last one in their respective system.
101  // TODO: we should have indices for the well equations and well primary variables separately
102  static constexpr int Bhp = numStaticWellEq - numWellControlEq;
103 
104  using StdWellEval::WQTotal;
105 
106  using typename Base::Scalar;
107 
108  using Base::name;
109  using Base::Water;
110  using Base::Oil;
111  using Base::Gas;
112 
113  using typename Base::BVector;
114 
115  using Eval = typename StdWellEval::Eval;
116  using EvalWell = typename StdWellEval::EvalWell;
117  using BVectorWell = typename StdWellEval::BVectorWell;
118 
119  using IndexTraits = typename FluidSystem::IndexTraitsType;
121 
122  StandardWell(const Well& well,
123  const ParallelWellInfo<Scalar>& pw_info,
124  const int time_step,
125  const ModelParameters& param,
126  const RateConverterType& rate_converter,
127  const int pvtRegionIdx,
128  const int num_conservation_quantities,
129  const int num_phases,
130  const int index_of_well,
131  const std::vector<PerforationData<Scalar>>& perf_data);
132 
133  virtual void init(const std::vector<Scalar>& depth_arg,
134  const Scalar gravity_arg,
135  const std::vector<Scalar>& B_avg,
136  const bool changed_to_open_this_step) override;
137 
139  virtual ConvergenceReport getWellConvergence(const GroupStateHelperType& groupStateHelper,
140  const std::vector<Scalar>& B_avg,
141  const bool relax_tolerance) const override;
142 
144  virtual void apply(const BVector& x, BVector& Ax) const override;
146  virtual void apply(BVector& r) const override;
147 
150  void recoverWellSolutionAndUpdateWellState(const Simulator& simulator,
151  const BVector& x,
152  const GroupStateHelperType& groupStateHelper,
153  WellStateType& well_state) override;
154 
156  void computeWellPotentials(const Simulator& simulator,
157  const WellStateType& well_state,
158  const GroupStateHelperType& groupStateHelper,
159  std::vector<Scalar>& well_potentials) /* const */ override;
160 
161  void updatePrimaryVariables(const GroupStateHelperType& groupStateHelper) override;
162 
163  void solveEqAndUpdateWellState(const Simulator& simulator,
164  const GroupStateHelperType& groupStateHelper,
165  WellStateType& well_state) override;
166 
167  void calculateExplicitQuantities(const Simulator& simulator,
168  const GroupStateHelperType& groupStateHelper) override; // should be const?
169 
170  void updateProductivityIndex(const Simulator& simulator,
171  const WellProdIndexCalculator<Scalar>& wellPICalc,
172  WellStateType& well_state,
173  DeferredLogger& deferred_logger) const override;
174 
175  Scalar connectionDensity(const int globalConnIdx,
176  const int openConnIdx) const override;
177 
178  void addWellContributions(SparseMatrixAdapter& mat) const override;
179 
180  void addWellPressureEquations(PressureMatrix& mat,
181  const BVector& x,
182  const int pressureVarIndex,
183  const bool use_well_weights,
184  const WellStateType& well_state) const override;
185 
186  // iterate well equations with the specified control until converged
187  bool iterateWellEqWithControl(const Simulator& simulator,
188  const double dt,
189  const Well::InjectionControls& inj_controls,
190  const Well::ProductionControls& prod_controls,
191  const GroupStateHelperType& groupStateHelper,
192  WellStateType& well_state) override;
193 
194  // iterate well equations including control switching
195  bool iterateWellEqWithSwitching(const Simulator& simulator,
196  const double dt,
197  const Well::InjectionControls& inj_controls,
198  const Well::ProductionControls& prod_controls,
199  const GroupStateHelperType& groupStateHelper,
200  WellStateType& well_state,
201  const bool fixed_control,
202  const bool fixed_status,
203  const bool solving_with_zero_rate) override;
204 
205  /* returns BHP */
206  Scalar computeWellRatesAndBhpWithThpAlqProd(const Simulator& ebos_simulator,
207  const GroupStateHelperType& groupStateHelper,
208  const SummaryState &summary_state,
209  std::vector<Scalar>& potentials,
210  Scalar alq) const;
211 
212  void computeWellRatesWithThpAlqProd(const Simulator& ebos_simulator,
213  const GroupStateHelperType& groupStateHelper,
214  const SummaryState& summary_state,
215  std::vector<Scalar>& potentials,
216  Scalar alq) const;
217 
218  std::optional<Scalar>
219  computeBhpAtThpLimitProdWithAlq(const Simulator& ebos_simulator,
220  const GroupStateHelperType& groupStateHelper,
221  const SummaryState& summary_state,
222  const Scalar alq_value,
223  bool iterate_if_no_solution) const override;
224 
225  void updateIPRImplicit(const Simulator& simulator,
226  const GroupStateHelperType& groupStateHelper,
227  WellStateType& well_state) override;
228 
229  void computeWellRatesWithBhp(const Simulator& ebosSimulator,
230  const Scalar& bhp,
231  std::vector<Scalar>& well_flux,
232  DeferredLogger& deferred_logger) const override;
233 
234  Scalar maxPerfPress(const Simulator& simulator) const override;
235 
236  // NOTE: These cannot be protected since they are used by GasLiftRuntime
237  using Base::vfp_properties_;
238 
239  std::vector<Scalar>
240  computeCurrentWellRates(const Simulator& ebosSimulator,
241  DeferredLogger& deferred_logger) const override;
242 
243  std::vector<Scalar> getPrimaryVars() const override;
244 
245  int setPrimaryVars(typename std::vector<Scalar>::const_iterator it) override;
246 
247  void getScaledWellFractions(std::vector<Scalar>& scaled_fractions,
248  DeferredLogger& deferred_logger) const override;
249 
250 
251  void addBCDMatrix(std::vector<typename Base::BMatrix>& b_matrices,
252  std::vector<typename Base::CMatrix>& c_matrices,
253  std::vector<typename Base::DMatrix>& d_matrices,
254  Opm::SparseTable<int>& wcells) const override
255  {
256  // System_cpr preconditioner is only supported when well DOF dimensions
257  // match between WellInterface and StandardWellEval (standard 3-phase blackoil).
258  if constexpr (Base::numWellDofs == StdWellEval::numWellDofs) {
259  StdWellEval::addBCDMatrix(b_matrices, c_matrices, d_matrices, wcells);
260  } else {
261  OPM_THROW(std::runtime_error,
262  "system_cpr preconditioner with standard wells is only supported for standard "
263  "3-phase blackoil (Indices::numEq == 3). This model has different equation count.");
264  }
265  }
266 
267  protected:
268  bool regularize_;
269 
270  // updating the well_state based on well solution dwells
271  void updateWellState(const Simulator& simulator,
272  const BVectorWell& dwells,
273  const GroupStateHelperType& groupStateHelper,
274  WellStateType& well_state);
275 
276  using WellConnectionProps = typename StdWellEval::StdWellConnections::Properties;
277 
278  // Compute connection level PVT properties needed to calulate the
279  // pressure difference between well connections.
280  WellConnectionProps
281  computePropertiesForWellConnectionPressures(const Simulator& simulator,
282  const WellStateType& well_state) const;
283 
284  void computeWellConnectionDensitesPressures(const Simulator& simulator,
285  const GroupStateHelperType& groupStateHelper,
286  const WellConnectionProps& props);
287 
288  void computeWellConnectionPressures(const Simulator& simulator,
289  const GroupStateHelperType& groupStateHelper);
290 
291  template<class Value>
292  void computePerfRate(const IntensiveQuantities& intQuants,
293  const std::vector<Value>& mob,
294  const Value& bhp,
295  const std::vector<Value>& Tw,
296  const int perf,
297  const bool allow_cf,
298  std::vector<Value>& cq_s,
299  PerforationRates<Scalar>& perf_rates,
300  DeferredLogger& deferred_logger) const;
301 
302  template<class Value>
303  void computePerfRate(const std::vector<Value>& mob,
304  const Value& pressure,
305  const Value& bhp,
306  const Value& rs,
307  const Value& rv,
308  const Value& rvw,
309  const Value& rsw,
310  std::vector<Value>& b_perfcells_dense,
311  const std::vector<Value>& Tw,
312  const int perf,
313  const bool allow_cf,
314  const Value& skin_pressure,
315  const std::vector<Value>& cmix_s,
316  std::vector<Value>& cq_s,
317  PerforationRates<Scalar>& perf_rates,
318  DeferredLogger& deferred_logger) const;
319 
320  void computeWellRatesWithBhpIterations(const Simulator& ebosSimulator,
321  const Scalar& bhp,
322  const GroupStateHelperType& groupStateHelper,
323  std::vector<Scalar>& well_flux) const override;
324 
325  std::vector<Scalar>
326  computeWellPotentialWithTHP(const Simulator& ebosSimulator,
327  const GroupStateHelperType& groupStateHelper,
328  const WellStateType& well_state) const;
329 
330  bool computeWellPotentialsImplicit(const Simulator& ebos_simulator,
331  const GroupStateHelperType& groupStateHelper,
332  std::vector<Scalar>& well_potentials) const;
333 
334  // return the density at the perforation[0] of the rank owning this well,
335  // value is cached to minimize the number of broadcasts
336  Scalar getRefDensity() const override;
337 
338  // get the transmissibility multiplier for specific perforation
339  template<class Value>
340  void getTransMult(Value& trans_mult,
341  const Simulator& simulator,
342  const int cell_indx) const;
343 
344  // get the mobility for specific perforation
345  template<class Value>
346  void getMobility(const Simulator& simulator,
347  const int perf,
348  std::vector<Value>& mob,
349  DeferredLogger& deferred_logger) const;
350 
351  void updateWaterMobilityWithPolymer(const Simulator& simulator,
352  const int perf,
353  std::vector<EvalWell>& mob_water,
354  DeferredLogger& deferred_logger) const;
355 
356  void updatePrimaryVariablesNewton(const BVectorWell& dwells,
357  const bool stop_or_zero_rate_target,
358  DeferredLogger& deferred_logger);
359 
360  void updateWellStateFromPrimaryVariables(WellStateType& well_state,
361  const SummaryState& summary_state,
362  DeferredLogger& deferred_logger) const;
363 
364  void assembleWellEqWithoutIteration(const Simulator& simulator,
365  const GroupStateHelperType& groupStateHelper,
366  const double dt,
367  const Well::InjectionControls& inj_controls,
368  const Well::ProductionControls& prod_controls,
369  WellStateType& well_state,
370  const bool solving_with_zero_rate) override;
371 
372  void assembleWellEqWithoutIterationImpl(const Simulator& simulator,
373  const GroupStateHelperType& groupStateHelper,
374  const double dt,
375  const Well::InjectionControls& inj_controls,
376  const Well::ProductionControls& prod_controls,
377  WellStateType& well_state,
378  const bool solving_with_zero_rate);
379 
380  void calculateSinglePerf(const Simulator& simulator,
381  const int perf,
382  WellStateType& well_state,
383  std::vector<RateVector>& connectionRates,
384  std::vector<EvalWell>& cq_s,
385  EvalWell& water_flux_s,
386  EvalWell& cq_s_zfrac_effective,
387  DeferredLogger& deferred_logger) const;
388 
389  // check whether the well is operable under BHP limit with current reservoir condition
390  void checkOperabilityUnderBHPLimit(const WellStateType& well_state,
391  const Simulator& simulator,
392  DeferredLogger& deferred_logger) override;
393 
394  // check whether the well is operable under THP limit with current reservoir condition
395  void checkOperabilityUnderTHPLimit(const Simulator& simulator,
396  const WellStateType& well_state,
397  const GroupStateHelperType& groupStateHelper) override;
398 
399  // updating the inflow based on the current reservoir condition
400  void updateIPR(const Simulator& simulator,
401  DeferredLogger& deferred_logger) const override;
402 
403  // for a well, when all drawdown are in the wrong direction, then this well will not
404  // be able to produce/inject .
405  bool allDrawDownWrongDirection(const Simulator& simulator) const;
406 
407  // turn on crossflow to avoid singular well equations
408  // when the well is banned from cross-flow and the BHP is not properly initialized,
409  // we turn on crossflow to avoid singular well equations. It can result in wrong-signed
410  // well rates, it can cause problem for THP calculation
411  // TODO: looking for better alternative to avoid wrong-signed well rates
412  bool openCrossFlowAvoidSingularity(const Simulator& simulator) const;
413 
414  // calculate the skin pressure based on water velocity, throughput and polymer concentration.
415  // throughput is used to describe the formation damage during water/polymer injection.
416  // calculated skin pressure will be applied to the drawdown during perforation rate calculation
417  // to handle the effect from formation damage.
418  EvalWell pskin(const Scalar throughput,
419  const EvalWell& water_velocity,
420  const EvalWell& poly_inj_conc,
421  DeferredLogger& deferred_logger) const;
422 
423  // calculate the skin pressure based on water velocity, throughput during water injection.
424  EvalWell pskinwater(const Scalar throughput,
425  const EvalWell& water_velocity,
426  DeferredLogger& deferred_logger) const;
427 
428  // calculate the injecting polymer molecular weight based on the througput and water velocity
429  EvalWell wpolymermw(const Scalar throughput,
430  const EvalWell& water_velocity,
431  DeferredLogger& deferred_logger) const;
432 
433  // modify the water rate for polymer injectivity study
434  void handleInjectivityRate(const Simulator& simulator,
435  const int perf,
436  std::vector<EvalWell>& cq_s) const;
437 
438  // handle the extra equations for polymer injectivity study
439  void handleInjectivityEquations(const Simulator& simulator,
440  const WellStateType& well_state,
441  const int perf,
442  const EvalWell& water_flux_s,
443  DeferredLogger& deferred_logger);
444 
445  void updateWaterThroughput(const double dt,
446  WellStateType& well_state) const override;
447 
448  // checking convergence of extra equations, if there are any
449  void checkConvergenceExtraEqs(const std::vector<Scalar>& res,
450  ConvergenceReport& report) const;
451 
452  // updating the connectionRates_ related polymer molecular weight
453  void updateConnectionRatePolyMW(const EvalWell& cq_s_poly,
454  const IntensiveQuantities& int_quants,
455  const WellStateType& well_state,
456  const int perf,
457  std::vector<RateVector>& connectionRates,
458  DeferredLogger& deferred_logger) const;
459 
460  std::optional<Scalar>
461  computeBhpAtThpLimitProd(const WellStateType& well_state,
462  const Simulator& simulator,
463  const GroupStateHelperType& groupStateHelper,
464  const SummaryState& summary_state) const;
465 
466  std::optional<Scalar>
467  computeBhpAtThpLimitInj(const Simulator& simulator,
468  const GroupStateHelperType& groupStateHelper,
469  const SummaryState& summary_state) const;
470 
471  private:
472  Eval connectionRateEnergy(const std::vector<EvalWell>& cq_s,
473  const IntensiveQuantities& intQuants,
474  DeferredLogger& deferred_logger) const;
475 
476  // density of the first perforation, might not be from this rank
477  Scalar cachedRefDensity{0};
478  };
479 
480 }
481 
482 #include "StandardWell_impl.hpp"
483 
484 #endif // OPM_STANDARDWELL_HEADER_INCLUDED
Definition: StandardWellEval.hpp:47
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
Definition: blackoilfoammodules.hh:57
virtual ConvergenceReport getWellConvergence(const GroupStateHelperType &groupStateHelper, const std::vector< Scalar > &B_avg, const bool relax_tolerance) const override
check whether the well equations get converged for this well
Definition: StandardWell_impl.hpp:1230
Definition: StandardWell.hpp:52
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
Definition: BlackoilWellModelConstraints.hpp:37
Facility for converting component rates at surface conditions to phase (voidage) rates at reservoir c...
void recoverWellSolutionAndUpdateWellState(const Simulator &simulator, const BVector &x, const GroupStateHelperType &groupStateHelper, WellStateType &well_state) override
using the solution x to recover the solution xw for wells and applying xw to update Well State ...
Definition: StandardWell_impl.hpp:1489
Contains classes extending the black-oil model.
Definition: BlackoilWellModelGasLift.hpp:38
Definition: PerforationData.hpp:55
std::vector< Scalar > computeCurrentWellRates(const Simulator &ebosSimulator, DeferredLogger &deferred_logger) const override
Compute well rates based on current reservoir conditions and well variables.
Definition: StandardWell_impl.hpp:2590
Class encapsulating some information about parallel wells.
Definition: MSWellHelpers.hpp:34
Definition: DeferredLogger.hpp:56
Collect per-connection static information to enable calculating connection-level or well-level produc...
Definition: WellProdIndexCalculator.hpp:36
void getScaledWellFractions(std::vector< Scalar > &scaled_fractions, DeferredLogger &deferred_logger) const override
Get scaled well fractions from primary variables Implemented by derived classes that have access to p...
Definition: StandardWell_impl.hpp:2658
Static data associated with a well perforation.
Definition: BlackoilWellModelRestart.hpp:41
Represents the convergence status of the whole simulator, to make it possible to query and store the ...
Definition: ConvergenceReport.hpp:37
virtual void apply(const BVector &x, BVector &Ax) const override
Ax = Ax - C D^-1 B x.
Definition: StandardWell_impl.hpp:1457
void computeWellPotentials(const Simulator &simulator, const WellStateType &well_state, const GroupStateHelperType &groupStateHelper, std::vector< Scalar > &well_potentials) override
computing the well potentials for group control
Definition: StandardWell_impl.hpp:1800
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition: TemperatureModel.hpp:65