mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
adding function checkConvergenceControlEq to refactor getWellConvergence
only functional change is that rate control or BHP control has different tolerance for MSW now.
This commit is contained in:
parent
41ef80dd7d
commit
4593453d10
@ -379,7 +379,13 @@ namespace Opm
|
|||||||
void detectOscillations(const std::vector<double>& measure_history,
|
void detectOscillations(const std::vector<double>& measure_history,
|
||||||
const int it, bool& oscillate, bool& stagnate) const;
|
const int it, bool& oscillate, bool& stagnate) const;
|
||||||
|
|
||||||
double getResidualMeasureValue(const std::vector<double>& residuals) const;
|
double getResidualMeasureValue(const std::vector<double>& residuals,
|
||||||
|
DeferredLogger& deferred_logger) const;
|
||||||
|
|
||||||
|
double getControlTolerance(DeferredLogger& deferred_logger) const;
|
||||||
|
|
||||||
|
void checkConvergenceControlEq(ConvergenceReport& report,
|
||||||
|
DeferredLogger& deferred_logger) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -429,28 +429,9 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using CR = ConvergenceReport;
|
|
||||||
CR::WellFailure::Type ctrltype = CR::WellFailure::Type::Invalid;
|
|
||||||
switch(well_controls_get_current_type(well_controls_)) {
|
|
||||||
case THP:
|
|
||||||
ctrltype = CR::WellFailure::Type::ControlTHP;
|
|
||||||
break;
|
|
||||||
case BHP:
|
|
||||||
ctrltype = CR::WellFailure::Type::ControlBHP;
|
|
||||||
break;
|
|
||||||
case RESERVOIR_RATE:
|
|
||||||
case SURFACE_RATE:
|
|
||||||
ctrltype = CR::WellFailure::Type::ControlRate;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
OPM_DEFLOG_THROW(std::runtime_error, "Unknown well control control types for well " << name(), deferred_logger);
|
|
||||||
}
|
|
||||||
assert(ctrltype != CR::WellFailure::Type::Invalid);
|
|
||||||
|
|
||||||
std::vector<double> maximum_residual(numWellEq, 0.0);
|
std::vector<double> maximum_residual(numWellEq, 0.0);
|
||||||
|
|
||||||
ConvergenceReport report;
|
ConvergenceReport report;
|
||||||
const int dummy_component = -1;
|
|
||||||
// TODO: the following is a little complicated, maybe can be simplified in some way?
|
// TODO: the following is a little complicated, maybe can be simplified in some way?
|
||||||
for (int eq_idx = 0; eq_idx < numWellEq; ++eq_idx) {
|
for (int eq_idx = 0; eq_idx < numWellEq; ++eq_idx) {
|
||||||
for (int seg = 0; seg < numberOfSegments(); ++seg) {
|
for (int seg = 0; seg < numberOfSegments(); ++seg) {
|
||||||
@ -460,18 +441,8 @@ namespace Opm
|
|||||||
maximum_residual[eq_idx] = flux_residual;
|
maximum_residual[eq_idx] = flux_residual;
|
||||||
}
|
}
|
||||||
} else { // pressure or control equation
|
} else { // pressure or control equation
|
||||||
if (seg == 0) {
|
// for the top segment (seg == 0), it is control equation, will be checked later separately
|
||||||
// Control equation
|
if (seg > 0) {
|
||||||
const double control_residual = abs_residual[seg][eq_idx];
|
|
||||||
if (std::isnan(control_residual)) {
|
|
||||||
report.setWellFailed({ctrltype, CR::Severity::NotANumber, dummy_component, name()});
|
|
||||||
} else if (control_residual > param_.max_residual_allowed_) {
|
|
||||||
report.setWellFailed({ctrltype, CR::Severity::TooLarge, dummy_component, name()});
|
|
||||||
// TODO: we should distinguish the flux residual or pressure residual here
|
|
||||||
} else if (control_residual > param_.tolerance_wells_) {
|
|
||||||
report.setWellFailed({ctrltype, CR::Severity::Normal, dummy_component, name()});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Pressure equation
|
// Pressure equation
|
||||||
const double pressure_residual = abs_residual[seg][eq_idx];
|
const double pressure_residual = abs_residual[seg][eq_idx];
|
||||||
if (pressure_residual > maximum_residual[eq_idx]) {
|
if (pressure_residual > maximum_residual[eq_idx]) {
|
||||||
@ -482,6 +453,7 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using CR = ConvergenceReport;
|
||||||
for (int eq_idx = 0; eq_idx < numWellEq; ++eq_idx) {
|
for (int eq_idx = 0; eq_idx < numWellEq; ++eq_idx) {
|
||||||
if (eq_idx < num_components_) { // phase or component mass equations
|
if (eq_idx < num_components_) { // phase or component mass equations
|
||||||
const double flux_residual = maximum_residual[eq_idx];
|
const double flux_residual = maximum_residual[eq_idx];
|
||||||
@ -495,6 +467,7 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
} else { // pressure equation
|
} else { // pressure equation
|
||||||
const double pressure_residual = maximum_residual[eq_idx];
|
const double pressure_residual = maximum_residual[eq_idx];
|
||||||
|
const int dummy_component = -1;
|
||||||
if (std::isnan(pressure_residual)) {
|
if (std::isnan(pressure_residual)) {
|
||||||
report.setWellFailed({CR::WellFailure::Type::Pressure, CR::Severity::NotANumber, dummy_component, name()});
|
report.setWellFailed({CR::WellFailure::Type::Pressure, CR::Severity::NotANumber, dummy_component, name()});
|
||||||
} else if (std::isinf(pressure_residual)) {
|
} else if (std::isinf(pressure_residual)) {
|
||||||
@ -505,6 +478,8 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkConvergenceControlEq(report, deferred_logger);
|
||||||
|
|
||||||
return report;
|
return report;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1825,7 +1800,7 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
|
|
||||||
residual_history.push_back(getWellResiduals(B_avg));
|
residual_history.push_back(getWellResiduals(B_avg));
|
||||||
measure_history.push_back(getResidualMeasureValue(residual_history[it]));
|
measure_history.push_back(getResidualMeasureValue(residual_history[it], deferred_logger) );
|
||||||
|
|
||||||
bool is_oscillate = false;
|
bool is_oscillate = false;
|
||||||
bool is_stagnate = false;
|
bool is_stagnate = false;
|
||||||
@ -2248,7 +2223,8 @@ namespace Opm
|
|||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
double
|
double
|
||||||
MultisegmentWell<TypeTag>::
|
MultisegmentWell<TypeTag>::
|
||||||
getResidualMeasureValue(const std::vector<double>& residuals) const
|
getResidualMeasureValue(const std::vector<double>& residuals,
|
||||||
|
DeferredLogger& deferred_logger) const
|
||||||
{
|
{
|
||||||
assert(int(residuals.size()) == numWellEq + 1);
|
assert(int(residuals.size()) == numWellEq + 1);
|
||||||
|
|
||||||
@ -2262,9 +2238,11 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const double pressure_tolerance = param_.tolerance_pressure_ms_wells_;
|
const double control_tolerance = getControlTolerance(deferred_logger);
|
||||||
if (residuals[SPres] > pressure_tolerance) {
|
|
||||||
sum += residuals[SPres] / pressure_tolerance;
|
// const double pressure_tolerance = param_.tolerance_pressure_ms_wells_;
|
||||||
|
if (residuals[SPres] > control_tolerance) {
|
||||||
|
sum += residuals[SPres] / control_tolerance;
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2275,4 +2253,69 @@ namespace Opm
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename TypeTag>
|
||||||
|
double
|
||||||
|
MultisegmentWell<TypeTag>::
|
||||||
|
getControlTolerance(DeferredLogger& deferred_logger) const
|
||||||
|
{
|
||||||
|
double control_tolerance = 0.;
|
||||||
|
switch(well_controls_get_current_type(well_controls_) ) {
|
||||||
|
case BHP:
|
||||||
|
case THP:
|
||||||
|
control_tolerance = param_.tolerance_wells_;
|
||||||
|
break;
|
||||||
|
case RESERVOIR_RATE:
|
||||||
|
case SURFACE_RATE:
|
||||||
|
control_tolerance = param_.tolerance_pressure_ms_wells_;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OPM_DEFLOG_THROW(std::runtime_error, "Unknown well control control types for well " << name(), deferred_logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
return control_tolerance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename TypeTag>
|
||||||
|
void
|
||||||
|
MultisegmentWell<TypeTag>::
|
||||||
|
checkConvergenceControlEq(ConvergenceReport& report,
|
||||||
|
DeferredLogger& deferred_logger) const
|
||||||
|
{
|
||||||
|
using CR = ConvergenceReport;
|
||||||
|
CR::WellFailure::Type ctrltype = CR::WellFailure::Type::Invalid;
|
||||||
|
switch(well_controls_get_current_type(well_controls_)) {
|
||||||
|
case THP:
|
||||||
|
ctrltype = CR::WellFailure::Type::ControlTHP;
|
||||||
|
break;
|
||||||
|
case BHP:
|
||||||
|
ctrltype = CR::WellFailure::Type::ControlBHP;
|
||||||
|
break;
|
||||||
|
case RESERVOIR_RATE:
|
||||||
|
case SURFACE_RATE:
|
||||||
|
ctrltype = CR::WellFailure::Type::ControlRate;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OPM_DEFLOG_THROW(std::runtime_error, "Unknown well control control types for well " << name(), deferred_logger);
|
||||||
|
}
|
||||||
|
assert(ctrltype != CR::WellFailure::Type::Invalid);
|
||||||
|
|
||||||
|
const double control_residual = std::abs(resWell_[0][SPres]);
|
||||||
|
const double control_tolerance = getControlTolerance(deferred_logger);
|
||||||
|
|
||||||
|
const int dummy_component = -1;
|
||||||
|
if (std::isnan(control_residual)) {
|
||||||
|
report.setWellFailed({ctrltype, CR::Severity::NotANumber, dummy_component, name()});
|
||||||
|
} else if (control_residual > param_.max_residual_allowed_) {
|
||||||
|
report.setWellFailed({ctrltype, CR::Severity::TooLarge, dummy_component, name()});
|
||||||
|
} else if (control_residual > control_tolerance) {
|
||||||
|
report.setWellFailed({ctrltype, CR::Severity::Normal, dummy_component, name()});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,6 +439,10 @@ namespace Opm
|
|||||||
Opm::DeferredLogger& deferred_logger) override;
|
Opm::DeferredLogger& deferred_logger) override;
|
||||||
|
|
||||||
virtual void updateWaterThroughput(const double dt, WellState& well_state) const override;
|
virtual void updateWaterThroughput(const double dt, WellState& well_state) const override;
|
||||||
|
|
||||||
|
void checkConvergenceControlEq(ConvergenceReport& report,
|
||||||
|
DeferredLogger& deferred_logger) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -465,6 +465,9 @@ namespace Opm
|
|||||||
Opm::DeferredLogger& deferred_logger);
|
Opm::DeferredLogger& deferred_logger);
|
||||||
|
|
||||||
virtual void updateWaterThroughput(const double dt, WellState& well_state) const override;
|
virtual void updateWaterThroughput(const double dt, WellState& well_state) const override;
|
||||||
|
|
||||||
|
void checkConvergenceControlEq(ConvergenceReport& report,
|
||||||
|
DeferredLogger& deferred_logger) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2029,40 +2029,12 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// processing the residual of the well control equation
|
checkConvergenceControlEq(report, deferred_logger);
|
||||||
const double well_control_residual = res[numWellEq_ - 1];
|
|
||||||
// TODO: we should have better way to specify the control equation tolerance
|
|
||||||
double control_tolerance = 0.;
|
|
||||||
switch(well_controls_get_current_type(well_controls_)) {
|
|
||||||
case THP:
|
|
||||||
type = CR::WellFailure::Type::ControlTHP;
|
|
||||||
control_tolerance = 1.e4; // 0.1 bar
|
|
||||||
break;
|
|
||||||
case BHP: // pressure type of control
|
|
||||||
type = CR::WellFailure::Type::ControlBHP;
|
|
||||||
control_tolerance = 1.e3; // 0.01 bar
|
|
||||||
break;
|
|
||||||
case RESERVOIR_RATE:
|
|
||||||
case SURFACE_RATE:
|
|
||||||
type = CR::WellFailure::Type::ControlRate;
|
|
||||||
control_tolerance = 1.e-4; // smaller tolerance for rate control
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
OPM_DEFLOG_THROW(std::runtime_error, "Unknown well control control types for well " + name(), deferred_logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int dummy_component = -1;
|
|
||||||
if (std::isnan(well_control_residual)) {
|
|
||||||
report.setWellFailed({type, CR::Severity::NotANumber, dummy_component, name()});
|
|
||||||
} else if (well_control_residual > maxResidualAllowed * 10.) {
|
|
||||||
report.setWellFailed({type, CR::Severity::TooLarge, dummy_component, name()});
|
|
||||||
} else if ( well_control_residual > control_tolerance) {
|
|
||||||
report.setWellFailed({type, CR::Severity::Normal, dummy_component, name()});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->has_polymermw && well_type_ == INJECTOR) {
|
if (this->has_polymermw && well_type_ == INJECTOR) {
|
||||||
// checking the convergence of the perforation rates
|
// checking the convergence of the perforation rates
|
||||||
const double wat_vel_tol = 1.e-8;
|
const double wat_vel_tol = 1.e-8;
|
||||||
|
const int dummy_component = -1;
|
||||||
const auto wat_vel_failure_type = CR::WellFailure::Type::MassBalance;
|
const auto wat_vel_failure_type = CR::WellFailure::Type::MassBalance;
|
||||||
for (int perf = 0; perf < number_of_perforations_; ++perf) {
|
for (int perf = 0; perf < number_of_perforations_; ++perf) {
|
||||||
const double wat_vel_residual = res[Bhp + 1 + perf];
|
const double wat_vel_residual = res[Bhp + 1 + perf];
|
||||||
@ -3112,4 +3084,49 @@ namespace Opm
|
|||||||
duneB_[0][cell_idx][wat_vel_index][pvIdx] = eq_wat_vel.derivative(pvIdx);
|
duneB_[0][cell_idx][wat_vel_index][pvIdx] = eq_wat_vel.derivative(pvIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename TypeTag>
|
||||||
|
void
|
||||||
|
StandardWellV<TypeTag>::
|
||||||
|
checkConvergenceControlEq(ConvergenceReport& report,
|
||||||
|
DeferredLogger& deferred_logger) const
|
||||||
|
{
|
||||||
|
double control_tolerance = 0.;
|
||||||
|
using CR = ConvergenceReport;
|
||||||
|
CR::WellFailure::Type ctrltype = CR::WellFailure::Type::Invalid;
|
||||||
|
switch(well_controls_get_current_type(well_controls_)) {
|
||||||
|
case THP:
|
||||||
|
ctrltype = CR::WellFailure::Type::ControlTHP;
|
||||||
|
control_tolerance = 1.e4; // 0.1 bar
|
||||||
|
break;
|
||||||
|
case BHP: // pressure type of control
|
||||||
|
ctrltype = CR::WellFailure::Type::ControlBHP;
|
||||||
|
control_tolerance = 1.e3; // 0.01 bar
|
||||||
|
break;
|
||||||
|
case RESERVOIR_RATE:
|
||||||
|
case SURFACE_RATE:
|
||||||
|
ctrltype = CR::WellFailure::Type::ControlRate;
|
||||||
|
control_tolerance = 1.e-4; // smaller tolerance for rate control
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OPM_DEFLOG_THROW(std::runtime_error, "Unknown well control control types for well " << name(), deferred_logger);
|
||||||
|
}
|
||||||
|
assert(ctrltype != CR::WellFailure::Type::Invalid);
|
||||||
|
|
||||||
|
const double well_control_residual = std::abs(resWell_[0][Bhp]);
|
||||||
|
const int dummy_component = -1;
|
||||||
|
const double max_residual_allowed = param_.max_residual_allowed_;
|
||||||
|
if (std::isnan(well_control_residual)) {
|
||||||
|
report.setWellFailed({ctrltype, CR::Severity::NotANumber, dummy_component, name()});
|
||||||
|
} else if (well_control_residual > max_residual_allowed * 10.) {
|
||||||
|
report.setWellFailed({ctrltype, CR::Severity::TooLarge, dummy_component, name()});
|
||||||
|
} else if ( well_control_residual > control_tolerance) {
|
||||||
|
report.setWellFailed({ctrltype, CR::Severity::Normal, dummy_component, name()});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1957,37 +1957,7 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// processing the residual of the well control equation
|
checkConvergenceControlEq(report, deferred_logger);
|
||||||
const double well_control_residual = res[numWellEq - 1];
|
|
||||||
// TODO: we should have better way to specify the control equation tolerance
|
|
||||||
double control_tolerance = 0.;
|
|
||||||
switch(well_controls_get_current_type(well_controls_)) {
|
|
||||||
case THP:
|
|
||||||
type = CR::WellFailure::Type::ControlTHP;
|
|
||||||
control_tolerance = 1.e4; // 0.1 bar
|
|
||||||
break;
|
|
||||||
case BHP: // pressure type of control
|
|
||||||
type = CR::WellFailure::Type::ControlBHP;
|
|
||||||
control_tolerance = 1.e3; // 0.01 bar
|
|
||||||
break;
|
|
||||||
case RESERVOIR_RATE:
|
|
||||||
case SURFACE_RATE:
|
|
||||||
type = CR::WellFailure::Type::ControlRate;
|
|
||||||
control_tolerance = 1.e-4; // smaller tolerance for rate control
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// If this happens, control_tolerance will remain zero and convergence will fail.
|
|
||||||
deferred_logger.bug("Unknown well control type for well " + name());
|
|
||||||
}
|
|
||||||
|
|
||||||
const int dummy_component = -1;
|
|
||||||
if (std::isnan(well_control_residual)) {
|
|
||||||
report.setWellFailed({type, CR::Severity::NotANumber, dummy_component, name()});
|
|
||||||
} else if (well_control_residual > maxResidualAllowed * 10.) {
|
|
||||||
report.setWellFailed({type, CR::Severity::TooLarge, dummy_component, name()});
|
|
||||||
} else if ( well_control_residual > control_tolerance) {
|
|
||||||
report.setWellFailed({type, CR::Severity::Normal, dummy_component, name()});
|
|
||||||
}
|
|
||||||
|
|
||||||
return report;
|
return report;
|
||||||
}
|
}
|
||||||
@ -2853,4 +2823,48 @@ namespace Opm
|
|||||||
updateWaterThroughput(const double dt OPM_UNUSED, WellState& well_state OPM_UNUSED) const
|
updateWaterThroughput(const double dt OPM_UNUSED, WellState& well_state OPM_UNUSED) const
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename TypeTag>
|
||||||
|
void
|
||||||
|
StandardWell<TypeTag>::
|
||||||
|
checkConvergenceControlEq(ConvergenceReport& report,
|
||||||
|
DeferredLogger& deferred_logger) const
|
||||||
|
{
|
||||||
|
double control_tolerance = 0.;
|
||||||
|
using CR = ConvergenceReport;
|
||||||
|
CR::WellFailure::Type ctrltype = CR::WellFailure::Type::Invalid;
|
||||||
|
switch(well_controls_get_current_type(well_controls_)) {
|
||||||
|
case THP:
|
||||||
|
ctrltype = CR::WellFailure::Type::ControlTHP;
|
||||||
|
control_tolerance = 1.e4; // 0.1 bar
|
||||||
|
break;
|
||||||
|
case BHP: // pressure type of control
|
||||||
|
ctrltype = CR::WellFailure::Type::ControlBHP;
|
||||||
|
control_tolerance = 1.e3; // 0.01 bar
|
||||||
|
break;
|
||||||
|
case RESERVOIR_RATE:
|
||||||
|
case SURFACE_RATE:
|
||||||
|
ctrltype = CR::WellFailure::Type::ControlRate;
|
||||||
|
control_tolerance = 1.e-4; // smaller tolerance for rate control
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OPM_DEFLOG_THROW(std::runtime_error, "Unknown well control control types for well " << name(), deferred_logger);
|
||||||
|
}
|
||||||
|
assert(ctrltype != CR::WellFailure::Type::Invalid);
|
||||||
|
|
||||||
|
const double well_control_residual = std::abs(resWell_[0][numWellEq -1]);
|
||||||
|
const int dummy_component = -1;
|
||||||
|
const double max_residual_allowed = param_.max_residual_allowed_;
|
||||||
|
if (std::isnan(well_control_residual)) {
|
||||||
|
report.setWellFailed({ctrltype, CR::Severity::NotANumber, dummy_component, name()});
|
||||||
|
} else if (well_control_residual > max_residual_allowed * 10.) {
|
||||||
|
report.setWellFailed({ctrltype, CR::Severity::TooLarge, dummy_component, name()});
|
||||||
|
} else if ( well_control_residual > control_tolerance) {
|
||||||
|
report.setWellFailed({ctrltype, CR::Severity::Normal, dummy_component, name()});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user