20#ifndef OPM_BLACKOILWELLMODEL_RESCOUP_IMPL_HEADER_INCLUDED
21#define OPM_BLACKOILWELLMODEL_RESCOUP_IMPL_HEADER_INCLUDED
24#ifndef OPM_BLACKOILWELLMODEL_RESCOUP_HEADER_INCLUDED
29#ifdef RESERVOIR_COUPLING_ENABLED
31#include <opm/common/TimingMacros.hpp>
33#include <opm/input/eclipse/EclipseState/Grid/RegionSetMatcher.hpp>
34#include <opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.hpp>
35#include <opm/input/eclipse/Schedule/Schedule.hpp>
36#include <opm/input/eclipse/Schedule/SummaryState.hpp>
37#include <opm/input/eclipse/Schedule/UDQ/UDQConfig.hpp>
38#include <opm/input/eclipse/Schedule/UDQ/UDQDefine.hpp>
39#include <opm/input/eclipse/Schedule/UDQ/UDQEnums.hpp>
40#include <opm/input/eclipse/Schedule/Well/WellMatcher.hpp>
41#include <opm/input/eclipse/Units/UnitSystem.hpp>
63template<
typename TypeTag>
64BlackoilWellModelRescoup<TypeTag>::
65BlackoilWellModelRescoup(BlackoilWellModel<TypeTag>& well_model)
66 : well_model_{well_model}
67 , network_{well_model.network()}
68 , simulator_{well_model.simulator()}
69 , param_{well_model.param()}
75template<
typename TypeTag>
77BlackoilWellModelRescoup<TypeTag>::
78evalGroupAndFieldUDQs()
80 const int reportStepIdx = this->groupStateHelper().reportStepIdx();
81 auto& deferred_logger = this->groupStateHelper().deferredLogger();
90 const auto select = [](
const UDQDefine& def) {
91 const auto var_type = def.var_type();
92 return ((var_type == UDQVarType::GROUP_VAR) || (var_type == UDQVarType::FIELD_VAR))
93 && (def.status().first != UDQUpdate::NEXT);
95 const auto& schedule = this->schedule();
98 schedule[reportStepIdx].udq().eval(
100 schedule.wellMatcher(reportStepIdx),
101 schedule[reportStepIdx].group_order(),
102 schedule.segmentMatcherFactory(reportStepIdx),
103 [es = std::cref(this->simulator_.vanguard().eclState())]() {
104 return std::make_unique<RegionSetMatcher>(es.get().fipRegionStatistics());
106 this->simulator_.vanguard().summaryState(),
107 this->simulator_.vanguard().udqState(),
111 "Failed to evaluate UDQs for reservoir coupling slave: ",
112 this->well_model_.terminalOutput(),
113 this->simulator_.vanguard().grid().comm())
116template<
typename TypeTag>
118BlackoilWellModelRescoup<TypeTag>::
119masterIsInCoupledNetworkIteration()
const
121 return this->isReservoirCouplingMaster()
122 && this->reservoirCouplingMaster().isFirstSubstepOfSyncTimestep()
123 && this->masterNetworkHasMasterGroupLeaves()
124 && !this->lastSentMasterGroupNodePressuresIsFinal();
128template<
typename TypeTag>
130BlackoilWellModelRescoup<TypeTag>::
131masterNetworkHasMasterGroupLeaves()
const
136 if (!this->isReservoirCouplingMaster())
return false;
137 const auto& rcm = this->reservoirCouplingMaster();
138 const auto num_slaves = rcm.numSlaves();
139 for (std::size_t s = 0; s < num_slaves; ++s) {
140 if (!rcm.slaveIsCoupled(s))
continue;
141 if (this->masterNetworkHasMasterGroupLeavesForSlave_(s)) {
148template<
typename TypeTag>
150BlackoilWellModelRescoup<TypeTag>::
151maybeExchangeNetworkOuterIterationWithSlaves(
bool more_network_update)
153 if (!this->masterIsInCoupledNetworkIteration()) {
156 const bool is_final = !more_network_update;
165 if (is_final || !this->well_model_.useTightRcNetworkCoupling()) {
167 this->sendMasterGroupNodePressuresToSlaves(is_final);
170 this->receiveSlaveGroupData();
171 this->refreshAndSendInjectionTargets_();
176template<
typename TypeTag>
178BlackoilWellModelRescoup<TypeTag>::
179maybeExchangeNetworkSubIterationWithSlaves()
199 if (!this->well_model_.useTightRcNetworkCoupling()) {
202 if (!this->masterIsInCoupledNetworkIteration()) {
205 this->sendMasterGroupNodePressuresToSlaves(
false);
206 this->receiveSlaveGroupData();
207 this->refreshAndSendInjectionTargets_();
210template<
typename TypeTag>
212BlackoilWellModelRescoup<TypeTag>::
213receiveCoupledNetworkActiveStatus()
216 assert(this->isReservoirCouplingSlave());
217 this->reservoirCouplingSlave().receiveCoupledNetworkActiveStatusFromMaster();
220template<
typename TypeTag>
222BlackoilWellModelRescoup<TypeTag>::
223receiveGroupConstraintsFromMaster()
226 RescoupReceiveGroupConstraints<Scalar, IndexTraits> constraint_receiver{
227 this->well_model_.guideRateHandler(),
228 this->groupStateHelper()
230 constraint_receiver.receiveGroupConstraintsFromMaster();
233template<
typename TypeTag>
235BlackoilWellModelRescoup<TypeTag>::
236receiveMasterGroupNodePressuresFromMaster()
239 assert(this->isReservoirCouplingSlave());
240 auto& rescoup_slave = this->reservoirCouplingSlave();
241 const auto [num_pressures, _is_final] =
242 rescoup_slave.receiveNumMasterGroupNodePressuresFromMaster();
243 if (num_pressures > 0) {
244 rescoup_slave.receiveMasterGroupNodePressuresFromMaster(num_pressures);
277 const auto& pressures = rescoup_slave.masterGroupNodePressures();
278 if (pressures.empty())
return;
279 const auto& summary_state = this->well_model_.summaryState();
280 auto& well_state = this->wellState();
281 for (
auto& well : this->wellContainer()) {
282 if (!well->isProducer() || !well->wellEcl().predictionMode())
continue;
283 const auto& group_name = well->wellEcl().groupName();
284 const auto it = pressures.find(group_name);
285 if (it == pressures.end())
continue;
286 if (!this->slaveGroupIsFixedPressureNodeInOwnNetwork_(group_name))
continue;
287 well->setDynamicThpLimit(it->second);
288 auto& ws = well_state[well->indexOfWell()];
289 if (ws.production_cmode == Well::ProducerCMode::THP) {
290 ws.thp = well->getTHPConstraint(summary_state);
295template<
typename TypeTag>
297BlackoilWellModelRescoup<TypeTag>::
298receiveSlaveGroupData()
301 assert(this->isReservoirCouplingMaster());
302 RescoupReceiveSlaveGroupData<Scalar, IndexTraits> slave_group_data_receiver{
303 this->groupStateHelper(),
305 slave_group_data_receiver.receiveSlaveGroupData();
308template<
typename TypeTag>
310BlackoilWellModelRescoup<TypeTag>::
311refreshSlaveGroupInjectionTargets()
318 this->storeSlaveGroupInjectionTargets();
319 this->evalGroupAndFieldUDQs();
320 this->storeSlaveGroupInjectionTargets();
323template<
typename TypeTag>
325BlackoilWellModelRescoup<TypeTag>::
326rescoupSyncSummaryData()
338 if (this->isReservoirCouplingMaster()) {
339 if (this->reservoirCouplingMaster().needsSlaveDataReceive()) {
340 this->receiveSlaveGroupData();
341 this->reservoirCouplingMaster().setNeedsSlaveDataReceive(
false);
344 if (this->isReservoirCouplingSlave()) {
345 if (this->reservoirCouplingSlave().isLastSubstepOfSyncTimestep()) {
346 this->sendSlaveGroupDataToMaster();
351template<
typename TypeTag>
353BlackoilWellModelRescoup<TypeTag>::
354sendCoupledNetworkActiveStatus()
357 assert(this->isReservoirCouplingMaster());
366 auto& rescoup_master = this->reservoirCouplingMaster();
367 const auto num_slaves = rescoup_master.numSlaves();
368 bool any_connected =
false;
369 for (std::size_t slave_idx = 0; slave_idx < num_slaves; ++slave_idx) {
370 if (rescoup_master.slaveIsCoupled(slave_idx)) {
371 const bool connected =
372 this->masterNetworkHasMasterGroupLeavesForSlave_(slave_idx);
373 any_connected = any_connected || connected;
374 rescoup_master.sendCoupledNetworkActiveStatusToSlave(slave_idx, connected);
381 this->last_sent_master_group_node_pressures_is_final_ = !any_connected;
384template<
typename TypeTag>
386BlackoilWellModelRescoup<TypeTag>::
387sendMasterGroupConstraintsToSlaves()
393 RescoupConstraintsCalculator<Scalar, IndexTraits> constraints_calculator{
394 this->well_model_.guideRateHandler(),
395 this->groupStateHelper()
397 constraints_calculator.calculateMasterGroupConstraintsAndSendToSlaves();
400template<
typename TypeTag>
402BlackoilWellModelRescoup<TypeTag>::
403sendMasterGroupNodePressuresToSlaves(
bool is_final)
406 assert(this->isReservoirCouplingMaster());
407 auto& rescoup_master = this->reservoirCouplingMaster();
408 const auto& node_pressures = this->network_.nodePressures();
409 const auto num_slaves = rescoup_master.numSlaves();
410 for (std::size_t slave_idx = 0; slave_idx < num_slaves; ++slave_idx) {
411 if (!rescoup_master.slaveIsCoupled(slave_idx))
continue;
412 std::vector<typename ReservoirCoupling::MasterGroupNodePressure<Scalar>> pressures;
413 const auto& master_groups = rescoup_master.getMasterGroupNamesForSlave(slave_idx);
414 for (std::size_t i = 0; i < master_groups.size(); ++i) {
415 const auto it = node_pressures.find(master_groups[i]);
416 if (it != node_pressures.end()) {
417 pressures.push_back({i, it->second});
420 rescoup_master.sendNumMasterGroupNodePressuresToSlave(
421 slave_idx, pressures.size(), is_final);
422 if (!pressures.empty()) {
423 rescoup_master.sendMasterGroupNodePressuresToSlave(slave_idx, pressures);
426 this->last_sent_master_group_node_pressures_is_final_ = is_final;
429template<
typename TypeTag>
431BlackoilWellModelRescoup<TypeTag>::
432sendSlaveGroupDataToMaster()
435 assert(this->isReservoirCouplingSlave());
436 RescoupSendSlaveGroupData<Scalar, IndexTraits> slave_group_data_sender{
437 this->groupStateHelper()};
438 slave_group_data_sender.sendSlaveGroupDataToMaster();
450template<
typename TypeTag>
451std::optional<ReservoirCoupling::ScopedLoggerGuard>
452BlackoilWellModelRescoup<TypeTag>::
453setupScopedLogger(DeferredLogger& local_logger)
455 if (this->isReservoirCouplingMaster()) {
456 return ReservoirCoupling::ScopedLoggerGuard{
457 this->reservoirCouplingMaster().logger(),
460 }
else if (this->isReservoirCouplingSlave()) {
461 return ReservoirCoupling::ScopedLoggerGuard{
462 this->reservoirCouplingSlave().logger(),
469template<
typename TypeTag>
471BlackoilWellModelRescoup<TypeTag>::
472storeSlaveGroupInjectionTargets()
474 const int reportStepIdx = this->groupStateHelper().reportStepIdx();
490 using M = UnitSystem::measure;
491 auto& summary_state = this->simulator_.vanguard().summaryState();
492 const auto& units = this->simulator_.vanguard().eclState().getUnits();
493 auto& slave = this->reservoirCouplingSlave();
494 const auto& rescoup = this->schedule()[reportStepIdx].rescoup();
504 const auto targets = std::array {
505 std::tuple { Phase::GAS, std::string{
"GGIRT"}, M::gas_surface_rate },
506 std::tuple { Phase::WATER, std::string{
"GWIRT"}, M::liquid_surface_rate },
508 auto& in_force = slave.effectiveInjectionTargets();
510 for (std::size_t i = 0; i < slave.numSlaveGroups(); ++i) {
511 const auto& gname = slave.slaveGroupIdxToGroupName(i);
512 for (
const auto& [phase, keyword, unit] : targets) {
513 const auto effective = this->effectiveSlaveGroupInjectionTarget_(
514 gname, phase, reportStepIdx, rescoup, summary_state);
515 if (effective.has_value()) {
516 in_force[gname][phase] = *effective;
517 summary_state.update_group_var(gname, keyword, units.from_si(unit, *effective));
520 summary_state.update_group_var(
522 units.from_si(unit, this->scheduleInjectionTarget_(gname, phase, reportStepIdx, summary_state)));
531template<
typename TypeTag>
532std::optional<typename BlackoilWellModelRescoup<TypeTag>::Scalar>
533BlackoilWellModelRescoup<TypeTag>::
534effectiveSlaveGroupInjectionTarget_(
const std::string& gname,
536 const int reportStepIdx,
537 const ReservoirCoupling::CouplingInfo& rescoup,
538 const SummaryState& summary_state)
const
540 using FilterFlag = ReservoirCoupling::GrupSlav::FilterFlag;
541 const auto& slave = this->reservoirCouplingSlave();
542 if (! slave.hasMasterInjectionTarget(gname, phase)) {
545 const auto [master_target, cmode] = slave.masterInjectionTarget(gname, phase);
546 if (cmode != Group::InjectionCMode::RATE) {
552 auto filter = FilterFlag::MAST;
553 if (rescoup.hasGrupSlav(gname)) {
554 const auto& grup_slav = rescoup.grupSlav(gname);
555 filter = (phase == Phase::GAS) ? grup_slav.gasInjFlag()
556 : (phase == Phase::WATER) ? grup_slav.waterInjFlag()
557 : grup_slav.oilInjFlag();
559 if (filter == FilterFlag::SLAV) {
564 if (filter == FilterFlag::BOTH) {
565 const auto& group = this->schedule().getGroup(gname, reportStepIdx);
566 if (group.hasInjectionControl(phase)) {
567 return std::min(master_target,
568 this->scheduleInjectionTarget_(gname, phase, reportStepIdx, summary_state));
571 return master_target;
574template<
typename TypeTag>
576BlackoilWellModelRescoup<TypeTag>::
577masterNetworkHasMasterGroupLeavesForSlave_(std::size_t slave_idx)
const
581 if (!this->isReservoirCouplingMaster())
return false;
582 const int episodeIdx = this->simulator_.episodeIndex();
583 const auto& network = this->schedule()[episodeIdx].network();
584 if (!network.active())
return false;
585 const auto& rcm = this->reservoirCouplingMaster();
586 for (
const auto& mg : rcm.getMasterGroupNamesForSlave(slave_idx)) {
587 if (network.has_node(mg)) {
594template<
typename TypeTag>
596BlackoilWellModelRescoup<TypeTag>::
597refreshAndSendInjectionTargets_()
606 const int report_step_idx = this->well_model_.simulator().episodeIndex();
607 this->well_model_.updateAndCommunicateGroupData(
608 report_step_idx,
false);
609 this->sendMasterGroupInjectionTargetsToSlaves_();
612template<
typename TypeTag>
613typename BlackoilWellModelRescoup<TypeTag>::Scalar
614BlackoilWellModelRescoup<TypeTag>::
615scheduleInjectionTarget_(
const std::string& gname,
617 const int reportStepIdx,
618 const SummaryState& summary_state)
const
620 const auto& group = this->schedule().getGroup(gname, reportStepIdx);
621 if (! group.hasInjectionControl(phase)) {
624 return static_cast<Scalar
>(group.injectionControls(phase, summary_state).surface_max_rate);
627template<
typename TypeTag>
629BlackoilWellModelRescoup<TypeTag>::
630sendMasterGroupInjectionTargetsToSlaves_()
633 RescoupConstraintsCalculator<Scalar, IndexTraits> constraints_calculator{
634 this->well_model_.guideRateHandler(),
635 this->groupStateHelper()
637 constraints_calculator.recalculateInjectionTargetsAndSendToSlaves();
640template<
typename TypeTag>
642BlackoilWellModelRescoup<TypeTag>::
643slaveGroupIsFixedPressureNodeInOwnNetwork_(
const std::string& group_name)
const
645 const int episodeIdx = this->simulator_.episodeIndex();
646 const auto& network = this->schedule()[episodeIdx].network();
647 if (!network.active())
return false;
648 if (!network.has_node(group_name))
return false;
649 return network.node(group_name).terminal_pressure().has_value();
#define OPM_END_PARALLEL_TRY_CATCH_LOG(obptc_logger, obptc_prefix, obptc_output, comm)
Catch exception, log, and throw in a parallel try-catch clause.
Definition: DeferredLoggingErrorHelpers.hpp:207
#define OPM_BEGIN_PARALLEL_TRY_CATCH()
Macro to setup the try of a parallel try-catch.
Definition: DeferredLoggingErrorHelpers.hpp:160
Phase
Phase indices for reservoir coupling, we currently only support black-oil phases (oil,...
Definition: ReservoirCoupling.hpp:183
Definition: blackoilbioeffectsmodules.hh:45