23#include <opm/simulators/utils/DeferredLoggingErrorHelpers.hpp>
24#include <opm/core/props/phaseUsageFromDeck.hpp>
25#include <opm/grid/utility/cartesianToCompressed.hpp>
27#include <opm/input/eclipse/Units/UnitSystem.hpp>
28#include <opm/input/eclipse/Schedule/Network/Balance.hpp>
29#include <opm/input/eclipse/Schedule/Network/ExtNetwork.hpp>
30#include <opm/input/eclipse/Schedule/Well/PAvgDynamicSourceData.hpp>
31#include <opm/input/eclipse/Schedule/Well/WellTestConfig.hpp>
32#include <opm/simulators/wells/BlackoilWellModelConstraints.hpp>
33#include <opm/simulators/wells/ParallelPAvgDynamicSourceData.hpp>
34#include <opm/simulators/wells/ParallelWBPCalculation.hpp>
35#include <opm/simulators/wells/VFPProperties.hpp>
36#include <opm/simulators/utils/MPIPacker.hpp>
37#include <opm/simulators/linalg/bda/WellContributions.hpp>
40#include <opm/simulators/utils/MPISerializer.hpp>
49#include <fmt/format.h>
52 template<
typename TypeTag>
53 BlackoilWellModel<TypeTag>::
54 BlackoilWellModel(Simulator& simulator,
const PhaseUsage& phase_usage)
55 : BlackoilWellModelGeneric(simulator.vanguard().schedule(),
56 simulator.vanguard().summaryState(),
57 simulator.vanguard().eclState(),
59 simulator.gridView().comm())
60 , simulator_(simulator)
62 terminal_output_ = ((simulator.gridView().comm().rank() == 0) &&
63 Parameters::get<TypeTag, Properties::EnableTerminalOutput>());
65 local_num_cells_ = simulator_.gridView().size(0);
68 global_num_cells_ = simulator_.vanguard().globalNumCells();
71 auto& parallel_wells = simulator.vanguard().parallelWells();
73 this->parallel_well_info_.reserve(parallel_wells.size());
74 for(
const auto& name_bool : parallel_wells) {
75 this->parallel_well_info_.emplace_back(name_bool, grid().comm());
79 this->alternative_well_rate_init_ =
80 Parameters::get<TypeTag, Properties::AlternativeWellRateInit>();
82 this->wbpCalculationService_
83 .localCellIndex([
this](
const std::size_t globalIndex)
84 {
return this->compressedIndexForInterior(globalIndex); })
85 .evalCellSource([
this](
const int localCell,
86 PAvgDynamicSourceData::SourceDataSpan<double> sourceTerms)
88 using Item = PAvgDynamicSourceData::SourceDataSpan<double>::Item;
90 const auto* intQuants = this->simulator_.model()
91 .cachedIntensiveQuantities(localCell, 0);
92 const auto& fs = intQuants->fluidState();
94 sourceTerms.set(Item::PoreVol, intQuants->porosity().value() *
95 this->simulator_.model().dofTotalVolume(localCell));
97 constexpr auto io = FluidSystem::oilPhaseIdx;
98 constexpr auto ig = FluidSystem::gasPhaseIdx;
99 constexpr auto iw = FluidSystem::waterPhaseIdx;
102 const auto haveOil = FluidSystem::phaseIsActive(io);
103 const auto haveGas = FluidSystem::phaseIsActive(ig);
104 const auto haveWat = FluidSystem::phaseIsActive(iw);
106 auto weightedPhaseDensity = [&fs](
const auto ip)
108 return fs.saturation(ip).value() * fs.density(ip).value();
111 if (haveOil) { sourceTerms.set(Item::Pressure, fs.pressure(io).value()); }
112 else if (haveGas) { sourceTerms.set(Item::Pressure, fs.pressure(ig).value()); }
113 else { sourceTerms.set(Item::Pressure, fs.pressure(iw).value()); }
117 if (haveOil) { rho += weightedPhaseDensity(io); }
118 if (haveGas) { rho += weightedPhaseDensity(ig); }
119 if (haveWat) { rho += weightedPhaseDensity(iw); }
121 sourceTerms.set(Item::MixtureDensity, rho);
125 template<
typename TypeTag>
126 BlackoilWellModel<TypeTag>::
127 BlackoilWellModel(Simulator& simulator) :
132 template<
typename TypeTag>
134 BlackoilWellModel<TypeTag>::
137 extractLegacyCellPvtRegionIndex_();
138 extractLegacyDepth_();
140 gravity_ = simulator_.problem().gravity()[2];
142 initial_step_ =
true;
145 simulator_.model().addAuxiliaryModule(
this);
147 is_cell_perforated_.resize(local_num_cells_,
false);
151 template<
typename TypeTag>
153 BlackoilWellModel<TypeTag>::
154 initWellContainer(
const int reportStepIdx)
156 const uint64_t effective_events_mask = ScheduleEvents::WELL_STATUS_CHANGE
157 + ScheduleEvents::NEW_WELL;
158 const auto& events = schedule()[reportStepIdx].wellgroup_events();
159 for (
auto& wellPtr : this->well_container_) {
160 const bool well_opened_this_step = report_step_starts_ && events.hasEvent(wellPtr->name(), effective_events_mask);
161 wellPtr->init(&this->phase_usage_, this->depth_, this->gravity_,
162 this->local_num_cells_, this->B_avg_, well_opened_this_step);
167 template<
typename TypeTag>
169 BlackoilWellModel<TypeTag>::
170 addNeighbors(std::vector<NeighborSet>& neighbors)
const
172 if (!param_.matrix_add_well_contributions_) {
177 const auto& schedule_wells = schedule().getWellsatEnd();
180 for (
const auto& well : schedule_wells)
182 std::vector<int> wellCells = this->getCellsForConnections(well);
183 for (
int cellIdx : wellCells) {
184 neighbors[cellIdx].insert(wellCells.begin(),
191 template<
typename TypeTag>
193 BlackoilWellModel<TypeTag>::
194 linearize(SparseMatrixAdapter& jacobian, GlobalEqVector& res)
196 OPM_BEGIN_PARALLEL_TRY_CATCH();
197 for (
const auto& well: well_container_) {
200 if (param_.matrix_add_well_contributions_) {
201 well->addWellContributions(jacobian);
207 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel::linearize failed: ",
208 simulator_.gridView().comm());
212 template<
typename TypeTag>
214 BlackoilWellModel<TypeTag>::
215 linearizeDomain(
const Domain& domain, SparseMatrixAdapter& jacobian, GlobalEqVector& res)
220 for (
const auto& well: well_container_) {
221 if (well_domain_.at(well->name()) == domain.index) {
224 if (param_.matrix_add_well_contributions_) {
225 well->addWellContributions(jacobian);
235 template<
typename TypeTag>
237 BlackoilWellModel<TypeTag>::
238 beginReportStep(
const int timeStepIdx)
240 DeferredLogger local_deferredLogger{};
242 this->report_step_starts_ =
true;
245 this->rateConverter_ = std::make_unique<RateConverterType>
246 (this->phase_usage_, std::vector<int>(this->local_num_cells_, 0));
250 const auto enableWellPIScaling =
true;
251 this->initializeLocalWellStructure(timeStepIdx, enableWellPIScaling);
254 this->initializeGroupStructure(timeStepIdx);
256 const auto& comm = this->simulator_.vanguard().grid().comm();
258 OPM_BEGIN_PARALLEL_TRY_CATCH()
262 this->rateConverter_->template defineState<ElementContext>(this->simulator_);
266 const auto& sched_state = this->schedule()[timeStepIdx];
268 this->vfp_properties_ = std::make_unique<VFPProperties>
269 (sched_state.vfpinj(), sched_state.vfpprod(), this->wellState());
272 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
273 "beginReportStep() failed: ",
274 this->terminal_output_, comm)
278 this->commitWGState();
280 this->wellStructureChangedDynamically_ =
false;
287 template <
typename TypeTag>
291 const bool enableWellPIScaling)
295 const auto& comm = this->simulator_.vanguard().grid().comm();
298 this->wells_ecl_ = this->getLocalWells(reportStepIdx);
299 this->local_parallel_well_info_ =
300 this->createLocalParallelWellInfo(this->wells_ecl_);
305 OPM_BEGIN_PARALLEL_TRY_CATCH()
307 this->initializeWellPerfData();
308 this->initializeWellState(reportStepIdx);
309 this->initializeWBPCalculationService();
311 if (this->param_.use_multisegment_well_ && this->anyMSWellOpenLocal()) {
312 this->wellState().initWellStateMSWell(this->wells_ecl_, &this->prevWellState());
315 this->initializeWellProdIndCalculators();
317 if (enableWellPIScaling && this->schedule()[reportStepIdx].events()
318 .hasEvent(ScheduleEvents::Events::WELL_PRODUCTIVITY_INDEX))
320 this->runWellPIScaling(reportStepIdx, local_deferredLogger);
323 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
324 "Failed to initialize local well structure: ",
325 this->terminal_output_, comm)
332 template <
typename TypeTag>
339 const auto& comm = this->simulator_.vanguard().grid().comm();
341 OPM_BEGIN_PARALLEL_TRY_CATCH()
343 const auto& fieldGroup =
344 this->schedule().getGroup(
"FIELD", reportStepIdx);
346 WellGroupHelpers::setCmodeGroup(fieldGroup,
348 this->summaryState(),
354 if (this->schedule()[reportStepIdx].has_gpmaint()) {
355 WellGroupHelpers::setRegionAveragePressureCalculator
359 this->eclState_.fieldProps(),
361 this->regionalAveragePressureCalculator_);
364 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
365 "Failed to initialize group structure: ",
366 this->terminal_output_, comm)
374 template<
typename TypeTag>
379 OPM_TIMEBLOCK(beginTimeStep);
381 this->updateAverageFormationFactor();
385 this->switched_prod_groups_.clear();
386 this->switched_inj_groups_.clear();
388 if (this->wellStructureChangedDynamically_) {
393 const auto reportStepIdx =
394 this->simulator_.episodeIndex();
398 const auto enableWellPIScaling =
false;
400 this->initializeLocalWellStructure(reportStepIdx, enableWellPIScaling);
401 this->initializeGroupStructure(reportStepIdx);
403 this->commitWGState();
409 this->wellStructureChangedDynamically_ =
false;
412 this->resetWGState();
414 const int reportStepIdx = simulator_.episodeIndex();
415 updateAndCommunicateGroupData(reportStepIdx,
416 simulator_.model().newtonMethod().numIterations());
418 this->wellState().updateWellsDefaultALQ(this->wells_ecl_, this->summaryState());
419 this->wellState().gliftTimeStepInit();
421 const double simulationTime = simulator_.time();
422 OPM_BEGIN_PARALLEL_TRY_CATCH();
425 wellTesting(reportStepIdx, simulationTime, local_deferredLogger);
428 createWellContainer(reportStepIdx);
431 const Grid& grid = simulator_.vanguard().grid();
432 wells_active_ = !this->well_container_.empty();
433 wells_active_ = grid.comm().max(wells_active_);
438 this->initWellContainer(reportStepIdx);
441 std::fill(is_cell_perforated_.begin(), is_cell_perforated_.end(),
false);
442 for (
auto& well : well_container_) {
443 well->updatePerforatedCell(is_cell_perforated_);
447 calculateEfficiencyFactors(reportStepIdx);
449 if constexpr (has_polymer_)
451 if (PolymerModule::hasPlyshlog() || getPropValue<TypeTag, Properties::EnablePolymerMW>() ) {
452 setRepRadiusPerfLength();
457 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
"beginTimeStep() failed: ",
458 terminal_output_, simulator_.vanguard().grid().comm());
460 for (
auto& well : well_container_) {
461 well->setVFPProperties(vfp_properties_.get());
462 well->setGuideRate(&guideRate_);
465 this->updateInjFCMult(local_deferredLogger);
468 for (
auto& well : well_container_) {
469 well->closeCompletions(wellTestState());
475 const auto& summaryState = simulator_.vanguard().summaryState();
476 if (alternative_well_rate_init_) {
481 for (
auto& well : well_container_) {
482 const bool zero_target = well->stopppedOrZeroRateTarget(summaryState, this->wellState());
483 if (well->isProducer() && !zero_target) {
484 well->updateWellStateRates(simulator_, this->wellState(), local_deferredLogger);
489 for (
auto& well : well_container_) {
490 if (well->isVFPActive(local_deferredLogger)){
491 well->setPrevSurfaceRates(this->wellState(), this->prevWellState());
497 updateWellPotentials(reportStepIdx,
499 simulator_.vanguard().summaryConfig(),
500 local_deferredLogger);
501 }
catch ( std::runtime_error& e ) {
502 const std::string msg =
"A zero well potential is returned for output purposes. ";
503 local_deferredLogger.warning(
"WELL_POTENTIAL_CALCULATION_FAILED", msg);
507 const auto& comm = simulator_.vanguard().grid().comm();
508 std::vector<double> pot(numPhases(), 0.0);
509 const Group& fieldGroup = schedule().getGroup(
"FIELD", reportStepIdx);
510 WellGroupHelpers::updateGuideRates(fieldGroup, schedule(), summaryState, this->phase_usage_, reportStepIdx, simulationTime,
511 this->wellState(), this->groupState(), comm, &this->guideRate_, pot, local_deferredLogger);
513 auto exc_type = ExceptionType::NONE;
515 if (schedule_[reportStepIdx].has_gpmaint()) {
516 for (
auto& calculator : regionalAveragePressureCalculator_) {
517 calculator.second->template defineState<ElementContext>(simulator_);
519 const double dt = simulator_.timeStepSize();
520 WellGroupHelpers::updateGpMaintTargetForGroups(fieldGroup,
521 schedule_, regionalAveragePressureCalculator_, reportStepIdx, dt, this->wellState(), this->groupState());
525 for (
auto& well : well_container_) {
526 const uint64_t effective_events_mask = ScheduleEvents::WELL_STATUS_CHANGE
527 + ScheduleEvents::INJECTION_TYPE_CHANGED
528 + ScheduleEvents::WELL_SWITCHED_INJECTOR_PRODUCER
529 + ScheduleEvents::NEW_WELL;
531 const auto& events = schedule()[reportStepIdx].wellgroup_events();
532 const bool event = report_step_starts_ && events.hasEvent(well->name(), effective_events_mask);
533 const bool dyn_status_change = this->wellState().well(well->name()).status
534 != this->prevWellState().well(well->name()).status;
536 if (event || dyn_status_change) {
538 well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), local_deferredLogger);
539 well->calculateExplicitQuantities(simulator_, this->wellState(), local_deferredLogger);
540 well->solveWellEquation(simulator_, this->wellState(), this->groupState(), local_deferredLogger);
541 }
catch (
const std::exception& e) {
542 const std::string msg =
"Compute initial well solution for new well " + well->name() +
" failed. Continue with zero initial rates";
543 local_deferredLogger.warning(
"WELL_INITIAL_SOLVE_FAILED", msg);
549 OPM_PARALLEL_CATCH_CLAUSE(exc_type, exc_msg);
551 if (exc_type != ExceptionType::NONE) {
552 const std::string msg =
"Compute initial well solution for new wells failed. Continue with zero initial rates";
553 local_deferredLogger.warning(
"WELL_INITIAL_SOLVE_FAILED", msg);
556 logAndCheckForExceptionsAndThrow(local_deferredLogger,
557 exc_type,
"beginTimeStep() failed: " + exc_msg, terminal_output_, comm);
561 template<
typename TypeTag>
563 BlackoilWellModel<TypeTag>::wellTesting(
const int timeStepIdx,
564 const double simulationTime,
565 DeferredLogger& deferred_logger)
567 for (
const std::string& well_name : this->getWellsForTesting(timeStepIdx, simulationTime)) {
568 const Well& wellEcl = schedule().getWell(well_name, timeStepIdx);
569 if (wellEcl.getStatus() == Well::Status::SHUT)
572 WellInterfacePtr well = createWellForWellTest(well_name, timeStepIdx, deferred_logger);
574 well->init(&phase_usage_, depth_, gravity_, local_num_cells_, B_avg_,
true);
576 double well_efficiency_factor = wellEcl.getEfficiencyFactor();
577 WellGroupHelpers::accumulateGroupEfficiencyFactor(schedule().getGroup(wellEcl.groupName(), timeStepIdx),
578 schedule(), timeStepIdx, well_efficiency_factor);
580 well->setWellEfficiencyFactor(well_efficiency_factor);
581 well->setVFPProperties(vfp_properties_.get());
582 well->setGuideRate(&guideRate_);
585 if (well->isProducer()) {
586 well->updateWellStateRates(simulator_, this->wellState(), deferred_logger);
588 if (well->isVFPActive(deferred_logger)) {
589 well->setPrevSurfaceRates(this->wellState(), this->prevWellState());
593 well->wellTesting(simulator_, simulationTime, this->wellState(), this->groupState(), wellTestState(), deferred_logger);
594 }
catch (
const std::exception& e) {
595 const std::string msg = fmt::format(
"Exception during testing of well: {}. The well will not open.\n Exception message: {}", wellEcl.name(), e.what());
596 deferred_logger.warning(
"WELL_TESTING_FAILED", msg);
606 template<
typename TypeTag>
608 BlackoilWellModel<TypeTag>::
612 for (
auto&& pinfo : this->local_parallel_well_info_)
623 template<
typename TypeTag>
624 const SimulatorReportSingle&
625 BlackoilWellModel<TypeTag>::
626 lastReport()
const {
return last_report_; }
633 template<
typename TypeTag>
635 BlackoilWellModel<TypeTag>::
636 timeStepSucceeded(
const double simulationTime,
const double dt)
638 this->closed_this_step_.clear();
641 report_step_starts_ =
false;
642 const int reportStepIdx = simulator_.episodeIndex();
644 DeferredLogger local_deferredLogger;
645 for (
const auto& well : well_container_) {
646 if (getPropValue<TypeTag, Properties::EnablePolymerMW>() && well->isInjector()) {
647 well->updateWaterThroughput(dt, this->wellState());
651 for (
const auto& well : well_container_) {
652 well->updateConnectionTransmissibilityFactor(simulator_, this->wellState().well(well->indexOfWell()));
653 well->updateConnectionDFactor(simulator_, this->wellState().well(well->indexOfWell()));
656 if (Indices::waterEnabled) {
657 this->updateFiltrationParticleVolume(dt, FluidSystem::waterPhaseIdx);
661 this->updateInjMult(local_deferredLogger);
664 for (
const auto& well : well_container_) {
665 well->reportWellSwitching(this->wellState().well(well->indexOfWell()), local_deferredLogger);
668 if (terminal_output_) {
670 for (
const auto& [name, to] : switched_prod_groups_) {
671 const Group::ProductionCMode& oldControl = this->prevWGState().group_state.production_control(name);
672 std::string from = Group::ProductionCMode2String(oldControl);
674 std::string msg =
" Production Group " + name
675 +
" control mode changed from ";
678 local_deferredLogger.info(msg);
681 for (
const auto& [key, to] : switched_inj_groups_) {
682 const std::string& name = key.first;
683 const Opm::Phase& phase = key.second;
685 const Group::InjectionCMode& oldControl = this->prevWGState().group_state.injection_control(name, phase);
686 std::string from = Group::InjectionCMode2String(oldControl);
688 std::string msg =
" Injection Group " + name
689 +
" control mode changed from ";
692 local_deferredLogger.info(msg);
698 rateConverter_->template defineState<ElementContext>(simulator_);
702 updateWellPotentials(reportStepIdx,
704 simulator_.vanguard().summaryConfig(),
705 local_deferredLogger);
706 }
catch ( std::runtime_error& e ) {
707 const std::string msg =
"A zero well potential is returned for output purposes. ";
708 local_deferredLogger.warning(
"WELL_POTENTIAL_CALCULATION_FAILED", msg);
711 updateWellTestState(simulationTime, wellTestState());
714 const Group& fieldGroup = schedule_.getGroup(
"FIELD", reportStepIdx);
716 fieldGroup, simulationTime, simulator_.episodeIndex(), local_deferredLogger);
717 checkGconsaleLimits(fieldGroup, this->wellState(),
718 simulator_.episodeIndex(), local_deferredLogger);
720 this->calculateProductivityIndexValues(local_deferredLogger);
722 this->commitWGState();
724 const Opm::Parallel::Communication& comm = grid().comm();
726 if (terminal_output_) {
727 global_deferredLogger.logMessages();
731 this->computeWellTemperature();
735 template<
typename TypeTag>
737 BlackoilWellModel<TypeTag>::
738 computeTotalRatesForDof(RateVector& rate,
739 unsigned elemIdx)
const
743 if (!is_cell_perforated_[elemIdx])
746 for (
const auto& well : well_container_)
747 well->addCellRates(rate, elemIdx);
751 template<
typename TypeTag>
752 template <
class Context>
754 BlackoilWellModel<TypeTag>::
755 computeTotalRatesForDof(RateVector& rate,
756 const Context& context,
758 unsigned timeIdx)
const
761 int elemIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
763 if (!is_cell_perforated_[elemIdx])
766 for (
const auto& well : well_container_)
767 well->addCellRates(rate, elemIdx);
772 template<
typename TypeTag>
774 BlackoilWellModel<TypeTag>::
775 initializeWellState(
const int timeStepIdx)
777 std::vector<double> cellPressures(this->local_num_cells_, 0.0);
778 ElementContext elemCtx(simulator_);
780 const auto& gridView = simulator_.vanguard().gridView();
782 OPM_BEGIN_PARALLEL_TRY_CATCH();
783 for (
const auto& elem : elements(gridView, Dune::Partitions::interior)) {
784 elemCtx.updatePrimaryStencil(elem);
785 elemCtx.updatePrimaryIntensiveQuantities(0);
787 const auto& fs = elemCtx.intensiveQuantities(0, 0).fluidState();
789 double& perf_pressure = cellPressures[elemCtx.globalSpaceIndex(0, 0)];
790 if (Indices::oilEnabled) {
791 perf_pressure = fs.pressure(FluidSystem::oilPhaseIdx).value();
792 }
else if (Indices::waterEnabled) {
793 perf_pressure = fs.pressure(FluidSystem::waterPhaseIdx).value();
795 perf_pressure = fs.pressure(FluidSystem::gasPhaseIdx).value();
798 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel::initializeWellState() failed: ", simulator_.vanguard().grid().comm());
800 this->wellState().init(cellPressures, schedule(), wells_ecl_, local_parallel_well_info_, timeStepIdx,
801 &this->prevWellState(), well_perf_data_,
802 this->summaryState());
809 template<
typename TypeTag>
811 BlackoilWellModel<TypeTag>::
812 createWellContainer(
const int report_step)
814 DeferredLogger local_deferredLogger;
816 const int nw = numLocalWells();
818 well_container_.clear();
821 well_container_.reserve(nw);
823 for (
int w = 0; w < nw; ++w) {
824 const Well& well_ecl = wells_ecl_[w];
826 if (!well_ecl.hasConnections()) {
831 const std::string& well_name = well_ecl.name();
832 const auto well_status = this->schedule()
833 .getWell(well_name, report_step).getStatus();
835 if ((well_ecl.getStatus() == Well::Status::SHUT) ||
836 (well_status == Well::Status::SHUT))
839 if (well_ecl.getStatus() != Well::Status::SHUT) {
840 this->closed_this_step_.insert(well_name);
841 this->wellState().shutWell(w);
848 if (this->wellTestState().well_is_closed(well_name)) {
853 const bool closed_this_step = (wellTestState().lastTestTime(well_name) == simulator_.time());
856 auto& events = this->wellState().well(w).events;
857 if (events.hasEvent(ScheduleEvents::REQUEST_OPEN_WELL)) {
858 if (!closed_this_step) {
859 wellTestState().open_well(well_name);
860 wellTestState().open_completions(well_name);
862 events.clearEvent(ScheduleEvents::REQUEST_OPEN_WELL);
868 bool wellIsStopped =
false;
869 if (wellTestState().well_is_closed(well_name))
871 if (well_ecl.getAutomaticShutIn()) {
873 this->wellState().shutWell(w);
876 if (!well_ecl.getAllowCrossFlow()) {
879 this->wellState().shutWell(w);
883 this->wellState().stopWell(w);
884 wellIsStopped =
true;
889 if (!well_ecl.getAllowCrossFlow()) {
890 const bool any_zero_rate_constraint = well_ecl.isProducer()
891 ? well_ecl.productionControls(summaryState_).anyZeroRateConstraint()
892 : well_ecl.injectionControls(summaryState_).anyZeroRateConstraint();
893 if (any_zero_rate_constraint) {
895 local_deferredLogger.debug(fmt::format(
" Well {} gets shut due to having zero rate constraint and disallowing crossflow ", well_ecl.name()) );
896 this->wellState().shutWell(w);
901 if (well_status == Well::Status::STOP) {
902 this->wellState().stopWell(w);
903 wellIsStopped =
true;
906 well_container_.emplace_back(this->createWellPointer(w, report_step));
909 well_container_.back()->stopWell();
915 const Opm::Parallel::Communication& comm = grid().comm();
917 if (terminal_output_) {
918 global_deferredLogger.logMessages();
921 well_container_generic_.clear();
922 for (
auto& w : well_container_)
923 well_container_generic_.push_back(w.get());
925 const auto& network = schedule()[report_step].network();
926 if (network.active() && !this->node_pressures_.empty()) {
927 for (
auto& well: well_container_generic_) {
931 if (well->isProducer()) {
932 const auto it = node_pressures_.find(well->wellEcl().groupName());
933 if (it != node_pressures_.end()) {
936 const double nodal_pressure = it->second;
937 well->setDynamicThpLimit(nodal_pressure);
943 this->registerOpenWellsForWBPCalculation();
950 template <
typename TypeTag>
951 typename BlackoilWellModel<TypeTag>::WellInterfacePtr
952 BlackoilWellModel<TypeTag>::
953 createWellPointer(
const int wellID,
const int report_step)
const
955 const auto is_multiseg = this->wells_ecl_[wellID].isMultiSegment();
957 if (! (this->param_.use_multisegment_well_ && is_multiseg)) {
958 return this->
template createTypedWellPointer<StandardWell<TypeTag>>(wellID, report_step);
961 return this->
template createTypedWellPointer<MultisegmentWell<TypeTag>>(wellID, report_step);
969 template <
typename TypeTag>
970 template <
typename WellType>
971 std::unique_ptr<WellType>
972 BlackoilWellModel<TypeTag>::
973 createTypedWellPointer(
const int wellID,
const int time_step)
const
976 const auto& perf_data = this->well_perf_data_[wellID];
979 const auto pvtreg = perf_data.empty()
980 ? 0 : pvt_region_idx_[perf_data.front().cell_index];
982 const auto& parallel_well_info = this->local_parallel_well_info_[wellID].get();
983 const auto global_pvtreg = parallel_well_info.broadcastFirstPerforationValue(pvtreg);
985 return std::make_unique<WellType>(this->wells_ecl_[wellID],
989 *this->rateConverter_,
991 this->numComponents(),
1001 template<
typename TypeTag>
1002 typename BlackoilWellModel<TypeTag>::WellInterfacePtr
1003 BlackoilWellModel<TypeTag>::
1004 createWellForWellTest(
const std::string& well_name,
1005 const int report_step,
1006 DeferredLogger& deferred_logger)
const
1009 const int nw_wells_ecl = wells_ecl_.size();
1010 int index_well_ecl = 0;
1011 for (; index_well_ecl < nw_wells_ecl; ++index_well_ecl) {
1012 if (well_name == wells_ecl_[index_well_ecl].name()) {
1017 if (index_well_ecl == nw_wells_ecl) {
1018 OPM_DEFLOG_THROW(std::logic_error,
1019 fmt::format(
"Could not find well {} in wells_ecl ", well_name),
1023 return this->createWellPointer(index_well_ecl, report_step);
1028 template<
typename TypeTag>
1030 BlackoilWellModel<TypeTag>::
1031 doPreStepNetworkRebalance(DeferredLogger& deferred_logger) {
1032 const double dt = this->simulator_.timeStepSize();
1034 auto& well_state = this->wellState();
1035 const std::size_t max_iter = param_.network_max_iterations_;
1036 bool converged =
false;
1037 std::size_t iter = 0;
1038 bool changed_well_group =
false;
1040 changed_well_group = updateWellControlsAndNetwork(
true, dt, deferred_logger);
1041 assembleWellEqWithoutIteration(dt, deferred_logger);
1042 converged = this->getWellConvergence(this->B_avg_,
true).converged() && !changed_well_group;
1047 for (
auto& well : this->well_container_) {
1048 const auto& summary_state = this->simulator_.vanguard().summaryState();
1049 well->solveEqAndUpdateWellState(summary_state, well_state, deferred_logger);
1051 this->initPrimaryVariablesEvaluation();
1052 }
while (iter < max_iter);
1055 const std::string msg = fmt::format(
"Initial (pre-step) network balance did not get converged with {} iterations, "
1056 "unconverged network balance result will be used", max_iter);
1057 deferred_logger.warning(msg);
1059 const std::string msg = fmt::format(
"Initial (pre-step) network balance converged with {} iterations", iter);
1060 deferred_logger.debug(msg);
1067 template<
typename TypeTag>
1069 BlackoilWellModel<TypeTag>::
1070 assemble(
const int iterationIdx,
1074 DeferredLogger local_deferredLogger;
1075 if (this->glift_debug) {
1076 const std::string msg = fmt::format(
1077 "assemble() : iteration {}" , iterationIdx);
1078 gliftDebug(msg, local_deferredLogger);
1080 last_report_ = SimulatorReportSingle();
1081 Dune::Timer perfTimer;
1083 closed_offending_wells_.clear();
1086 const int episodeIdx = simulator_.episodeIndex();
1087 const auto& network = schedule()[episodeIdx].network();
1088 if ( !wellsActive() && !network.active() ) {
1093 if (iterationIdx == 0 && wellsActive()) {
1098 OPM_BEGIN_PARALLEL_TRY_CATCH();
1100 calculateExplicitQuantities(local_deferredLogger);
1101 prepareTimeStep(local_deferredLogger);
1103 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
1104 "assemble() failed (It=0): ",
1105 terminal_output_, grid().comm());
1108 const bool well_group_control_changed = updateWellControlsAndNetwork(
false, dt, local_deferredLogger);
1112 if ( ! wellsActive() ) {
1116 assembleWellEqWithoutIteration(dt, local_deferredLogger);
1120 last_report_.well_group_control_changed = well_group_control_changed;
1121 last_report_.assemble_time_well += perfTimer.stop();
1127 template<
typename TypeTag>
1129 BlackoilWellModel<TypeTag>::
1130 updateWellControlsAndNetwork(
const bool mandatory_network_balance,
const double dt, DeferredLogger& local_deferredLogger)
1133 bool do_network_update =
true;
1134 bool well_group_control_changed =
false;
1136 const std::size_t iteration_to_relax = param_.network_max_strict_iterations_;
1138 const std::size_t max_iteration = param_.network_max_iterations_;
1139 std::size_t network_update_iteration = 0;
1140 while (do_network_update) {
1141 if (terminal_output_ && (network_update_iteration == iteration_to_relax) ) {
1142 local_deferredLogger.info(
" we begin using relaxed tolerance for network update now after " + std::to_string(iteration_to_relax) +
" iterations ");
1144 const bool relax_network_balance = network_update_iteration >= iteration_to_relax;
1145 std::tie(do_network_update, well_group_control_changed) =
1146 updateWellControlsAndNetworkIteration(mandatory_network_balance, relax_network_balance, dt,local_deferredLogger);
1147 ++network_update_iteration;
1149 if (network_update_iteration >= max_iteration ) {
1150 if (terminal_output_) {
1151 local_deferredLogger.info(
"maximum of " + std::to_string(max_iteration) +
" iterations has been used, we stop the network update now. "
1152 "The simulation will continue with unconverged network results");
1157 return well_group_control_changed;
1163 template<
typename TypeTag>
1164 std::pair<bool, bool>
1165 BlackoilWellModel<TypeTag>::
1166 updateWellControlsAndNetworkIteration(
const bool mandatory_network_balance,
1167 const bool relax_network_tolerance,
1169 DeferredLogger& local_deferredLogger)
1171 auto [well_group_control_changed, more_network_update] =
1172 updateWellControls(mandatory_network_balance, local_deferredLogger, relax_network_tolerance);
1174 bool alq_updated =
false;
1175 OPM_BEGIN_PARALLEL_TRY_CATCH();
1178 initPrimaryVariablesEvaluation();
1180 alq_updated = maybeDoGasLiftOptimize(local_deferredLogger);
1182 prepareWellsBeforeAssembling(dt, local_deferredLogger);
1184 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
"updateWellControlsAndNetworkIteration() failed: ",
1185 terminal_output_, grid().comm());
1188 const int reportStepIdx = simulator_.episodeIndex();
1189 if (alq_updated || BlackoilWellModelGuideRates(*this).
1190 guideRateUpdateIsNeeded(reportStepIdx)) {
1191 const double simulationTime = simulator_.time();
1192 const auto& comm = simulator_.vanguard().grid().comm();
1193 const auto& summaryState = simulator_.vanguard().summaryState();
1194 std::vector<double> pot(numPhases(), 0.0);
1195 const Group& fieldGroup = schedule().getGroup(
"FIELD", reportStepIdx);
1196 WellGroupHelpers::updateGuideRates(fieldGroup, schedule(), summaryState, this->phase_usage_, reportStepIdx, simulationTime,
1197 this->wellState(), this->groupState(), comm, &this->guideRate_, pot, local_deferredLogger);
1201 return {more_network_update, well_group_control_changed};
1206 template<
typename TypeTag>
1208 BlackoilWellModel<TypeTag>::
1209 assembleDomain([[maybe_unused]]
const int iterationIdx,
1211 const Domain& domain)
1213 last_report_ = SimulatorReportSingle();
1214 Dune::Timer perfTimer;
1218 const int episodeIdx = simulator_.episodeIndex();
1219 const auto& network = schedule()[episodeIdx].network();
1220 if ( !wellsActive() && !network.active() ) {
1230 DeferredLogger local_deferredLogger;
1231 updateWellControlsDomain(local_deferredLogger, domain);
1232 initPrimaryVariablesEvaluationDomain(domain);
1233 assembleWellEqDomain(dt, domain, local_deferredLogger);
1237 if (terminal_output_) {
1238 local_deferredLogger.logMessages();
1241 last_report_.converged =
true;
1242 last_report_.assemble_time_well += perfTimer.stop();
1246 template<
typename TypeTag>
1248 BlackoilWellModel<TypeTag>::
1249 maybeDoGasLiftOptimize(DeferredLogger& deferred_logger)
1251 bool do_glift_optimization =
false;
1252 int num_wells_changed = 0;
1253 const double simulation_time = simulator_.time();
1254 const double min_wait = simulator_.vanguard().schedule().glo(simulator_.episodeIndex()).min_wait();
1259 if ( simulation_time == last_glift_opt_time_ || simulation_time >= (last_glift_opt_time_ + min_wait)) {
1260 do_glift_optimization =
true;
1261 last_glift_opt_time_ = simulation_time;
1264 if (do_glift_optimization) {
1265 GLiftOptWells glift_wells;
1266 GLiftProdWells prod_wells;
1267 GLiftWellStateMap state_map;
1275 GLiftEclWells ecl_well_map;
1276 initGliftEclWellMap(ecl_well_map);
1277 GasLiftGroupInfo group_info {
1279 simulator_.vanguard().schedule(),
1280 simulator_.vanguard().summaryState(),
1281 simulator_.episodeIndex(),
1282 simulator_.model().newtonMethod().numIterations(),
1287 simulator_.vanguard().grid().comm(),
1290 group_info.initialize();
1291 gasLiftOptimizationStage1(
1292 deferred_logger, prod_wells, glift_wells, group_info, state_map);
1293 gasLiftOptimizationStage2(
1294 deferred_logger, prod_wells, glift_wells, group_info, state_map,
1295 simulator_.episodeIndex());
1296 if (this->glift_debug) gliftDebugShowALQ(deferred_logger);
1297 num_wells_changed = glift_wells.size();
1299 num_wells_changed = this->comm_.sum(num_wells_changed);
1300 return num_wells_changed > 0;
1303 template<
typename TypeTag>
1305 BlackoilWellModel<TypeTag>::
1306 gasLiftOptimizationStage1(DeferredLogger& deferred_logger,
1307 GLiftProdWells &prod_wells, GLiftOptWells &glift_wells,
1308 GasLiftGroupInfo &group_info, GLiftWellStateMap &state_map)
1310 auto comm = simulator_.vanguard().grid().comm();
1311 int num_procs = comm.size();
1337 for (
int i = 0; i< num_procs; i++) {
1338 int num_rates_to_sync = 0;
1339 GLiftSyncGroups groups_to_sync;
1340 if (comm.rank() == i) {
1342 for (
const auto& well : well_container_) {
1344 if (group_info.hasWell(well->name())) {
1345 gasLiftOptimizationStage1SingleWell(
1346 well.get(), deferred_logger, prod_wells, glift_wells,
1347 group_info, state_map, groups_to_sync
1351 num_rates_to_sync = groups_to_sync.size();
1353 num_rates_to_sync = comm.sum(num_rates_to_sync);
1354 if (num_rates_to_sync > 0) {
1355 std::vector<int> group_indexes;
1356 group_indexes.reserve(num_rates_to_sync);
1357 std::vector<double> group_alq_rates;
1358 group_alq_rates.reserve(num_rates_to_sync);
1359 std::vector<double> group_oil_rates;
1360 group_oil_rates.reserve(num_rates_to_sync);
1361 std::vector<double> group_gas_rates;
1362 group_gas_rates.reserve(num_rates_to_sync);
1363 std::vector<double> group_water_rates;
1364 group_water_rates.reserve(num_rates_to_sync);
1365 if (comm.rank() == i) {
1366 for (
auto idx : groups_to_sync) {
1367 auto [oil_rate, gas_rate, water_rate, alq] = group_info.getRates(idx);
1368 group_indexes.push_back(idx);
1369 group_oil_rates.push_back(oil_rate);
1370 group_gas_rates.push_back(gas_rate);
1371 group_water_rates.push_back(water_rate);
1372 group_alq_rates.push_back(alq);
1375 group_indexes.resize(num_rates_to_sync);
1376 group_oil_rates.resize(num_rates_to_sync);
1377 group_gas_rates.resize(num_rates_to_sync);
1378 group_water_rates.resize(num_rates_to_sync);
1379 group_alq_rates.resize(num_rates_to_sync);
1382 Parallel::MpiSerializer ser(comm);
1383 ser.broadcast(i, group_indexes, group_oil_rates,
1384 group_gas_rates, group_water_rates, group_alq_rates);
1386 if (comm.rank() != i) {
1387 for (
int j=0; j<num_rates_to_sync; j++) {
1388 group_info.updateRate(group_indexes[j],
1389 group_oil_rates[j], group_gas_rates[j], group_water_rates[j], group_alq_rates[j]);
1392 if (this->glift_debug) {
1394 if (comm.rank() == i) {
1395 counter = this->wellState().gliftGetDebugCounter();
1397 counter = comm.sum(counter);
1398 if (comm.rank() != i) {
1399 this->wellState().gliftSetDebugCounter(counter);
1409 template<
typename TypeTag>
1411 BlackoilWellModel<TypeTag>::
1412 gasLiftOptimizationStage1SingleWell(WellInterface<TypeTag> *well,
1413 DeferredLogger& deferred_logger,
1414 GLiftProdWells &prod_wells, GLiftOptWells &glift_wells,
1415 GasLiftGroupInfo &group_info, GLiftWellStateMap &state_map,
1416 GLiftSyncGroups& sync_groups)
1418 const auto& summary_state = simulator_.vanguard().summaryState();
1419 std::unique_ptr<GasLiftSingleWell> glift
1420 = std::make_unique<GasLiftSingleWell>(
1421 *well, simulator_, summary_state,
1422 deferred_logger, this->wellState(), this->groupState(),
1423 group_info, sync_groups, this->comm_, this->glift_debug);
1424 auto state = glift->runOptimize(
1425 simulator_.model().newtonMethod().numIterations());
1427 state_map.insert({well->name(), std::move(state)});
1428 glift_wells.insert({well->name(), std::move(glift)});
1431 prod_wells.insert({well->name(), well});
1435 template<
typename TypeTag>
1437 BlackoilWellModel<TypeTag>::
1438 initGliftEclWellMap(GLiftEclWells &ecl_well_map)
1440 for (
const auto& well: well_container_ ) {
1441 ecl_well_map.try_emplace(
1442 well->name(), &(well->wellEcl()), well->indexOfWell());
1447 template<
typename TypeTag>
1449 BlackoilWellModel<TypeTag>::
1450 assembleWellEq(
const double dt, DeferredLogger& deferred_logger)
1452 for (
auto& well : well_container_) {
1453 well->assembleWellEq(simulator_, dt, this->wellState(), this->groupState(), deferred_logger);
1458 template<
typename TypeTag>
1460 BlackoilWellModel<TypeTag>::
1461 assembleWellEqDomain(
const double dt,
const Domain& domain, DeferredLogger& deferred_logger)
1463 for (
auto& well : well_container_) {
1464 if (well_domain_.at(well->name()) == domain.index) {
1465 well->assembleWellEq(simulator_, dt, this->wellState(), this->groupState(), deferred_logger);
1471 template<
typename TypeTag>
1473 BlackoilWellModel<TypeTag>::
1474 prepareWellsBeforeAssembling(
const double dt, DeferredLogger& deferred_logger)
1476 for (
auto& well : well_container_) {
1477 well->prepareWellBeforeAssembling(simulator_, dt, this->wellState(), this->groupState(), deferred_logger);
1482 template<
typename TypeTag>
1484 BlackoilWellModel<TypeTag>::
1485 assembleWellEqWithoutIteration(
const double dt, DeferredLogger& deferred_logger)
1489 OPM_BEGIN_PARALLEL_TRY_CATCH();
1491 for (
auto& well: well_container_) {
1492 well->assembleWellEqWithoutIteration(simulator_, dt, this->wellState(), this->groupState(),
1495 OPM_END_PARALLEL_TRY_CATCH_LOG(deferred_logger,
"BlackoilWellModel::assembleWellEqWithoutIteration failed: ",
1496 terminal_output_, grid().comm());
1501 template<
typename TypeTag>
1503 BlackoilWellModel<TypeTag>::
1504 apply(BVector& r)
const
1506 for (
auto& well : well_container_) {
1513 template<
typename TypeTag>
1515 BlackoilWellModel<TypeTag>::
1516 apply(
const BVector& x, BVector& Ax)
const
1518 for (
auto& well : well_container_) {
1523 template<
typename TypeTag>
1525 BlackoilWellModel<TypeTag>::
1526 getWellContributions(WellContributions& wellContribs)
const
1529 wellContribs.setBlockSize(StandardWell<TypeTag>::Indices::numEq, StandardWell<TypeTag>::numStaticWellEq);
1531 for(
unsigned int i = 0; i < well_container_.size(); i++){
1532 auto& well = well_container_[i];
1533 std::shared_ptr<StandardWell<TypeTag> > derived = std::dynamic_pointer_cast<StandardWell<TypeTag> >(well);
1535 wellContribs.addNumBlocks(derived->linSys().getNumBlocks());
1540 wellContribs.alloc();
1542 for(
unsigned int i = 0; i < well_container_.size(); i++){
1543 auto& well = well_container_[i];
1545 auto derived_std = std::dynamic_pointer_cast<StandardWell<TypeTag>>(well);
1547 derived_std->linSys().extract(derived_std->numStaticWellEq, wellContribs);
1549 auto derived_ms = std::dynamic_pointer_cast<MultisegmentWell<TypeTag> >(well);
1551 derived_ms->linSys().extract(wellContribs);
1553 OpmLog::warning(
"Warning unknown type of well");
1560 template<
typename TypeTag>
1562 BlackoilWellModel<TypeTag>::
1563 applyScaleAdd(
const Scalar alpha,
const BVector& x, BVector& Ax)
const
1565 if (this->well_container_.empty()) {
1569 if( scaleAddRes_.size() != Ax.size() ) {
1570 scaleAddRes_.resize( Ax.size() );
1575 apply( x, scaleAddRes_ );
1577 Ax.axpy( alpha, scaleAddRes_ );
1580 template<
typename TypeTag>
1582 BlackoilWellModel<TypeTag>::
1583 addWellContributions(SparseMatrixAdapter& jacobian)
const
1585 for (
const auto& well: well_container_ ) {
1586 well->addWellContributions(jacobian);
1590 template<
typename TypeTag>
1592 BlackoilWellModel<TypeTag>::
1593 addWellPressureEquations(PressureMatrix& jacobian,
const BVector& weights,
const bool use_well_weights)
const
1595 int nw = this->numLocalWellsEnd();
1596 int rdofs = local_num_cells_;
1597 for (
int i = 0; i < nw; i++ ){
1598 int wdof = rdofs + i;
1599 jacobian[wdof][wdof] = 1.0;
1602 for (
const auto& well : well_container_ ) {
1603 well->addWellPressureEquations(jacobian, weights, pressureVarIndex, use_well_weights, this->wellState());
1607 template <
typename TypeTag>
1608 void BlackoilWellModel<TypeTag>::
1609 addReservoirSourceTerms(GlobalEqVector& residual,
1610 std::vector<typename SparseMatrixAdapter::MatrixBlock*>& diagMatAddress)
const
1615 for (
const auto& well : well_container_) {
1616 if (!well->isOperableAndSolvable() && !well->wellIsStopped()) {
1619 const auto& cells = well->cells();
1620 const auto& rates = well->connectionRates();
1621 for (
unsigned perfIdx = 0; perfIdx < rates.size(); ++perfIdx) {
1622 unsigned cellIdx = cells[perfIdx];
1623 auto rate = rates[perfIdx];
1625 VectorBlockType res(0.0);
1626 using MatrixBlockType =
typename SparseMatrixAdapter::MatrixBlock;
1627 MatrixBlockType bMat(0.0);
1628 simulator_.model().linearizer().setResAndJacobi(res, bMat, rate);
1629 residual[cellIdx] += res;
1630 *diagMatAddress[cellIdx] += bMat;
1636 template<
typename TypeTag>
1638 BlackoilWellModel<TypeTag>::
1639 addWellPressureEquationsStruct(PressureMatrix& jacobian)
const
1641 int nw = this->numLocalWellsEnd();
1642 int rdofs = local_num_cells_;
1643 for(
int i=0; i < nw; i++){
1644 int wdof = rdofs + i;
1645 jacobian.entry(wdof,wdof) = 1.0;
1647 std::vector<std::vector<int>> wellconnections = getMaxWellConnections();
1648 for(
int i=0; i < nw; i++){
1649 const auto& perfcells = wellconnections[i];
1650 for(
int perfcell : perfcells){
1651 int wdof = rdofs + i;
1652 jacobian.entry(wdof,perfcell) = 0.0;
1653 jacobian.entry(perfcell, wdof) = 0.0;
1659 template<
typename TypeTag>
1661 BlackoilWellModel<TypeTag>::
1662 recoverWellSolutionAndUpdateWellState(
const BVector& x)
1664 DeferredLogger local_deferredLogger;
1665 OPM_BEGIN_PARALLEL_TRY_CATCH();
1667 const auto& summary_state = simulator_.vanguard().summaryState();
1668 for (
auto& well : well_container_) {
1669 well->recoverWellSolutionAndUpdateWellState(summary_state, x, this->wellState(), local_deferredLogger);
1672 OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
1673 "recoverWellSolutionAndUpdateWellState() failed: ",
1674 terminal_output_, simulator_.vanguard().grid().comm());
1678 template<
typename TypeTag>
1680 BlackoilWellModel<TypeTag>::
1681 recoverWellSolutionAndUpdateWellStateDomain(
const BVector& x,
const Domain& domain)
1686 DeferredLogger local_deferredLogger;
1687 const auto& summary_state = this->simulator_.vanguard().summaryState();
1688 for (
auto& well : well_container_) {
1689 if (well_domain_.at(well->name()) == domain.index) {
1690 well->recoverWellSolutionAndUpdateWellState(summary_state, x,
1692 local_deferredLogger);
1697 if (terminal_output_) {
1698 local_deferredLogger.logMessages();
1703 template<
typename TypeTag>
1705 BlackoilWellModel<TypeTag>::
1706 initPrimaryVariablesEvaluation()
const
1708 for (
auto& well : well_container_) {
1709 well->initPrimaryVariablesEvaluation();
1714 template<
typename TypeTag>
1716 BlackoilWellModel<TypeTag>::
1717 initPrimaryVariablesEvaluationDomain(
const Domain& domain)
const
1719 for (
auto& well : well_container_) {
1720 if (well_domain_.at(well->name()) == domain.index) {
1721 well->initPrimaryVariablesEvaluation();
1731 template<
typename TypeTag>
1733 BlackoilWellModel<TypeTag>::
1734 getDomainWellConvergence(
const Domain& domain,
1735 const std::vector<Scalar>& B_avg,
1736 DeferredLogger& local_deferredLogger)
const
1738 const auto& summary_state = simulator_.vanguard().summaryState();
1739 const int iterationIdx = simulator_.model().newtonMethod().numIterations();
1740 const bool relax_tolerance = iterationIdx > param_.strict_outer_iter_wells_;
1742 ConvergenceReport report;
1743 for (
const auto& well : well_container_) {
1744 if ((well_domain_.at(well->name()) == domain.index)) {
1745 if (well->isOperableAndSolvable() || well->wellIsStopped()) {
1746 report += well->getWellConvergence(summary_state,
1749 local_deferredLogger,
1752 ConvergenceReport xreport;
1753 using CR = ConvergenceReport;
1754 xreport.setWellFailed({CR::WellFailure::Type::Unsolvable, CR::Severity::Normal, -1, well->name()});
1761 if (terminal_output_) {
1762 for (
const auto& f : report.wellFailures()) {
1763 if (f.severity() == ConvergenceReport::Severity::NotANumber) {
1764 local_deferredLogger.debug(
"NaN residual found with phase " + std::to_string(f.phase()) +
" for well " + f.wellName());
1765 }
else if (f.severity() == ConvergenceReport::Severity::TooLarge) {
1766 local_deferredLogger.debug(
"Too large residual found with phase " + std::to_string(f.phase()) +
" for well " + f.wellName());
1777 template<
typename TypeTag>
1779 BlackoilWellModel<TypeTag>::
1780 getWellConvergence(
const std::vector<Scalar>& B_avg,
bool checkWellGroupControls)
const
1783 DeferredLogger local_deferredLogger;
1785 ConvergenceReport local_report;
1786 const int iterationIdx = simulator_.model().newtonMethod().numIterations();
1787 for (
const auto& well : well_container_) {
1788 if (well->isOperableAndSolvable() || well->wellIsStopped()) {
1789 const auto& summary_state = simulator_.vanguard().summaryState();
1790 local_report += well->getWellConvergence(
1791 summary_state, this->wellState(), B_avg, local_deferredLogger,
1792 iterationIdx > param_.strict_outer_iter_wells_);
1794 ConvergenceReport report;
1795 using CR = ConvergenceReport;
1796 report.setWellFailed({CR::WellFailure::Type::Unsolvable, CR::Severity::Normal, -1, well->name()});
1797 local_report += report;
1801 const Opm::Parallel::Communication comm = grid().comm();
1806 if (checkWellGroupControls) {
1807 report.setWellGroupTargetsViolated(this->lastReport().well_group_control_changed);
1810 if (terminal_output_) {
1811 global_deferredLogger.logMessages();
1814 if (terminal_output_) {
1815 for (
const auto& f : report.wellFailures()) {
1816 if (f.severity() == ConvergenceReport::Severity::NotANumber) {
1817 OpmLog::debug(
"NaN residual found with phase " + std::to_string(f.phase()) +
" for well " + f.wellName());
1818 }
else if (f.severity() == ConvergenceReport::Severity::TooLarge) {
1819 OpmLog::debug(
"Too large residual found with phase " + std::to_string(f.phase()) +
" for well " + f.wellName());
1830 template<
typename TypeTag>
1836 for (
auto& well : well_container_) {
1845 template<
typename TypeTag>
1846 std::pair<bool, bool>
1850 const int episodeIdx = simulator_.episodeIndex();
1851 const auto& network = schedule()[episodeIdx].network();
1852 if (!wellsActive() && !network.active()) {
1853 return {
false,
false};
1856 const int iterationIdx = simulator_.model().newtonMethod().numIterations();
1857 const auto& comm = simulator_.vanguard().grid().comm();
1858 updateAndCommunicateGroupData(episodeIdx, iterationIdx);
1861 bool more_network_update =
false;
1862 if (shouldBalanceNetwork(episodeIdx, iterationIdx) || mandatory_network_balance) {
1863 const auto local_network_imbalance = updateNetworkPressures(episodeIdx);
1864 const double network_imbalance = comm.max(local_network_imbalance);
1865 const auto& balance = schedule()[episodeIdx].network_balance();
1866 constexpr double relaxtion_factor = 10.0;
1867 const double tolerance = relax_network_tolerance ? relaxtion_factor * balance.pressure_tolerance() : balance.pressure_tolerance();
1868 more_network_update = this->networkActive() && network_imbalance > tolerance;
1871 bool changed_well_group =
false;
1873 const int nupcol = schedule()[episodeIdx].nupcol();
1876 if (iterationIdx <= nupcol) {
1877 const Group& fieldGroup = schedule().getGroup(
"FIELD", episodeIdx);
1878 changed_well_group = updateGroupControls(fieldGroup, deferred_logger, episodeIdx, iterationIdx);
1881 bool changed_well_to_group =
false;
1885 OPM_BEGIN_PARALLEL_TRY_CATCH()
1886 for (const auto& well : well_container_) {
1887 const auto mode = WellInterface<TypeTag>::IndividualOrGroup::Group;
1888 const bool changed_well = well->updateWellControl(simulator_, mode, this->wellState(), this->groupState(), deferred_logger);
1890 changed_well_to_group = changed_well || changed_well_to_group;
1893 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel: updating well controls failed: ",
1894 simulator_.gridView().comm());
1897 changed_well_to_group = comm.sum(
static_cast<int>(changed_well_to_group));
1898 if (changed_well_to_group) {
1899 updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger);
1900 changed_well_group =
true;
1904 bool changed_well_individual =
false;
1908 OPM_BEGIN_PARALLEL_TRY_CATCH()
1909 for (const auto& well : well_container_) {
1910 const auto mode = WellInterface<TypeTag>::IndividualOrGroup::Individual;
1911 const bool changed_well = well->updateWellControl(simulator_, mode, this->wellState(), this->groupState(), deferred_logger);
1913 changed_well_individual = changed_well || changed_well_individual;
1916 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel: updating well controls failed: ",
1917 simulator_.gridView().comm());
1920 changed_well_individual = comm.sum(
static_cast<int>(changed_well_individual));
1921 if (changed_well_individual) {
1922 updateAndCommunicate(episodeIdx, iterationIdx, deferred_logger);
1923 changed_well_group =
true;
1927 const Group& fieldGroup = schedule().getGroup(
"FIELD", episodeIdx);
1928 updateWsolvent(fieldGroup, episodeIdx, this->nupcolWellState());
1930 return { changed_well_group, more_network_update };
1933 template<
typename TypeTag>
1935 BlackoilWellModel<TypeTag>::
1936 updateWellControlsDomain(DeferredLogger& deferred_logger,
const Domain& domain)
1938 if ( !wellsActive() ) return ;
1944 for (
const auto& well : well_container_) {
1945 if (well_domain_.at(well->name()) == domain.index) {
1946 const auto mode = WellInterface<TypeTag>::IndividualOrGroup::Individual;
1947 well->updateWellControl(simulator_, mode, this->wellState(), this->groupState(), deferred_logger);
1956 template <
typename TypeTag>
1958 BlackoilWellModel<TypeTag>::
1959 initializeWBPCalculationService()
1961 this->wbpCalcMap_.clear();
1962 this->wbpCalcMap_.resize(this->wells_ecl_.size());
1964 this->registerOpenWellsForWBPCalculation();
1966 auto wellID = std::size_t{0};
1967 for (
const auto& well : this->wells_ecl_) {
1968 this->wbpCalcMap_[wellID].wbpCalcIdx_ = this->wbpCalculationService_
1969 .createCalculator(well,
1970 this->local_parallel_well_info_[wellID],
1971 this->conn_idx_map_[wellID].local(),
1972 this->makeWellSourceEvaluatorFactory(wellID));
1977 this->wbpCalculationService_.defineCommunication();
1984 template <
typename TypeTag>
1985 data::WellBlockAveragePressures
1986 BlackoilWellModel<TypeTag>::
1987 computeWellBlockAveragePressures()
const
1989 auto wbpResult = data::WellBlockAveragePressures{};
1991 using Calculated = PAvgCalculator::Result::WBPMode;
1992 using Output = data::WellBlockAvgPress::Quantity;
1994 this->wbpCalculationService_.collectDynamicValues();
1996 const auto numWells = this->wells_ecl_.size();
1997 for (
auto wellID = 0*numWells; wellID < numWells; ++wellID) {
1998 const auto calcIdx = this->wbpCalcMap_[wellID].wbpCalcIdx_;
1999 const auto& well = this->wells_ecl_[wellID];
2001 if (! well.hasRefDepth()) {
2007 this->wbpCalculationService_
2008 .inferBlockAveragePressures(calcIdx, well.pavg(),
2010 well.getWPaveRefDepth());
2012 const auto& result = this->wbpCalculationService_
2013 .averagePressures(calcIdx);
2015 auto& reported = wbpResult.values[well.name()];
2017 reported[Output::WBP] = result.value(Calculated::WBP);
2018 reported[Output::WBP4] = result.value(Calculated::WBP4);
2019 reported[Output::WBP5] = result.value(Calculated::WBP5);
2020 reported[Output::WBP9] = result.value(Calculated::WBP9);
2030 template <
typename TypeTag>
2031 ParallelWBPCalculation::EvaluatorFactory
2032 BlackoilWellModel<TypeTag>::
2033 makeWellSourceEvaluatorFactory(
const std::vector<Well>::size_type wellIdx)
const
2035 using Span = PAvgDynamicSourceData::SourceDataSpan<double>;
2036 using Item =
typename Span::Item;
2038 return [wellIdx,
this]() -> ParallelWBPCalculation::Evaluator
2040 if (! this->wbpCalcMap_[wellIdx].openWellIdx_.has_value()) {
2042 return []([[maybe_unused]]
const int connIdx, Span sourceTerm)
2048 .set(Item::Pressure , 0.0)
2049 .set(Item::PoreVol , 0.0)
2050 .set(Item::MixtureDensity, 0.0);
2055 return [
this, wellPtr = this->well_container_[*this->wbpCalcMap_[wellIdx].openWellIdx_].get()]
2056 (
const int connIdx, Span sourceTerm)
2062 const auto& connIdxMap =
2063 this->conn_idx_map_[wellPtr->indexOfWell()];
2065 const auto rho = wellPtr->
2066 connectionDensity(connIdxMap.global(connIdx),
2067 connIdxMap.open(connIdx));
2070 .set(Item::Pressure , 0.0)
2071 .set(Item::PoreVol , 0.0)
2072 .set(Item::MixtureDensity, rho);
2081 template <
typename TypeTag>
2083 BlackoilWellModel<TypeTag>::
2084 registerOpenWellsForWBPCalculation()
2086 assert (this->wbpCalcMap_.size() == this->wells_ecl_.size());
2088 for (
auto& wbpCalc : this->wbpCalcMap_) {
2089 wbpCalc.openWellIdx_.reset();
2092 auto openWellIdx =
typename std::vector<WellInterfacePtr>::size_type{0};
2093 for (
const auto* openWell : this->well_container_generic_) {
2094 this->wbpCalcMap_[openWell->indexOfWell()].openWellIdx_ = openWellIdx++;
2102 template<
typename TypeTag>
2104 BlackoilWellModel<TypeTag>::
2105 updateAndCommunicate(
const int reportStepIdx,
2106 const int iterationIdx,
2107 DeferredLogger& deferred_logger)
2109 updateAndCommunicateGroupData(reportStepIdx, iterationIdx);
2113 OPM_BEGIN_PARALLEL_TRY_CATCH()
2115 for (const auto& well : well_container_) {
2116 well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), deferred_logger);
2118 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel::updateAndCommunicate failed: ",
2119 simulator_.gridView().comm())
2120 updateAndCommunicateGroupData(reportStepIdx, iterationIdx);
2123 template<typename TypeTag>
2125 BlackoilWellModel<TypeTag>::
2126 updateGroupControls(const Group& group,
2127 DeferredLogger& deferred_logger,
2128 const
int reportStepIdx,
2129 const
int iterationIdx)
2131 bool changed =
false;
2132 bool changed_hc = checkGroupHigherConstraints( group, deferred_logger, reportStepIdx);
2135 updateAndCommunicate(reportStepIdx, iterationIdx, deferred_logger);
2138 bool changed_individual =
2139 BlackoilWellModelConstraints(*this).
2140 updateGroupIndividualControl(group,
2142 this->switched_inj_groups_,
2143 this->switched_prod_groups_,
2144 this->closed_offending_wells_,
2149 if (changed_individual) {
2151 updateAndCommunicate(reportStepIdx, iterationIdx, deferred_logger);
2154 for (
const std::string& groupName : group.groups()) {
2155 bool changed_this = updateGroupControls( schedule().getGroup(groupName, reportStepIdx), deferred_logger, reportStepIdx,iterationIdx);
2156 changed = changed || changed_this;
2161 template<
typename TypeTag>
2167 for (
const auto& well : well_container_) {
2168 const auto& wname = well->name();
2169 const auto wasClosed = wellTestState.well_is_closed(wname);
2170 well->checkWellOperability(simulator_, this->wellState(), local_deferredLogger);
2171 well->updateWellTestState(this->wellState().well(wname), simulationTime,
true, wellTestState, local_deferredLogger);
2173 if (!wasClosed && wellTestState.well_is_closed(wname)) {
2174 this->closed_this_step_.insert(wname);
2178 const Opm::Parallel::Communication comm = grid().comm();
2181 for (
const auto& [group_name, to] : closed_offending_wells_) {
2182 if (!this->wasDynamicallyShutThisTimeStep(to.second)) {
2183 wellTestState.close_well(
2184 to.second, WellTestConfig::Reason::GROUP, simulationTime);
2185 this->updateClosedWellsThisStep(to.second);
2186 std::string msg = fmt::format(
"Procedure on exceeding {} limit is WELL for group {}. Well {} is {}.",
2191 global_deferredLogger.info(msg);
2195 if (terminal_output_) {
2206 template<
typename TypeTag>
2210 std::string& exc_msg,
2211 ExceptionType::ExcEnum& exc_type,
2214 const int np = numPhases();
2215 std::vector<double> potentials;
2216 const auto& well = well_container_[widx];
2217 std::string cur_exc_msg;
2218 auto cur_exc_type = ExceptionType::NONE;
2220 well->computeWellPotentials(simulator_, well_state_copy, potentials, deferred_logger);
2223 OPM_PARALLEL_CATCH_CLAUSE(cur_exc_type, cur_exc_msg);
2224 if (cur_exc_type != ExceptionType::NONE) {
2225 exc_msg += fmt::format(
"\nFor well {}: {}", well->name(), cur_exc_msg);
2227 exc_type = std::max(exc_type, cur_exc_type);
2231 auto& ws = this->wellState().well(well->indexOfWell());
2232 for (
int p = 0; p < np; ++p) {
2234 ws.well_potentials[p] = std::max(0.0, potentials[p]);
2240 template <
typename TypeTag>
2242 BlackoilWellModel<TypeTag>::
2243 calculateProductivityIndexValues(DeferredLogger& deferred_logger)
2245 for (
const auto& wellPtr : this->well_container_) {
2246 this->calculateProductivityIndexValues(wellPtr.get(), deferred_logger);
2254 template <
typename TypeTag>
2256 BlackoilWellModel<TypeTag>::
2257 calculateProductivityIndexValuesShutWells(
const int reportStepIdx,
2258 DeferredLogger& deferred_logger)
2265 for (
const auto& shutWell : this->local_shut_wells_) {
2266 if (!this->wells_ecl_[shutWell].hasConnections()) {
2271 auto wellPtr = this->
template createTypedWellPointer
2272 <StandardWell<TypeTag>>(shutWell, reportStepIdx);
2274 wellPtr->init(&this->phase_usage_, this->depth_, this->gravity_,
2275 this->local_num_cells_, this->B_avg_,
true);
2277 this->calculateProductivityIndexValues(wellPtr.get(), deferred_logger);
2285 template <
typename TypeTag>
2287 BlackoilWellModel<TypeTag>::
2288 calculateProductivityIndexValues(
const WellInterface<TypeTag>* wellPtr,
2289 DeferredLogger& deferred_logger)
2291 wellPtr->updateProductivityIndex(this->simulator_,
2292 this->prod_index_calc_[wellPtr->indexOfWell()],
2299 template<
typename TypeTag>
2301 BlackoilWellModel<TypeTag>::
2302 prepareTimeStep(DeferredLogger& deferred_logger)
2305 const auto episodeIdx = simulator_.episodeIndex();
2306 this->updateNetworkActiveState(episodeIdx);
2310 const bool do_prestep_network_rebalance = this->needPreStepNetworkRebalance(episodeIdx);
2312 for (
const auto& well : well_container_) {
2313 auto& events = this->wellState().well(well->indexOfWell()).events;
2314 if (events.hasEvent(WellState::event_mask)) {
2315 well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), deferred_logger);
2316 const auto& summary_state = simulator_.vanguard().summaryState();
2317 well->updatePrimaryVariables(summary_state, this->wellState(), deferred_logger);
2318 well->initPrimaryVariablesEvaluation();
2321 events.clearEvent(WellState::event_mask);
2324 if (events.hasEvent(ScheduleEvents::REQUEST_OPEN_WELL)) {
2325 events.clearEvent(ScheduleEvents::REQUEST_OPEN_WELL);
2328 if (param_.solve_welleq_initially_ && well->isOperableAndSolvable()) {
2330 well->solveWellEquation(simulator_, this->wellState(), this->groupState(), deferred_logger);
2331 }
catch (
const std::exception& e) {
2332 const std::string msg =
"Compute initial well solution for " + well->name() +
" initially failed. Continue with the previous rates";
2333 deferred_logger.warning(
"WELL_INITIAL_SOLVE_FAILED", msg);
2338 well->resetWellOperability();
2340 updatePrimaryVariables(deferred_logger);
2343 if (do_prestep_network_rebalance) doPreStepNetworkRebalance(deferred_logger);
2346 template<
typename TypeTag>
2348 BlackoilWellModel<TypeTag>::
2349 updateAverageFormationFactor()
2351 std::vector< Scalar > B_avg(numComponents(), Scalar() );
2352 const auto& grid = simulator_.vanguard().grid();
2353 const auto& gridView = grid.leafGridView();
2354 ElementContext elemCtx(simulator_);
2356 OPM_BEGIN_PARALLEL_TRY_CATCH();
2357 for (
const auto& elem : elements(gridView, Dune::Partitions::interior)) {
2358 elemCtx.updatePrimaryStencil(elem);
2359 elemCtx.updatePrimaryIntensiveQuantities(0);
2361 const auto& intQuants = elemCtx.intensiveQuantities(0, 0);
2362 const auto& fs = intQuants.fluidState();
2364 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx)
2366 if (!FluidSystem::phaseIsActive(phaseIdx)) {
2370 const unsigned compIdx = Indices::canonicalToActiveComponentIndex(FluidSystem::solventComponentIndex(phaseIdx));
2371 auto& B = B_avg[ compIdx ];
2373 B += 1 / fs.invB(phaseIdx).value();
2375 if constexpr (has_solvent_) {
2376 auto& B = B_avg[solventSaturationIdx];
2377 B += 1 / intQuants.solventInverseFormationVolumeFactor().value();
2380 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel::updateAverageFormationFactor() failed: ", grid.comm())
2383 grid.comm().sum(B_avg.data(), B_avg.size());
2384 for (auto& bval : B_avg)
2386 bval /= global_num_cells_;
2395 template<
typename TypeTag>
2397 BlackoilWellModel<TypeTag>::
2398 updatePrimaryVariables(DeferredLogger& deferred_logger)
2400 for (
const auto& well : well_container_) {
2401 const auto& summary_state = simulator_.vanguard().summaryState();
2402 well->updatePrimaryVariables(summary_state, this->wellState(), deferred_logger);
2406 template<
typename TypeTag>
2408 BlackoilWellModel<TypeTag>::extractLegacyCellPvtRegionIndex_()
2410 const auto& grid = simulator_.vanguard().grid();
2411 const auto& eclProblem = simulator_.problem();
2412 const unsigned numCells = grid.size(0);
2414 pvt_region_idx_.resize(numCells);
2415 for (
unsigned cellIdx = 0; cellIdx < numCells; ++cellIdx) {
2416 pvt_region_idx_[cellIdx] =
2417 eclProblem.pvtRegionIndex(cellIdx);
2422 template<
typename TypeTag>
2424 BlackoilWellModel<TypeTag>::numComponents()
const
2432 int numComp = numPhases() < 3? numPhases(): FluidSystem::numComponents;
2433 if constexpr (has_solvent_) {
2439 template<
typename TypeTag>
2441 BlackoilWellModel<TypeTag>::extractLegacyDepth_()
2443 const auto& eclProblem = simulator_.problem();
2444 depth_.resize(local_num_cells_);
2445 for (
unsigned cellIdx = 0; cellIdx < local_num_cells_; ++cellIdx) {
2446 depth_[cellIdx] = eclProblem.dofCenterDepth(cellIdx);
2450 template<
typename TypeTag>
2451 typename BlackoilWellModel<TypeTag>::WellInterfacePtr
2452 BlackoilWellModel<TypeTag>::
2453 getWell(
const std::string& well_name)
const
2456 auto well = std::find_if(well_container_.begin(),
2457 well_container_.end(),
2458 [&well_name](
const WellInterfacePtr& elem)->bool {
2459 return elem->name() == well_name;
2462 assert(well != well_container_.end());
2467 template<
typename TypeTag>
2469 BlackoilWellModel<TypeTag>::
2470 hasWell(
const std::string& well_name)
const
2472 return std::any_of(well_container_.begin(), well_container_.end(),
2473 [&well_name](
const WellInterfacePtr& elem) ->
bool
2475 return elem->name() == well_name;
2482 template <
typename TypeTag>
2484 BlackoilWellModel<TypeTag>::
2485 reportStepIndex()
const
2487 return std::max(this->simulator_.episodeIndex(), 0);
2494 template<
typename TypeTag>
2496 BlackoilWellModel<TypeTag>::
2497 calcRates(
const int fipnum,
2499 const std::vector<double>& production_rates,
2500 std::vector<double>& resv_coeff)
2502 rateConverter_->calcCoeff(fipnum, pvtreg, production_rates, resv_coeff);
2505 template<
typename TypeTag>
2507 BlackoilWellModel<TypeTag>::
2508 calcInjRates(
const int fipnum,
2510 std::vector<double>& resv_coeff)
2512 rateConverter_->calcInjCoeff(fipnum, pvtreg, resv_coeff);
2516 template <
typename TypeTag>
2518 BlackoilWellModel<TypeTag>::
2519 computeWellTemperature()
2524 int np = numPhases();
2525 double cellInternalEnergy;
2528 double perfPhaseRate;
2529 const int nw = numLocalWells();
2530 for (
auto wellID = 0*nw; wellID < nw; ++wellID) {
2531 const Well& well = wells_ecl_[wellID];
2532 if (well.isInjector())
2535 std::array<double,2> weighted{0.0,0.0};
2536 auto& [weighted_temperature, total_weight] = weighted;
2538 auto& well_info = local_parallel_well_info_[wellID].get();
2539 auto& ws = this->wellState().well(wellID);
2540 auto& perf_data = ws.perf_data;
2541 auto& perf_phase_rate = perf_data.phase_rates;
2543 using int_type =
decltype(well_perf_data_[wellID].size());
2544 for (int_type perf = 0, end_perf = well_perf_data_[wellID].size(); perf < end_perf; ++perf) {
2545 const int cell_idx = well_perf_data_[wellID][perf].cell_index;
2546 const auto& intQuants = simulator_.model().intensiveQuantities(cell_idx, 0);
2547 const auto& fs = intQuants.fluidState();
2550 double cellTemperatures = fs.temperature(0).value();
2552 double weight_factor = 0.0;
2553 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx)
2555 if (!FluidSystem::phaseIsActive(phaseIdx)) {
2558 cellInternalEnergy = fs.enthalpy(phaseIdx).value() - fs.pressure(phaseIdx).value() / fs.density(phaseIdx).value();
2559 cellBinv = fs.invB(phaseIdx).value();
2560 cellDensity = fs.density(phaseIdx).value();
2561 perfPhaseRate = perf_phase_rate[ perf*np + phaseIdx ];
2562 weight_factor += cellDensity * perfPhaseRate/cellBinv * cellInternalEnergy/cellTemperatures;
2564 total_weight += weight_factor;
2565 weighted_temperature += weight_factor * cellTemperatures;
2567 well_info.communication().sum(weighted.data(), 2);
2568 this->wellState().well(wellID).temperature = weighted_temperature/total_weight;
2573 template <
typename TypeTag>
2575 BlackoilWellModel<TypeTag>::
2576 logPrimaryVars()
const
2578 std::ostringstream os;
2579 for (
const auto& w : well_container_) {
2580 os << w->name() <<
":";
2581 auto pv = w->getPrimaryVars();
2582 for (
const double v : pv) {
2587 OpmLog::debug(os.str());
2592 template <
typename TypeTag>
2594 BlackoilWellModel<TypeTag>::
2595 getPrimaryVarsDomain(
const Domain& domain)
const
2597 std::vector<double> ret;
2598 for (
const auto& well : well_container_) {
2599 if (well_domain_.at(well->name()) == domain.index) {
2600 const auto& pv = well->getPrimaryVars();
2601 ret.insert(ret.end(), pv.begin(), pv.end());
2609 template <
typename TypeTag>
2611 BlackoilWellModel<TypeTag>::
2612 setPrimaryVarsDomain(
const Domain& domain,
const std::vector<double>& vars)
2614 std::size_t offset = 0;
2615 for (
auto& well : well_container_) {
2616 if (well_domain_.at(well->name()) == domain.index) {
2617 int num_pri_vars = well->setPrimaryVars(vars.begin() + offset);
2618 offset += num_pri_vars;
2621 assert(offset == vars.size());
2626 template <
typename TypeTag>
2628 BlackoilWellModel<TypeTag>::
2629 setupDomains(
const std::vector<Domain>& domains)
2631 OPM_BEGIN_PARALLEL_TRY_CATCH();
2636 for (
const auto& wellPtr : this->well_container_) {
2637 const int first_well_cell = wellPtr->cells().front();
2638 for (
const auto& domain : domains) {
2639 auto cell_present = [&domain](
const auto cell)
2641 return std::binary_search(domain.cells.begin(),
2642 domain.cells.end(), cell);
2645 if (cell_present(first_well_cell)) {
2648 well_domain_[wellPtr->name()] = domain.index;
2651 for (
int well_cell : wellPtr->cells()) {
2652 if (! cell_present(well_cell)) {
2653 OPM_THROW(std::runtime_error,
2654 fmt::format(
"Well '{}' found on multiple domains.",
2661 OPM_END_PARALLEL_TRY_CATCH(
"BlackoilWellModel::setupDomains(): well found on multiple domains.",
2662 simulator_.gridView().comm());
2665 const Opm::Parallel::Communication& comm = grid().comm();
2666 const int rank = comm.rank();
2667 DeferredLogger local_log;
2668 if (!well_domain_.empty()) {
2669 std::ostringstream os;
2670 os <<
"Well name Rank Domain\n";
2671 for (
const auto& [wname, domain] : well_domain_) {
2672 os << wname << std::setw(19 - wname.size()) << rank << std::setw(12) << domain <<
'\n';
2674 local_log.debug(os.str());
2677 if (terminal_output_) {
2678 global_log.logMessages();
Class for handling the blackoil well model.
Definition BlackoilWellModel.hpp:96
void calculateExplicitQuantities(DeferredLogger &deferred_logger) const
Calculating the explict quantities used in the well calculation.
Definition BlackoilWellModel_impl.hpp:1833
Definition DeferredLogger.hpp:57
void logMessages()
Log all messages to the OpmLog backends, and clear the message container.
Definition DeferredLogger.cpp:85
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition WellState.hpp:61
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition BlackoilPhases.hpp:27
Opm::DeferredLogger gatherDeferredLogger(const Opm::DeferredLogger &local_deferredlogger, Opm::Parallel::Communication)
Create a global log combining local logs.
Definition gatherDeferredLogger.cpp:168
ConvergenceReport gatherConvergenceReport(const ConvergenceReport &local_report, Parallel::Communication mpi_communicator)
Create a global convergence report combining local (per-process) reports.
Definition gatherConvergenceReport.cpp:249
PhaseUsage phaseUsageFromDeck(const EclipseState &eclipseState)
Looks at presence of WATER, OIL and GAS keywords in state object to determine active phases.
Definition phaseUsageFromDeck.cpp:137