My Project
Loading...
Searching...
No Matches
BlackoilWellModel.hpp
1/*
2 Copyright 2016 SINTEF ICT, Applied Mathematics.
3 Copyright 2016 - 2017 Statoil ASA.
4 Copyright 2017 Dr. Blatt - HPC-Simulation-Software & Services
5 Copyright 2016 - 2018 IRIS AS
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
24#ifndef OPM_BLACKOILWELLMODEL_HEADER_INCLUDED
25#define OPM_BLACKOILWELLMODEL_HEADER_INCLUDED
26
27#include <dune/common/fmatrix.hh>
28#include <dune/istl/bcrsmatrix.hh>
29#include <dune/istl/matrixmatrix.hh>
30
31#include <opm/common/OpmLog/OpmLog.hpp>
32
33#include <opm/input/eclipse/Schedule/Group/Group.hpp>
34#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
35#include <opm/input/eclipse/Schedule/Schedule.hpp>
36#include <opm/input/eclipse/Schedule/Well/WellTestState.hpp>
37
38#include <opm/material/densead/Math.hpp>
39
40#include <opm/simulators/flow/countGlobalCells.hpp>
42
43#include <opm/simulators/linalg/matrixblock.hh>
44
45#include <opm/simulators/timestepping/SimulatorReport.hpp>
46#include <opm/simulators/timestepping/gatherConvergenceReport.hpp>
47
48#include <opm/simulators/utils/DeferredLogger.hpp>
49
50#include <opm/simulators/wells/BlackoilWellModelGasLift.hpp>
51#include <opm/simulators/wells/BlackoilWellModelGeneric.hpp>
52#include <opm/simulators/wells/BlackoilWellModelGuideRates.hpp>
53#include <opm/simulators/wells/GasLiftGroupInfo.hpp>
54#include <opm/simulators/wells/GasLiftSingleWell.hpp>
55#include <opm/simulators/wells/GasLiftSingleWellGeneric.hpp>
56#include <opm/simulators/wells/GasLiftWellState.hpp>
57#include <opm/simulators/wells/MultisegmentWell.hpp>
58#include <opm/simulators/wells/ParallelWBPCalculation.hpp>
59#include <opm/simulators/wells/ParallelWellInfo.hpp>
60#include <opm/simulators/wells/PerforationData.hpp>
63#include <opm/simulators/wells/StandardWell.hpp>
64#include <opm/simulators/wells/VFPInjProperties.hpp>
65#include <opm/simulators/wells/VFPProdProperties.hpp>
66#include <opm/simulators/wells/WellConnectionAuxiliaryModule.hpp>
67#include <opm/simulators/wells/WellGroupHelpers.hpp>
68#include <opm/simulators/wells/WellInterface.hpp>
69#include <opm/simulators/wells/WellProdIndexCalculator.hpp>
70#include <opm/simulators/wells/WellState.hpp>
71#include <opm/simulators/wells/WGState.hpp>
72
73#include <cstddef>
74#include <map>
75#include <memory>
76#include <string>
77#include <tuple>
78#include <vector>
79
80namespace Opm {
81
82template<class Scalar> class BlackoilWellModelNldd;
83template<class T> class SparseTable;
84
85#if COMPILE_GPU_BRIDGE
86template<class Scalar> class WellContributions;
87#endif
88
90 template<typename TypeTag>
91 class BlackoilWellModel : public WellConnectionAuxiliaryModule<TypeTag, BlackoilWellModel<TypeTag>>
92 , public BlackoilWellModelGeneric<GetPropType<TypeTag,
93 Properties::Scalar>>
94 {
95 public:
96 // --------- Types ---------
108
110
111 constexpr static std::size_t pressureVarIndex = GetPropType<TypeTag, Properties::Indices>::pressureSwitchIdx;
112
113 static const int numEq = Indices::numEq;
114 static const int solventSaturationIdx = Indices::solventSaturationIdx;
115 static constexpr bool has_solvent_ = getPropValue<TypeTag, Properties::EnableSolvent>();
116 static constexpr bool has_polymer_ = getPropValue<TypeTag, Properties::EnablePolymer>();
117 static constexpr bool has_energy_ = getPropValue<TypeTag, Properties::EnableEnergy>();
118 static constexpr bool has_micp_ = getPropValue<TypeTag, Properties::EnableMICP>();
119
120 // TODO: where we should put these types, WellInterface or Well Model?
121 // or there is some other strategy, like TypeTag
122 using VectorBlockType = Dune::FieldVector<Scalar, numEq>;
123 using BVector = Dune::BlockVector<VectorBlockType>;
124
127
128 // For the conversion between the surface volume rate and reservoir voidage rate
129 using RateConverterType = RateConverter::
130 SurfaceToReservoirVoidage<FluidSystem, std::vector<int> >;
131
132 // For computing average pressured used by gpmaint
133 using AverageRegionalPressureType = RegionAverageCalculator::
134 AverageRegionalPressure<FluidSystem, std::vector<int> >;
135
136 explicit BlackoilWellModel(Simulator& simulator);
137
138 void init();
139 void initWellContainer(const int reportStepIdx) override;
140
141 void beginEpisode()
142 {
144 beginReportStep(simulator_.episodeIndex());
145 }
146
147 void beginTimeStep();
148
149 void beginIteration()
150 {
151 OPM_TIMEBLOCK(beginIteration);
152 assemble(simulator_.model().newtonMethod().numIterations(),
153 simulator_.timeStepSize());
154 }
155
156 void endIteration()
157 { }
158
159 void endTimeStep()
160 {
161 OPM_TIMEBLOCK(endTimeStep);
162 timeStepSucceeded(simulator_.time(), simulator_.timeStepSize());
163 }
164
165 void endEpisode()
166 {
167 endReportStep();
168 }
169
170 void computeTotalRatesForDof(RateVector& rate,
171 unsigned globalIdx) const;
172
173 template <class Context>
174 void computeTotalRatesForDof(RateVector& rate,
175 const Context& context,
176 unsigned spaceIdx,
177 unsigned timeIdx) const;
178
179
180 using WellInterfacePtr = std::shared_ptr<WellInterface<TypeTag> >;
181
182 using BlackoilWellModelGeneric<Scalar>::initFromRestartFile;
183 void initFromRestartFile(const RestartValue& restartValues)
184 {
185 initFromRestartFile(restartValues,
186 this->simulator_.vanguard().transferWTestState(),
187 grid().size(0),
189 }
190
191 using BlackoilWellModelGeneric<Scalar>::prepareDeserialize;
192 void prepareDeserialize(const int report_step)
193 {
194 prepareDeserialize(report_step, grid().size(0),
196 }
197
198 data::Wells wellData() const
199 {
200 auto wsrpt = this->wellState()
201 .report(simulator_.vanguard().globalCell().data(),
202 [this](const int well_index) -> bool
203 {
204 return this->wasDynamicallyShutThisTimeStep(well_index);
205 });
206
207 {
208 const auto& tracerRates = this->simulator_.problem()
209 .tracerModel().getWellTracerRates();
210 const auto& freeTracerRates = simulator_.problem()
211 .tracerModel().getWellFreeTracerRates();
212 const auto& solTracerRates = simulator_.problem()
213 .tracerModel().getWellSolTracerRates();
214 const auto& mswTracerRates = simulator_.problem()
215 .tracerModel().getMswTracerRates();
216
217 this->assignWellTracerRates(wsrpt, tracerRates, this->reportStepIndex());
218 this->assignWellTracerRates(wsrpt, freeTracerRates, this->reportStepIndex());
219 this->assignWellTracerRates(wsrpt, solTracerRates, this->reportStepIndex());
220 this->assignMswTracerRates(wsrpt, mswTracerRates, this->reportStepIndex());
221 }
222
224 .assignWellGuideRates(wsrpt, this->reportStepIndex());
225
226 this->assignWellTargets(wsrpt);
227 this->assignShutConnections(wsrpt, this->reportStepIndex());
228 // only used to compute gas injection mass rates for CO2STORE runs
229 // The gas reference density is thus the same for all pvt regions
230 // We therefore for simplicity use 0 here
231 if (eclState().runspec().co2Storage()) {
232 this->assignMassGasRate(wsrpt, FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, 0));
233 }
234 return wsrpt;
235 }
236
237 data::WellBlockAveragePressures wellBlockAveragePressures() const
238 {
239 return this->wbp_.computeWellBlockAveragePressures(this->gravity_);
240 }
241
242#if COMPILE_GPU_BRIDGE
243 // accumulate the contributions of all Wells in the WellContributions object
245#endif
246
247 // Check if well equations is converged.
248 ConvergenceReport getWellConvergence(const std::vector<Scalar>& B_avg, const bool checkWellGroupControls = false) const;
249
250 const SimulatorReportSingle& lastReport() const;
251
252 void addWellContributions(SparseMatrixAdapter& jacobian) const;
253
254 // add source from wells to the reservoir matrix
255 void addReservoirSourceTerms(GlobalEqVector& residual,
256 const std::vector<typename SparseMatrixAdapter::MatrixBlock*>& diagMatAddress) const;
257
258 // called at the beginning of a report step
259 void beginReportStep(const int time_step);
260
261 // it should be able to go to prepareTimeStep(), however, the updateWellControls()
262 // makes it a little more difficult. unless we introduce if (iterationIdx != 0) to avoid doing the above function
263 // twice at the beginning of the time step
267 // some preparation work, mostly related to group control and RESV,
268 // at the beginning of each time step (Not report step)
269 void prepareTimeStep(DeferredLogger& deferred_logger);
270
271 std::tuple<bool, bool, Scalar>
272 updateWellControls(const bool mandatory_network_balance, DeferredLogger& deferred_logger, const bool relax_network_tolerance = false);
273
274 void updateAndCommunicate(const int reportStepIdx,
275 const int iterationIdx,
277
278 bool updateGroupControls(const Group& group,
280 const int reportStepIdx,
281 const int iterationIdx);
282
283 WellInterfacePtr getWell(const std::string& well_name) const;
284
285 using PressureMatrix = Dune::BCRSMatrix<Opm::MatrixBlock<Scalar, 1, 1>>;
286
287 void addWellPressureEquations(PressureMatrix& jacobian,
288 const BVector& weights,
289 const bool use_well_weights) const;
290 void addWellPressureEquationsStruct(PressureMatrix& jacobian) const;
291 void addWellPressureEquationsDomain(PressureMatrix& jacobian,
292 const BVector& weights,
293 const bool use_well_weights,
294 const int domainIndex) const
295 {
296 if (!nldd_) {
297 OPM_THROW(std::logic_error, "Attempt to access NLDD data without a NLDD solver");
298 }
299 return nldd_->addWellPressureEquations(jacobian,
300 weights,
303 }
304
306 const std::vector<WellInterfacePtr>& localNonshutWells() const
307 {
308 return well_container_;
309 }
310
311 const SparseTable<int>& well_local_cells() const
312 {
313 if (!nldd_) {
314 OPM_THROW(std::logic_error, "Attempt to access NLDD data without a NLDD solver");
315 }
316 return nldd_->well_local_cells();
317 }
318
319 const std::map<std::string, int>& well_domain() const
320 {
321 if (!nldd_) {
322 OPM_THROW(std::logic_error, "Attempt to access NLDD data without a NLDD solver");
323 }
324
325 return nldd_->well_domain();
326 }
327
328 auto begin() const { return well_container_.begin(); }
329 auto end() const { return well_container_.end(); }
330 bool empty() const { return well_container_.empty(); }
331
332 bool addMatrixContributions() const
333 { return param_.matrix_add_well_contributions_; }
334
335 int numStrictIterations() const
336 { return param_.strict_outer_iter_wells_; }
337
339 {
340 return simulator_.vanguard().compressedIndexForInterior(cartesian_cell_idx);
341 }
342
343 // using the solution x to recover the solution xw for wells and applying
344 // xw to update Well State
345 void recoverWellSolutionAndUpdateWellState(const BVector& x);
346
347 // using the solution x to recover the solution xw for wells and applying
348 // xw to update Well State
349 void recoverWellSolutionAndUpdateWellStateDomain(const BVector& x,
350 const int domainIdx);
351
352 const Grid& grid() const
353 { return simulator_.vanguard().grid(); }
354
355 const Simulator& simulator() const
356 { return simulator_; }
357
358 void setNlddAdapter(BlackoilWellModelNldd<TypeTag>* mod)
359 { nldd_ = mod; }
360
361 protected:
362 Simulator& simulator_;
363
364 // a vector of all the wells.
365 std::vector<WellInterfacePtr> well_container_{};
366
367 std::vector<bool> is_cell_perforated_{};
368
369 void initializeWellState(const int timeStepIdx);
370
371 // create the well container
372 void createWellContainer(const int report_step) override;
373
374 WellInterfacePtr
375 createWellPointer(const int wellID,
376 const int report_step) const;
377
378 template <typename WellType>
379 std::unique_ptr<WellType>
380 createTypedWellPointer(const int wellID,
381 const int time_step) const;
382
383 WellInterfacePtr createWellForWellTest(const std::string& well_name,
384 const int report_step,
385 DeferredLogger& deferred_logger) const;
386
387 const ModelParameters param_;
388 std::size_t global_num_cells_{};
389 // the number of the cells in the local grid
390 std::size_t local_num_cells_{};
391 Scalar gravity_{};
392 std::vector<Scalar> depth_{};
393 bool alternative_well_rate_init_{};
394 std::map<std::string, Scalar> well_group_thp_calc_;
395 std::unique_ptr<RateConverterType> rateConverter_{};
396 std::map<std::string, std::unique_ptr<AverageRegionalPressureType>> regionalAveragePressureCalculator_{};
397
398 SimulatorReportSingle last_report_{};
399
400 // Pre-step network solve at static reservoir conditions (group and well states might be updated)
401 void doPreStepNetworkRebalance(DeferredLogger& deferred_logger);
402
403 std::vector<Scalar> B_avg_{};
404
405 const EquilGrid& equilGrid() const
406 { return simulator_.vanguard().equilGrid(); }
407
408 const EclipseState& eclState() const
409 { return simulator_.vanguard().eclState(); }
410
411 // compute the well fluxes and assemble them in to the reservoir equations as source terms
412 // and in the well equations.
413 void assemble(const int iterationIdx,
414 const double dt);
415
416 // well controls and network pressures affect each other and are solved in an iterative manner.
417 // the function handles one iteration of updating well controls and network pressures.
418 // it is possible to decouple the update of well controls and network pressures further.
419 // the returned two booleans are {continue_due_to_network, well_group_control_changed}, respectively
420 std::tuple<bool, bool, Scalar> updateWellControlsAndNetworkIteration(const bool mandatory_network_balance,
421 const bool relax_network_tolerance,
422 const bool optimize_gas_lift,
423 const double dt,
424 DeferredLogger& local_deferredLogger);
425
426 bool updateWellControlsAndNetwork(const bool mandatory_network_balance,
427 const double dt,
428 DeferredLogger& local_deferredLogger);
429
430 bool computeWellGroupThp(const double dt, DeferredLogger& local_deferredLogger);
431
441 const bool enableWellPIScaling);
442
447
448 // called at the end of a time step
449 void timeStepSucceeded(const double simulationTime, const double dt);
450
451 // called at the end of a report step
452 void endReportStep();
453
454 // setting the well_solutions_ based on well_state.
455 void updatePrimaryVariables(DeferredLogger& deferred_logger);
456
457 void updateAverageFormationFactor();
458
459 void computePotentials(const std::size_t widx,
461 std::string& exc_msg,
462 ExceptionType::ExcEnum& exc_type,
463 DeferredLogger& deferred_logger) override;
464
465 const std::vector<Scalar>& wellPerfEfficiencyFactors() const;
466
467 void calculateProductivityIndexValuesShutWells(const int reportStepIdx, DeferredLogger& deferred_logger) override;
468 void calculateProductivityIndexValues(DeferredLogger& deferred_logger) override;
469 void calculateProductivityIndexValues(const WellInterface<TypeTag>* wellPtr,
470 DeferredLogger& deferred_logger);
471
472 // The number of components in the model.
473 int numComponents() const;
474
475 int reportStepIndex() const;
476
477 void assembleWellEq(const double dt, DeferredLogger& deferred_logger);
478
479 void prepareWellsBeforeAssembling(const double dt, DeferredLogger& deferred_logger);
480
481 // TODO: finding a better naming
482 void assembleWellEqWithoutIteration(const double dt, DeferredLogger& deferred_logger);
483
484 void extractLegacyCellPvtRegionIndex_();
485
486 void extractLegacyDepth_();
487
489 void updateWellTestState(const double& simulationTime, WellTestState& wellTestState) const;
490
491 void wellTesting(const int timeStepIdx, const double simulationTime, DeferredLogger& deferred_logger);
492
493 void calcResvCoeff(const int fipnum,
494 const int pvtreg,
495 const std::vector<Scalar>& production_rates,
496 std::vector<Scalar>& resv_coeff) override;
497
498 void calcInjResvCoeff(const int fipnum,
499 const int pvtreg,
500 std::vector<Scalar>& resv_coeff) override;
501
502 void computeWellTemperature();
503
504 private:
505 BlackoilWellModel(Simulator& simulator, const PhaseUsage& pu);
506
508 BlackoilWellModelNldd<TypeTag>* nldd_ = nullptr;
509
510 // These members are used to avoid reallocation in specific functions
511 // instead of using local variables.
512 // Their state is not relevant between function calls, so they can
513 // (and must) be mutable, as the functions using them are const.
514 mutable BVector x_local_;
515 };
516
517
518} // namespace Opm
519
520#include "BlackoilWellModel_impl.hpp"
521
522#endif
Helper class for grid instantiation of ECL file-format using problems.
Facility for converting component rates at surface conditions to phase (voidage) rates at reservoir c...
Facility for converting component rates at surface conditions to phase (voidage) rates at reservoir c...
Contains the high level supplements required to extend the black oil model by MICP.
Definition blackoilmicpmodules.hh:49
Contains the high level supplements required to extend the black oil model by polymer.
Definition blackoilpolymermodules.hh:54
Class for handling the blackoil well model.
Definition BlackoilWellModelGeneric.hpp:92
Class for handling the guide rates in the blackoil well model.
Definition BlackoilWellModelGuideRates.hpp:46
void assignWellGuideRates(data::Wells &wsrpt, const int reportStepIdx) const
Assign well guide rates.
Definition BlackoilWellModelGuideRates.cpp:392
Class for handling the blackoil well model.
Definition BlackoilWellModel.hpp:94
void initializeGroupStructure(const int reportStepIdx)
Initialize group control modes/constraints and group solution state.
Definition BlackoilWellModel_impl.hpp:291
const std::vector< WellInterfacePtr > & localNonshutWells() const
Get list of local nonshut wells.
Definition BlackoilWellModel.hpp:306
void calculateExplicitQuantities(DeferredLogger &deferred_logger) const
Calculating the explict quantities used in the well calculation.
Definition BlackoilWellModel_impl.hpp:1753
void initializeLocalWellStructure(const int reportStepIdx, const bool enableWellPIScaling)
Update rank's notion of intersecting wells and their associate solution variables.
Definition BlackoilWellModel_impl.hpp:246
void updateWellTestState(const double &simulationTime, WellTestState &wellTestState) const
upate the wellTestState related to economic limits
Definition BlackoilWellModel_impl.hpp:1961
int compressedIndexForInterior(int cartesian_cell_idx) const override
get compressed index for interior cells (-1, otherwise
Definition BlackoilWellModel.hpp:338
Represents the convergence status of the whole simulator, to make it possible to query and store the ...
Definition ConvergenceReport.hpp:38
Definition DeferredLogger.hpp:57
Convert component rates at surface conditions to phase (voidage) rates at reservoir conditions.
Definition RateConverter.hpp:71
Computes hydrocarbon weighed average pressures over regions.
Definition RegionAverageCalculator.hpp:60
Definition BlackoilWellModel.hpp:83
Definition WellConnectionAuxiliaryModule.hpp:39
This class serves to eliminate the need to include the WellContributions into the matrix (with –matri...
Definition WellContributions.hpp:51
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition blackoilboundaryratevector.hh:37
constexpr auto getPropValue()
get the value data member of a property
Definition propertysystem.hh:242
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:235
Solver parameters for the BlackoilModel.
Definition BlackoilModelParameters.hpp:174
bool matrix_add_well_contributions_
Whether to add influences of wells between cells to the matrix and preconditioner matrix.
Definition BlackoilModelParameters.hpp:280
bool use_multisegment_well_
Whether to use MultisegmentWell to handle multisegment wells it is something temporary before the mul...
Definition BlackoilModelParameters.hpp:274
int strict_outer_iter_wells_
Newton iteration where wells are stricly convergent.
Definition BlackoilModelParameters.hpp:230
A struct for returning timing data from a simulator to its caller.
Definition SimulatorReport.hpp:34