diff --git a/opm/simulators/timestepping/AdaptiveTimeStepping.hpp b/opm/simulators/timestepping/AdaptiveTimeStepping.hpp index d3166a252..43bfb0da1 100644 --- a/opm/simulators/timestepping/AdaptiveTimeStepping.hpp +++ b/opm/simulators/timestepping/AdaptiveTimeStepping.hpp @@ -426,24 +426,34 @@ void registerAdaptiveParameters(); // Found no wells to close, chop the timestep as above. chopTimestep(); } else { - // Close all consistently failing wells. - int num_shut_wells = 0; + // Close all consistently failing wells that are not under group control + std::vector shut_wells; for (const auto& well : failing_wells) { - bool was_shut = solver.model().wellModel().forceShutWellByName(well, substepTimer.simulationTimeElapsed()); + bool was_shut = solver.model().wellModel().forceShutWellByName( + well, substepTimer.simulationTimeElapsed(), /*dont_shut_grup_wells =*/ true); if (was_shut) { - ++num_shut_wells; + shut_wells.push_back(well); } } - if (num_shut_wells == 0) { - // None of the problematic wells were shut. - // We must fall back to chopping again. + // If no wells are closed we also try to shut wells under group control + if (shut_wells.empty()) { + for (const auto& well : failing_wells) { + bool was_shut = solver.model().wellModel().forceShutWellByName( + well, substepTimer.simulationTimeElapsed(), /*dont_shut_grup_wells =*/ false); + if (was_shut) { + shut_wells.push_back(well); + } + } + } + // If still no wells are closed we must fall back to chopping again + if (shut_wells.empty()) { chopTimestep(); } else { substepTimer.provideTimeStepEstimate(dt); if (solverVerbose_) { std::string msg; msg = "\nProblematic well(s) were shut: "; - for (const auto& well : failing_wells) { + for (const auto& well : shut_wells) { msg += well; msg += " "; } diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index 44a441050..024251f5b 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -1318,13 +1318,27 @@ needPreStepNetworkRebalance(const int report_step) const template bool BlackoilWellModelGeneric:: forceShutWellByName(const std::string& wellname, - const double simulation_time) + const double simulation_time, + const bool dont_shut_grup_wells) { // Only add the well to the closed list on the // process that owns it. int well_was_shut = 0; for (const auto& well : well_container_generic_) { if (well->name() == wellname) { + // if one well on individuel control (typical thp/bhp) in a group strugles to converge + // it may lead to problems for the other wells in the group + // we dont want to shut all the wells in a group only the one creating the problems. + const auto& ws = this->wellState().well(well->indexOfWell()); + if (dont_shut_grup_wells) { + if (well->isInjector()) { + if (ws.injection_cmode == Well::InjectorCMode::GRUP) + continue; + } else { + if (ws.production_cmode == Well::ProducerCMode::GRUP) + continue; + } + } wellTestState().close_well(wellname, WellTestConfig::Reason::PHYSICAL, simulation_time); well_was_shut = 1; break; diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.hpp b/opm/simulators/wells/BlackoilWellModelGeneric.hpp index 324d63939..7daa70277 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.hpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.hpp @@ -191,7 +191,8 @@ public: /// Shut down any single well /// Returns true if the well was actually found and shut. bool forceShutWellByName(const std::string& wellname, - const double simulation_time); + const double simulation_time, + const bool dont_shut_grup_wells); const std::vector>& perfData(const int well_idx) const { return well_perf_data_[well_idx]; }