95 class BlackoilWellModel :
public WellConnectionAuxiliaryModule<TypeTag, BlackoilWellModel<TypeTag>>
96 ,
public BlackoilWellModelGeneric<GetPropType<TypeTag, Properties::Scalar>,
97 typename GetPropType<TypeTag, Properties::FluidSystem>::IndexTraitsType>
113 using WellConnectionModule = WellConnectionAuxiliaryModule<TypeTag, BlackoilWellModel<TypeTag>>;
114 using IndexTraits =
typename FluidSystem::IndexTraitsType;
119 static const int numEq = Indices::numEq;
120 static const int solventSaturationIdx = Indices::solventSaturationIdx;
124 static constexpr bool has_energy_ = (energyModuleType_ == EnergyModules::FullyImplicitThermal);
125 static constexpr bool has_micp_ = Indices::enableMICP;
130 using VectorBlockType = Dune::FieldVector<Scalar, numEq>;
131 using BVector = Dune::BlockVector<VectorBlockType>;
137 using RateConverterType = RateConverter::
138 SurfaceToReservoirVoidage<FluidSystem, std::vector<int> >;
141 using AverageRegionalPressureType = RegionAverageCalculator::
142 AverageRegionalPressure<FluidSystem, std::vector<int> >;
144 explicit BlackoilWellModel(Simulator& simulator);
147 void initWellContainer(
const int reportStepIdx)
override;
151 OPM_TIMEBLOCK(beginEpsiode);
152 beginReportStep(simulator_.episodeIndex());
155 void beginTimeStep();
157 void beginIteration()
159 OPM_TIMEBLOCK(beginIteration);
160 assemble(simulator_.timeStepSize());
168 OPM_TIMEBLOCK(endTimeStep);
169 timeStepSucceeded(simulator_.time(), simulator_.timeStepSize());
177 void computeTotalRatesForDof(RateVector& rate,
178 unsigned globalIdx)
const;
180 template <
class Context>
181 void computeTotalRatesForDof(RateVector& rate,
182 const Context& context,
184 unsigned timeIdx)
const;
187 using WellInterfacePtr = std::unique_ptr<WellInterface<TypeTag>>;
189 using BlackoilWellModelGeneric<Scalar, IndexTraits>::initFromRestartFile;
190 void initFromRestartFile(
const RestartValue& restartValues)
192 initFromRestartFile(restartValues,
193 this->simulator_.vanguard().transferWTestState(),
195 param_.use_multisegment_well_,
196 this->simulator_.vanguard().enableDistributedWells());
199 using BlackoilWellModelGeneric<Scalar, IndexTraits>::prepareDeserialize;
200 void prepareDeserialize(
const int report_step)
202 prepareDeserialize(report_step, grid().size(0),
203 param_.use_multisegment_well_,
204 this->simulator_.vanguard().enableDistributedWells());
207 data::Wells wellData()
const
209 auto wsrpt = this->wellState()
210 .report(this->simulator_.vanguard().globalCell().data(),
211 [
this](
const int well_index)
212 { return this->wasDynamicallyShutThisTimeStep(well_index); },
213 this->rsConstInfo());
218 this->assignWellTracerRates(wsrpt);
220 if constexpr (has_geochem_) {
221 this->assignWellSpeciesRates(wsrpt);
224 if (
const auto& rspec = eclState().runspec();
225 rspec.co2Storage() || rspec.h2Storage())
231 this->assignMassGasRate(wsrpt, FluidSystem::referenceDensity(FluidSystem::gasPhaseIdx, 0));
234 this->assignWellTargets(wsrpt);
245 data::WellBlockAveragePressures wellBlockAveragePressures()
const
247 return this->wbp_.computeWellBlockAveragePressures(this->gravity_);
250#if COMPILE_GPU_BRIDGE
256 ConvergenceReport getWellConvergence(
const std::vector<Scalar>& B_avg,
const bool checkWellGroupControlsAndNetwork =
false)
const;
260 void addWellContributions(SparseMatrixAdapter& jacobian)
const;
263 void addReservoirSourceTerms(GlobalEqVector& residual,
264 const std::vector<typename SparseMatrixAdapter::MatrixBlock*>& diagMatAddress)
const;
267 void beginReportStep(
const int time_step);
281 void updateAndCommunicate(
const int reportStepIdx);
283 bool updateGroupControls(
const Group& group,
285 const int reportStepIdx);
289 using PressureMatrix = Dune::BCRSMatrix<Opm::MatrixBlock<Scalar, 1, 1>>;
291 void addWellPressureEquations(PressureMatrix& jacobian,
292 const BVector& weights,
293 const bool use_well_weights)
const;
294 void addWellPressureEquationsStruct(PressureMatrix& jacobian)
const;
295 void addWellPressureEquationsDomain(PressureMatrix& jacobian,
296 const BVector& weights,
297 const bool use_well_weights,
298 const int domainIndex)
const
301 OPM_THROW(std::logic_error,
"Attempt to access NLDD data without a NLDD solver");
303 return nldd_->addWellPressureEquations(jacobian,
312 return well_container_;
318 OPM_THROW(std::logic_error,
"Attempt to access NLDD data without a NLDD solver");
320 return nldd_->well_local_cells();
323 const std::map<std::string, int>& well_domain()
const
326 OPM_THROW(std::logic_error,
"Attempt to access NLDD data without a NLDD solver");
329 return nldd_->well_domain();
332 auto begin()
const {
return well_container_.begin(); }
333 auto end()
const {
return well_container_.end(); }
334 bool empty()
const {
return well_container_.empty(); }
336 bool addMatrixContributions()
const
337 {
return param_.matrix_add_well_contributions_; }
339 int numStrictIterations()
const
340 {
return param_.strict_outer_iter_wells_; }
344 return simulator_.vanguard().compressedIndexForInterior(cartesian_cell_idx);
347 int compressedIndexForInteriorLGR(
const std::string& lgr_tag,
const Connection& conn)
const override
349 return simulator_.vanguard().compressedIndexForInteriorLGR(lgr_tag, conn);
354 void recoverWellSolutionAndUpdateWellState(
const BVector& x);
358 void recoverWellSolutionAndUpdateWellStateDomain(
const BVector& x,
359 const int domainIdx);
361 void updateCellRates();
364 void updateCellRatesForDomain(
int domainIndex,
365 const std::map<std::string, int>& well_domain_map);
367 const Grid& grid()
const
368 {
return simulator_.vanguard().grid(); }
370 const Simulator& simulator()
const
371 {
return simulator_; }
373 void setNlddAdapter(BlackoilWellModelNldd<TypeTag>* mod)
390 const double sim_time)
392 this->guide_rate_handler_.updateGuideRates(
393 report_step_idx, sim_time, this->wellState(), this->groupState()
406 return rescoup_.master();
412 return rescoup_.slave();
415#ifdef RESERVOIR_COUPLING_ENABLED
418 rescoup_.setMaster(master);
419 this->guide_rate_handler_.setReservoirCouplingMaster(master);
420 this->groupStateHelper().setReservoirCouplingMaster(master);
422 void setReservoirCouplingSlave(ReservoirCouplingSlave<Scalar>* slave)
424 rescoup_.setSlave(slave);
425 this->guide_rate_handler_.setReservoirCouplingSlave(slave);
426 this->groupStateHelper().setReservoirCouplingSlave(slave);
430 void sendSlaveGroupDataToMaster();
433 void receiveSlaveGroupData();
435 void receiveGroupConstraintsFromMaster();
436 void sendMasterGroupConstraintsToSlaves();
437 void rescoupSyncSummaryData();
447 std::optional<ReservoirCoupling::ScopedLoggerGuard>
448 setupRescoupScopedLogger(DeferredLogger& local_logger);
451 bool updateWellControlsAndNetwork(
const bool mandatory_network_balance,
453 DeferredLogger& local_deferredLogger);
456 void assembleWellEqWithoutIteration(
const double dt);
458 const std::vector<Scalar>& B_avg()
const
461 const ModelParameters& param()
const
465 template<
class Flu
idState,
class SingleWellState>
466 static Scalar computeTemperatureWeightFactor(
const int perf_index,
const int np,
const FluidState& fs,
const SingleWellState& ws)
468 const auto& perf_phase_rate = ws.perf_data.phase_rates;
470 Scalar cellTemperatures = fs.temperature(0).value();
471 Scalar weight_factor = 0.0;
472 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
473 if (!FluidSystem::phaseIsActive(phaseIdx)) {
476 Scalar cellInternalEnergy = fs.enthalpy(phaseIdx).value() -
477 fs.pressure(phaseIdx).value() / fs.density(phaseIdx).value();
478 Scalar cellBinv = fs.invB(phaseIdx).value();
479 Scalar cellDensity = fs.density(phaseIdx).value();
480 Scalar perfPhaseRate = perf_phase_rate[perf_index*np + phaseIdx];
481 weight_factor += cellDensity * (perfPhaseRate / cellBinv) * (cellInternalEnergy / cellTemperatures);
483 return (std::abs(weight_factor) + 1e-13);
487 Simulator& simulator_;
490 std::vector<WellInterfacePtr> well_container_{};
492 std::vector<bool> is_cell_perforated_{};
494 void initializeWellState(
const int timeStepIdx);
497 void createWellContainer(
const int report_step)
override;
500 createWellPointer(
const int wellID,
501 const int report_step)
const;
503 template <
typename WellType>
504 std::unique_ptr<WellType>
505 createTypedWellPointer(
const int wellID,
506 const int time_step)
const;
508 WellInterfacePtr createWellForWellTest(
const std::string& well_name,
509 const int report_step,
510 DeferredLogger& deferred_logger)
const;
512 const ModelParameters param_;
513 std::size_t global_num_cells_{};
515 std::size_t local_num_cells_{};
517 std::vector<Scalar> depth_{};
518 bool alternative_well_rate_init_{};
519 std::unique_ptr<RateConverterType> rateConverter_{};
520 std::map<std::string, std::unique_ptr<AverageRegionalPressureType>> regionalAveragePressureCalculator_{};
522 SimulatorReportSingle last_report_{};
523 GuideRateHandler<Scalar, IndexTraits> guide_rate_handler_{};
524 ReservoirCoupling::Proxy<Scalar> rescoup_{};
527 bool network_needs_more_balancing_force_another_newton_iteration_{
false};
529 std::vector<Scalar> B_avg_{};
531 const EquilGrid& equilGrid()
const
532 {
return simulator_.vanguard().equilGrid(); }
534 const EclipseState& eclState()
const
535 {
return simulator_.vanguard().eclState(); }
539 void assemble(
const double dt);
545 std::tuple<bool, bool, Scalar> updateWellControlsAndNetworkIteration(
const bool mandatory_network_balance,
546 const bool relax_network_tolerance,
547 const bool optimize_gas_lift,
549 DeferredLogger& local_deferredLogger);
560 const bool enableWellPIScaling);
568 void timeStepSucceeded(
const double simulationTime,
const double dt);
571 void endReportStep();
574 void updatePrimaryVariables();
576 void updateAverageFormationFactor();
578 void computePotentials(
const std::size_t widx,
579 const WellState<Scalar, IndexTraits>& well_state_copy,
580 std::string& exc_msg,
581 ExceptionType::ExcEnum& exc_type)
override;
583 const std::vector<Scalar>& wellPerfEfficiencyFactors()
const;
585 void calculateProductivityIndexValuesShutWells(
const int reportStepIdx, DeferredLogger& deferred_logger)
override;
586 void calculateProductivityIndexValues(DeferredLogger& deferred_logger)
override;
587 void calculateProductivityIndexValues(
const WellInterface<TypeTag>* wellPtr,
588 DeferredLogger& deferred_logger);
591 int numConservationQuantities()
const;
593 int reportStepIndex()
const;
595 void assembleWellEq(
const double dt);
597 void prepareWellsBeforeAssembling(
const double dt);
599 void extractLegacyCellPvtRegionIndex_();
601 void extractLegacyDepth_();
606 void wellTesting(
const int timeStepIdx,
const double simulationTime, DeferredLogger& deferred_logger);
608 void calcResvCoeff(
const int fipnum,
610 const std::vector<Scalar>& production_rates,
611 std::vector<Scalar>& resv_coeff)
const override;
613 void calcInjResvCoeff(
const int fipnum,
615 std::vector<Scalar>& resv_coeff)
const override;
617 void computeWellTemperature();
620 BlackoilWellModelGasLift<TypeTag> gaslift_;
621 BlackoilWellModelNetwork<TypeTag> network_;
622 BlackoilWellModelNldd<TypeTag>* nldd_ =
nullptr;
628 mutable BVector x_local_;
631 std::map<int, RateVector> cellRates_;
633 void assignWellTracerRates(data::Wells& wsrpt)
const;
634 void assignWellSpeciesRates(data::Wells& wsrpt)
const;
636 [[nodiscard]]
auto rsConstInfo() const
637 -> typename WellState<Scalar,IndexTraits>::RsConstInfo;