Merge pull request #1671 from atgeirr/fix-infinite-loop

Fix potential infinite loop
This commit is contained in:
Tor Harald Sandve
2018-12-07 12:41:37 +01:00
committed by GitHub
3 changed files with 46 additions and 30 deletions

View File

@@ -243,7 +243,8 @@ namespace Opm {
bool hasTHPConstraints() const;
/// Shut down any single well, but only if it is in prediction mode.
void forceShutWellByNameIfPredictionMode(const std::string& wellname, const double simulation_time);
/// Returns true if the well was actually found and shut.
bool forceShutWellByNameIfPredictionMode(const std::string& wellname, const double simulation_time);
protected:

View File

@@ -133,30 +133,37 @@ namespace Opm {
/// Return true if any well has a THP constraint.
/// Return true if the well was found and shut.
template<typename TypeTag>
void
bool
BlackoilWellModel<TypeTag>::
forceShutWellByNameIfPredictionMode(const std::string& wellname,
const double simulation_time)
{
// 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_) {
if (well->name() == wellname) {
if (well->underPredictionMode()) {
wellTestState_.addClosedWell(wellname, WellTestConfig::Reason::PHYSICAL, simulation_time);
well_was_shut = 1;
}
break;
}
}
// Communicate across processes if a well was shut.
well_was_shut = ebosSimulator_.vanguard().grid().comm().max(well_was_shut);
// Only log a message on the output rank.
if (terminal_output_) {
if (terminal_output_ && well_was_shut) {
const std::string msg = "Well " + wellname
+ " will be shut because it cannot get converged.";
OpmLog::info(msg);
}
return (well_was_shut == 1);
}

View File

@@ -334,12 +334,13 @@ namespace Opm {
substepTimer.setLastStepFailed(false);
}
else { // in case of no convergence (linearIterations < 0)
else { // in case of no convergence
substepTimer.setLastStepFailed(true);
failureReport_ += substepReport;
// increase restart counter
// If we have restarted (i.e. cut the timestep) too
// many times, we have failed and throw an exception.
if (restarts >= solverRestartMax_) {
const auto msg = std::string("Solver failed to converge after cutting timestep ")
+ std::to_string(restarts) + " times.";
@@ -349,10 +350,11 @@ namespace Opm {
OPM_THROW_NOLOG(Opm::NumericalIssue, msg);
}
// The new, chopped timestep.
const double newTimeStep = restartFactor_ * dt;
const double minimumChoppedTimestep = 0.25 * unit::day;
if (newTimeStep > minimumChoppedTimestep) {
// Chop the timestep.
// Define utility function for chopping timestep.
auto chopTimestep = [&]() {
substepTimer.provideTimeStepEstimate(newTimeStep);
if (solverVerbose_) {
std::string msg;
@@ -361,44 +363,50 @@ namespace Opm {
OpmLog::problem(msg);
}
++restarts;
};
const double minimumChoppedTimestep = 0.25 * unit::day;
if (newTimeStep > minimumChoppedTimestep) {
chopTimestep();
} else {
// We are below the threshold, and will check if there are any
// wells we should close rather than chopping again.
std::set<std::string> failing_wells = consistentlyFailingWells(solver.model().stepReports());
if (failing_wells.empty()) {
// Found no wells to close, chop the timestep as above.
substepTimer.provideTimeStepEstimate(newTimeStep);
if (solverVerbose_) {
std::string msg;
msg = causeOfFailure + "\nTimestep chopped to "
+ std::to_string(unit::convert::to(substepTimer.currentStepLength(), unit::day)) + " days\n";
OpmLog::problem(msg);
}
++restarts;
chopTimestep();
} else {
// Close all consistently failing wells.
int num_shut_wells = 0;
for (const auto& well : failing_wells) {
solver.model().wellModel().forceShutWellByNameIfPredictionMode(well, substepTimer.simulationTimeElapsed());
}
substepTimer.provideTimeStepEstimate(dt);
if (solverVerbose_) {
std::string msg;
msg = "\nProblematic well(s) were shut: ";
for (const auto& well : failing_wells) {
msg += well;
msg += " ";
bool was_shut = solver.model().wellModel().forceShutWellByNameIfPredictionMode(well, substepTimer.simulationTimeElapsed());
if (was_shut) {
++num_shut_wells;
}
}
if (num_shut_wells == 0) {
// None of the problematic wells were prediction wells,
// so none were shut. We must fall back to chopping again.
chopTimestep();
} else {
substepTimer.provideTimeStepEstimate(dt);
if (solverVerbose_) {
std::string msg;
msg = "\nProblematic well(s) were shut: ";
for (const auto& well : failing_wells) {
msg += well;
msg += " ";
}
msg += "(retrying timestep)\n";
OpmLog::problem(msg);
}
msg += "(retrying timestep)\n";
OpmLog::problem(msg);
}
}
}
}
ebosProblem.setNextTimeStepSize(substepTimer.currentStepLength());
}
// store estimated time step for next reportStep
suggestedNextTimestep_ = substepTimer.currentStepLength();
if (timestepVerbose_) {