cleanup thp-solve

This commit is contained in:
Stein Krogstad 2023-11-07 17:29:19 +01:00
parent 3e6732a67b
commit 44e17fa615
2 changed files with 66 additions and 67 deletions

View File

@ -430,13 +430,13 @@ protected:
const GroupState& group_state, const GroupState& group_state,
DeferredLogger& deferred_logger); DeferredLogger& deferred_logger);
bool robustWellSolveWithTHP(const Simulator& ebos_simulator, bool solveWellWithTHPConstraint(const Simulator& ebos_simulator,
const double dt, const double dt,
const Well::InjectionControls& inj_controls, const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls, const Well::ProductionControls& prod_controls,
WellState& well_state, WellState& well_state,
const GroupState& group_state, const GroupState& group_state,
DeferredLogger& deferred_logger); DeferredLogger& deferred_logger);
std::optional<double> estimateOperableBhp(const Simulator& ebos_simulator, std::optional<double> estimateOperableBhp(const Simulator& ebos_simulator,
const double dt, const double dt,

View File

@ -462,10 +462,11 @@ namespace Opm
converged = this->iterateWellEqWithControl(ebosSimulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger); converged = this->iterateWellEqWithControl(ebosSimulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
} else { } else {
if (this->well_ecl_.isProducer() && this->wellHasTHPConstraints(summary_state)) { if (this->well_ecl_.isProducer() && this->wellHasTHPConstraints(summary_state)) {
converged = robustWellSolveWithTHP(ebosSimulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger); converged = solveWellWithTHPConstraint(ebosSimulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
} else { } else {
converged = this->iterateWellEqWithSwitching(ebosSimulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger); converged = this->iterateWellEqWithSwitching(ebosSimulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
} }
this->updateIPRImplicit(ebosSimulator, well_state, deferred_logger);
} }
} catch (NumericalProblem& e ) { } catch (NumericalProblem& e ) {
@ -479,99 +480,97 @@ namespace Opm
template<typename TypeTag> template<typename TypeTag>
bool bool
WellInterface<TypeTag>:: WellInterface<TypeTag>::
robustWellSolveWithTHP(const Simulator& ebos_simulator, solveWellWithTHPConstraint(const Simulator& ebos_simulator,
const double dt, const double dt,
const Well::InjectionControls& inj_controls, const Well::InjectionControls& inj_controls,
const Well::ProductionControls& prod_controls, const Well::ProductionControls& prod_controls,
WellState& well_state, WellState& well_state,
const GroupState& group_state, const GroupState& group_state,
DeferredLogger& deferred_logger) DeferredLogger& deferred_logger)
{ {
const auto& summary_state = ebos_simulator.vanguard().summaryState(); const auto& summary_state = ebos_simulator.vanguard().summaryState();
bool is_operable = true; bool is_operable = true;
bool converged; bool converged = true;
auto& ws = well_state.well(this->index_of_well_);
// if well is stopped, check if we can reopen
if (this->wellIsStopped()) { if (this->wellIsStopped()) {
this->openWell(); this->openWell();
auto bhp_target = estimateOperableBhp(ebos_simulator, dt, well_state, group_state, summary_state, deferred_logger); auto bhp_target = estimateOperableBhp(ebos_simulator, dt, well_state, group_state, summary_state, deferred_logger);
if (!bhp_target.has_value()) { if (!bhp_target.has_value()) {
// well can't operate using explicit fractions // no intersection with ipr
is_operable = false; is_operable = false;
// XXX convereged = true - iterate with closed well! // solve with zero rates
converged = solveWellWithZeroRate(ebos_simulator, dt, well_state, deferred_logger); converged = solveWellWithZeroRate(ebos_simulator, dt, well_state, deferred_logger);
this->stopWell();
} else { } else {
converged = solveWellWithBhp(ebos_simulator, dt, bhp_target.value(), well_state, deferred_logger); // solve well with the estimated target bhp (or limit)
const double bhp = std::max(bhp_target.value(), prod_controls.bhp_limit);
converged = solveWellWithBhp(ebos_simulator, dt, bhp, well_state, deferred_logger);
} }
} else { }
// solve well-equation
if (is_operable) {
converged = this->iterateWellEqWithSwitching(ebos_simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger); converged = this->iterateWellEqWithSwitching(ebos_simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
} }
if (converged && !this->stopppedOrZeroRateTarget(summary_state, well_state) && well_state.well(this->index_of_well_).production_cmode == Well::ProducerCMode::THP) {
auto rates = well_state.well(this->index_of_well_).surface_rates;
this->adaptRatesForVFP(rates);
// FIX !!!!!!!!!!
// first, check just dbhp/dflo
// update ipr for stability-check const bool isThp = ws.production_cmode == Well::ProducerCMode::THP;
this->updateIPRImplicit(ebos_simulator, well_state, deferred_logger); // check stability of solution under thp-control
bool is_stable = WellBhpThpCalculator(*this).isStableSolution(well_state, this->well_ecl_, rates, summary_state, deferred_logger); if (true) {
if (!is_stable) { if (converged && !this->stopppedOrZeroRateTarget(summary_state, well_state) && isThp) {
// solution converged to an unstable point! auto rates = well_state.well(this->index_of_well_).surface_rates;
this->operability_status_.use_vfpexplicit = true; this->adaptRatesForVFP(rates);
auto bhp_stable = WellBhpThpCalculator(*this).estimateStableBhp(well_state, this->well_ecl_, rates, this->getRefDensity(), summary_state, deferred_logger); this->updateIPRImplicit(ebos_simulator, well_state, deferred_logger);
if (!bhp_stable.has_value()) { bool is_stable = WellBhpThpCalculator(*this).isStableSolution(well_state, this->well_ecl_, rates, summary_state, deferred_logger);
// well is not operable (no intersection) if (!is_stable) {
// XXX convereged = true - iterate with closed well! // solution converged to an unstable point!
//is_operable = false; this->operability_status_.use_vfpexplicit = true;
//converged = solveWellWithZeroRate(ebos_simulator, dt, well_state, deferred_logger); // msg = ...
} else { auto bhp_stable = WellBhpThpCalculator(*this).estimateStableBhp(well_state, this->well_ecl_, rates, this->getRefDensity(), summary_state, deferred_logger);
// solve equations for bhp_stable (in attempt to get closer to actual solution) // if we find an intersection with a sufficiently lower bhp, re-solve equations
const bool converged_bhp = solveWellWithBhp(ebos_simulator, dt, bhp_stable.value(), well_state, deferred_logger); const bool reltol = 1e-3;
this->updateIPRImplicit(ebos_simulator, well_state, deferred_logger); const double cur_bhp = ws.bhp;
auto bhp_stable1 = WellBhpThpCalculator(*this).estimateStableBhp(well_state, this->well_ecl_, rates, this->getRefDensity(), summary_state, deferred_logger); if (bhp_stable.has_value() && cur_bhp - bhp_stable.value() > cur_bhp*reltol){
const bool converged_bhp1 = solveWellWithBhp(ebos_simulator, dt, bhp_stable.value(), well_state, deferred_logger); const bool converged_bhp = solveWellWithBhp(ebos_simulator, dt, bhp_stable.value(), well_state, deferred_logger);
if (!converged_bhp) { // re-solve with hopefully good initial guess
// ws.thp = this->getTHPConstraint(summary_state);
} else {
// re-solve well equations
// XXX reset thp
well_state.well(this->index_of_well_).thp = this->getTHPConstraint(summary_state);
converged = this->iterateWellEqWithSwitching(ebos_simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger); converged = this->iterateWellEqWithSwitching(ebos_simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
} }
} }
} }
} else if (!converged) { }
if (!converged) {
// Well did not converge, switch to explicit fractions // Well did not converge, switch to explicit fractions
this->operability_status_.use_vfpexplicit = true; this->operability_status_.use_vfpexplicit = true;
//auto well_state_copy = well_state;
//
this->openWell(); this->openWell();
auto bhp_target = estimateOperableBhp(ebos_simulator, dt, well_state, group_state, summary_state, deferred_logger); auto bhp_target = estimateOperableBhp(ebos_simulator, dt, well_state, group_state, summary_state, deferred_logger);
if (!bhp_target.has_value()) { if (!bhp_target.has_value()) {
// well can't operate using explicit fractions // well can't operate using explicit fractions
is_operable = false; is_operable = false;
// XXX convereged = true - iterate with closed well! // solve with zero rate
converged = solveWellWithZeroRate(ebos_simulator, dt, well_state, deferred_logger); converged = solveWellWithZeroRate(ebos_simulator, dt, well_state, deferred_logger);
this->stopWell();
} else { } else {
// first solve well equations for bhp = bhp_target which should give solution close to actual // solve well with the estimated target bhp (or limit)
converged = solveWellWithBhp(ebos_simulator, dt, bhp_target.value(), well_state, deferred_logger); const double bhp = std::max(bhp_target.value(), prod_controls.bhp_limit);
const bool converged_bhp = solveWellWithBhp(ebos_simulator, dt, bhp, well_state, deferred_logger);
ws.thp = this->getTHPConstraint(summary_state);
converged = this->iterateWellEqWithSwitching(ebos_simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
/*
if (!converged) { if (!converged) {
// debug // debug
} else { } else {
// re-solve well equations // re-solve well equations
// XXX reset thp // XXX reset thp
well_state.well(this->index_of_well_).thp = this->getTHPConstraint(summary_state); well_state.well(this->index_of_well_).thp = this->getTHPConstraint(summary_state);
converged = this->iterateWellEqWithSwitching(ebos_simulator, dt, inj_controls, prod_controls, well_state, group_state, deferred_logger);
} }
*/
} }
} }
if (!is_operable) { // update operability
this->stopWell(); this->operability_status_.can_obtain_bhp_with_thp_limit = is_operable;
if (this->wellHasTHPConstraints(summary_state)){ this->operability_status_.obey_thp_limit_under_bhp_limit = is_operable;
this->operability_status_.can_obtain_bhp_with_thp_limit = false;
this->operability_status_.obey_thp_limit_under_bhp_limit = false;
} else {
this->operability_status_.operable_under_only_bhp_limit = false;
}
}
return converged; return converged;
} }