This commit is contained in:
Stein Krogstad 2025-02-14 22:31:04 +01:00 committed by GitHub
commit 77b95eebcf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 90 additions and 69 deletions

View File

@ -507,7 +507,7 @@ namespace Opm {
if (event || dyn_status_change) { if (event || dyn_status_change) {
try { try {
well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), local_deferredLogger); well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), local_deferredLogger, /*initialize*/ true);
well->calculateExplicitQuantities(simulator_, this->wellState(), local_deferredLogger); well->calculateExplicitQuantities(simulator_, this->wellState(), local_deferredLogger);
well->solveWellEquation(simulator_, this->wellState(), this->groupState(), local_deferredLogger); well->solveWellEquation(simulator_, this->wellState(), this->groupState(), local_deferredLogger);
} catch (const std::exception& e) { } catch (const std::exception& e) {
@ -1846,7 +1846,7 @@ namespace Opm {
ws.injection_cmode == Well::InjectorCMode::GRUP) ws.injection_cmode == Well::InjectorCMode::GRUP)
{ {
well->updateWellStateWithTarget(simulator_, this->groupState(), well->updateWellStateWithTarget(simulator_, this->groupState(),
this->wellState(), deferred_logger); this->wellState(), deferred_logger, /*initialize*/ false);
} }
} }
OPM_END_PARALLEL_TRY_CATCH("BlackoilWellModel::updateAndCommunicate failed: ", OPM_END_PARALLEL_TRY_CATCH("BlackoilWellModel::updateAndCommunicate failed: ",
@ -2067,7 +2067,7 @@ namespace Opm {
for (const auto& well : well_container_) { for (const auto& well : well_container_) {
auto& events = this->wellState().well(well->indexOfWell()).events; auto& events = this->wellState().well(well->indexOfWell()).events;
if (events.hasEvent(WellState<Scalar>::event_mask)) { if (events.hasEvent(WellState<Scalar>::event_mask)) {
well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), deferred_logger); well->updateWellStateWithTarget(simulator_, this->groupState(), this->wellState(), deferred_logger, /*initialize*/ true);
well->updatePrimaryVariables(simulator_, this->wellState(), deferred_logger); well->updatePrimaryVariables(simulator_, this->wellState(), deferred_logger);
// There is no new well control change input within a report step, // There is no new well control change input within a report step,
// so next time step, the well does not consider to have effective events anymore. // so next time step, the well does not consider to have effective events anymore.

View File

@ -90,7 +90,8 @@ namespace Opm {
void updateWellStateWithTarget(const Simulator& simulator, void updateWellStateWithTarget(const Simulator& simulator,
const GroupState<Scalar>& group_state, const GroupState<Scalar>& group_state,
WellState<Scalar>& well_state, WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) const override; DeferredLogger& deferred_logger,
const bool initialize = true) override;
/// check whether the well equations get converged for this well /// check whether the well equations get converged for this well
ConvergenceReport getWellConvergence(const Simulator& simulator, ConvergenceReport getWellConvergence(const Simulator& simulator,

View File

@ -169,15 +169,18 @@ namespace Opm
updateWellStateWithTarget(const Simulator& simulator, updateWellStateWithTarget(const Simulator& simulator,
const GroupState<Scalar>& group_state, const GroupState<Scalar>& group_state,
WellState<Scalar>& well_state, WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) const DeferredLogger& deferred_logger,
const bool initialize)
{ {
Base::updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger); Base::updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger, initialize);
// scale segment rates based on the wellRates // scale segment rates based on the wellRates
// and segment pressure based on bhp // and segment pressure based on bhp
this->scaleSegmentRatesWithWellRates(this->segments_.inlets(), if (initialize) {
this->segments_.perforations(), this->scaleSegmentRatesWithWellRates(this->segments_.inlets(),
well_state); this->segments_.perforations(),
this->scaleSegmentPressuresWithBhp(well_state); well_state);
this->scaleSegmentPressuresWithBhp(well_state);
}
} }

View File

@ -215,7 +215,8 @@ public:
virtual void updateWellStateWithTarget(const Simulator& simulator, virtual void updateWellStateWithTarget(const Simulator& simulator,
const GroupState<Scalar>& group_state, const GroupState<Scalar>& group_state,
WellState<Scalar>& well_state, WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) const; DeferredLogger& deferred_logger,
const bool initialize = true);
virtual void computeWellRatesWithBhpIterations(const Simulator& simulator, virtual void computeWellRatesWithBhpIterations(const Simulator& simulator,
const Scalar& bhp, const Scalar& bhp,

View File

@ -263,7 +263,7 @@ namespace Opm
deferred_logger.debug(ss.str()); deferred_logger.debug(ss.str());
this->well_control_log_.push_back(from); this->well_control_log_.push_back(from);
updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger); updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger, /*initialize*/ false);
updatePrimaryVariables(simulator, well_state, deferred_logger); updatePrimaryVariables(simulator, well_state, deferred_logger);
} }
@ -326,7 +326,7 @@ namespace Opm
ws.production_cmode == Well::ProducerCMode::THP; ws.production_cmode == Well::ProducerCMode::THP;
if (!thp_controlled){ if (!thp_controlled){
// don't call for thp since this might trigger additional local solve // don't call for thp since this might trigger additional local solve
updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger); updateWellStateWithTarget(simulator, group_state, well_state, deferred_logger, /*initialize*/ false);
} else { } else {
ws.thp = this->getTHPConstraint(summary_state); ws.thp = this->getTHPConstraint(summary_state);
} }
@ -397,7 +397,7 @@ namespace Opm
WellState<Scalar> well_state_copy = well_state; WellState<Scalar> well_state_copy = well_state;
auto& ws = well_state_copy.well(this->indexOfWell()); auto& ws = well_state_copy.well(this->indexOfWell());
updateWellStateWithTarget(simulator, group_state, well_state_copy, deferred_logger); updateWellStateWithTarget(simulator, group_state, well_state_copy, deferred_logger, /*initialize*/ true);
calculateExplicitQuantities(simulator, well_state_copy, deferred_logger); calculateExplicitQuantities(simulator, well_state_copy, deferred_logger);
updatePrimaryVariables(simulator, well_state_copy, deferred_logger); updatePrimaryVariables(simulator, well_state_copy, deferred_logger);
@ -1147,7 +1147,8 @@ namespace Opm
updateWellStateWithTarget(const Simulator& simulator, updateWellStateWithTarget(const Simulator& simulator,
const GroupState<Scalar>& group_state, const GroupState<Scalar>& group_state,
WellState<Scalar>& well_state, WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) const DeferredLogger& deferred_logger,
const bool initialize)
{ {
OPM_TIMEFUNCTION(); OPM_TIMEFUNCTION();
// only bhp and wellRates are used to initilize the primaryvariables for standard wells // only bhp and wellRates are used to initilize the primaryvariables for standard wells
@ -1221,39 +1222,42 @@ namespace Opm
} }
case Well::InjectorCMode::THP: case Well::InjectorCMode::THP:
{ {
auto rates = ws.surface_rates;
Scalar bhp = WellBhpThpCalculator(*this).calculateBhpFromThp(well_state,
rates,
well,
summaryState,
this->getRefDensity(),
deferred_logger);
ws.bhp = bhp;
ws.thp = this->getTHPConstraint(summaryState); ws.thp = this->getTHPConstraint(summaryState);
if (initialize) {
// if the total rates are negative or zero auto rates = ws.surface_rates;
// we try to provide a better intial well rate Scalar bhp = WellBhpThpCalculator(*this).calculateBhpFromThp(well_state,
// using the well potentials rates,
Scalar total_rate = std::accumulate(rates.begin(), rates.end(), 0.0); well,
if (total_rate <= 0.0) summaryState,
ws.surface_rates = ws.well_potentials; this->getRefDensity(),
deferred_logger);
ws.bhp = bhp;
// if the total rates are negative or zero
// we try to provide a better intial well rate
// using the well potentials
Scalar total_rate = std::accumulate(rates.begin(), rates.end(), 0.0);
if (total_rate <= 0.0)
ws.surface_rates = ws.well_potentials;
}
break; break;
} }
case Well::InjectorCMode::BHP: case Well::InjectorCMode::BHP:
{ {
ws.bhp = controls.bhp_limit; ws.bhp = controls.bhp_limit;
Scalar total_rate = 0.0; if (initialize) {
for (int p = 0; p<np; ++p) { Scalar total_rate = 0.0;
total_rate += ws.surface_rates[p]; for (int p = 0; p<np; ++p) {
total_rate += ws.surface_rates[p];
}
// if the total rates are negative or zero
// we try to provide a better intial well rate
// using the well potentials
if (total_rate <= 0.0)
ws.surface_rates = ws.well_potentials;
} }
// if the total rates are negative or zero
// we try to provide a better intial well rate
// using the well potentials
if (total_rate <= 0.0)
ws.surface_rates = ws.well_potentials;
break; break;
} }
case Well::InjectorCMode::GRUP: case Well::InjectorCMode::GRUP:
@ -1441,41 +1445,53 @@ namespace Opm
case Well::ProducerCMode::BHP: case Well::ProducerCMode::BHP:
{ {
ws.bhp = controls.bhp_limit; ws.bhp = controls.bhp_limit;
Scalar total_rate = 0.0; if (initialize) {
for (int p = 0; p<np; ++p) { Scalar total_rate = 0.0;
total_rate -= ws.surface_rates[p];
}
// if the total rates are negative or zero
// we try to provide a better intial well rate
// using the well potentials
if (total_rate <= 0.0){
for (int p = 0; p<np; ++p) { for (int p = 0; p<np; ++p) {
ws.surface_rates[p] = -ws.well_potentials[p]; total_rate -= ws.surface_rates[p];
}
// if the total rates are negative or zero
// we try to provide a better intial well rate
// using the well potentials
if (total_rate <= 0.0){
for (int p = 0; p<np; ++p) {
ws.surface_rates[p] = -ws.well_potentials[p];
}
} }
} }
break; break;
} }
case Well::ProducerCMode::THP: case Well::ProducerCMode::THP:
{ {
const bool update_success = updateWellStateWithTHPTargetProd(simulator, well_state, deferred_logger); ws.thp = this->getTHPConstraint(summaryState);
if (initialize) {
if (!update_success) { const double dt = simulator.timeStepSize();
// the following is the original way of initializing well state with THP constraint auto bhp_target = estimateOperableBhp(simulator, dt, well_state, summaryState, deferred_logger);
// keeping it for robust reason in case that it fails to get a bhp value with THP constraint if (bhp_target.has_value()) {
// more sophisticated design might be needed in the future const Scalar bhp = std::max(bhp_target.value(), static_cast<Scalar>(controls.bhp_limit));
auto rates = ws.surface_rates; solveWellWithBhp(simulator, dt, bhp, well_state, deferred_logger);
this->adaptRatesForVFP(rates); } else {
const Scalar bhp = WellBhpThpCalculator(*this).calculateBhpFromThp( deferred_logger.debug("Did not find operable bhp for well " + this->name() + ", re-trying initialization." );
well_state, rates, well, summaryState, this->getRefDensity(), deferred_logger); const bool update_success = updateWellStateWithTHPTargetProd(simulator, well_state, deferred_logger);
ws.bhp = bhp; if (!update_success) {
ws.thp = this->getTHPConstraint(summaryState); // the following is the original way of initializing well state with THP constraint
// if the total rates are negative or zero // keeping it for robust reason in case that it fails to get a bhp value with THP constraint
// we try to provide a better initial well rate // more sophisticated design might be needed in the future
// using the well potentials auto rates = ws.surface_rates;
const Scalar total_rate = -std::accumulate(rates.begin(), rates.end(), 0.0); this->adaptRatesForVFP(rates);
if (total_rate <= 0.0) { const Scalar bhp = WellBhpThpCalculator(*this).calculateBhpFromThp(
for (int p = 0; p < this->number_of_phases_; ++p) { well_state, rates, well, summaryState, this->getRefDensity(), deferred_logger);
ws.surface_rates[p] = -ws.well_potentials[p]; ws.bhp = bhp;
// if the total rates are negative or zero
// we try to provide a better initial well rate
// using the well potentials
const Scalar total_rate = -std::accumulate(rates.begin(), rates.end(), 0.0);
if (total_rate <= 0.0) {
for (int p = 0; p < this->number_of_phases_; ++p) {
ws.surface_rates[p] = -ws.well_potentials[p];
}
}
} }
} }
} }