From 588f73d8f3c99e7a4cb411519d6d30c0287a121f Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 18 Aug 2026 08:56:46 +0200 Subject: [PATCH] Respect explicit well STOP status during state propagation and solver recovery --- opm/simulators/wells/WellInterface_impl.hpp | 8 +++++--- opm/simulators/wells/WellState.cpp | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/opm/simulators/wells/WellInterface_impl.hpp b/opm/simulators/wells/WellInterface_impl.hpp index 1f9e7ac1d98..28bf102e41b 100644 --- a/opm/simulators/wells/WellInterface_impl.hpp +++ b/opm/simulators/wells/WellInterface_impl.hpp @@ -635,8 +635,8 @@ namespace Opm const auto& summary_state = simulator.vanguard().summaryState(); bool converged = true; auto& ws = well_state.well(this->index_of_well_); - // if well is stopped, check if we can reopen with explicit fraction - if (this->wellIsStopped()) { + // Solver recovery may reopen dynamic stops, but never an explicit schedule STOP. + if (this->wellIsStopped() && this->well_ecl_.getStatus() != Well::Status::STOP) { this->openWell(); const bool use_vfpexplicit = this->operability_status_.use_vfpexplicit; this->operability_status_.use_vfpexplicit = true; @@ -1145,7 +1145,9 @@ namespace Opm deferred_logger.debug(" well " + this->name() + " gets STOPPED during iteration" + ctx); changed_to_stopped_this_step_ = true; } - } else if (well_state.isOpen(this->name())) { + // Do not let automatic revival override an explicit schedule STOP. + } else if (well_state.isOpen(this->name()) && + this->well_ecl_.getStatus() != Well::Status::STOP) { this->openWell(); if (!old_well_operable) { const std::string ctx = iterCtx.inLocalSolve() ? " (NLDD domain solve)" : ""; diff --git a/opm/simulators/wells/WellState.cpp b/opm/simulators/wells/WellState.cpp index c805a0e8155..31e8fd84da5 100644 --- a/opm/simulators/wells/WellState.cpp +++ b/opm/simulators/wells/WellState.cpp @@ -396,7 +396,10 @@ init(const std::vector& cellPressures, continue; } - new_well.status = prev_well.status; + // A current schedule STOP/OPEN must take precedence over the previous runtime status. + if (!new_well.events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE)) { + new_well.status = prev_well.status; + } if (new_well.producer != prev_well.producer) { // Well changed to/from injector from/to producer, do not