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) {
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->solveWellEquation(simulator_, this->wellState(), this->groupState(), local_deferredLogger);
} catch (const std::exception& e) {
@ -1846,7 +1846,7 @@ namespace Opm {
ws.injection_cmode == Well::InjectorCMode::GRUP)
{
well->updateWellStateWithTarget(simulator_, this->groupState(),
this->wellState(), deferred_logger);
this->wellState(), deferred_logger, /*initialize*/ false);
}
}
OPM_END_PARALLEL_TRY_CATCH("BlackoilWellModel::updateAndCommunicate failed: ",
@ -2067,7 +2067,7 @@ namespace Opm {
for (const auto& well : well_container_) {
auto& events = this->wellState().well(well->indexOfWell()).events;
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);
// 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.

View File

@ -90,7 +90,8 @@ namespace Opm {
void updateWellStateWithTarget(const Simulator& simulator,
const GroupState<Scalar>& group_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
ConvergenceReport getWellConvergence(const Simulator& simulator,

View File

@ -169,15 +169,18 @@ namespace Opm
updateWellStateWithTarget(const Simulator& simulator,
const GroupState<Scalar>& group_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
// and segment pressure based on bhp
this->scaleSegmentRatesWithWellRates(this->segments_.inlets(),
this->segments_.perforations(),
well_state);
this->scaleSegmentPressuresWithBhp(well_state);
if (initialize) {
this->scaleSegmentRatesWithWellRates(this->segments_.inlets(),
this->segments_.perforations(),
well_state);
this->scaleSegmentPressuresWithBhp(well_state);
}
}

View File

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

View File

@ -263,7 +263,7 @@ namespace Opm
deferred_logger.debug(ss.str());
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);
}
@ -326,7 +326,7 @@ namespace Opm
ws.production_cmode == Well::ProducerCMode::THP;
if (!thp_controlled){
// 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 {
ws.thp = this->getTHPConstraint(summary_state);
}
@ -397,7 +397,7 @@ namespace Opm
WellState<Scalar> well_state_copy = well_state;
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);
updatePrimaryVariables(simulator, well_state_copy, deferred_logger);
@ -1147,7 +1147,8 @@ namespace Opm
updateWellStateWithTarget(const Simulator& simulator,
const GroupState<Scalar>& group_state,
WellState<Scalar>& well_state,
DeferredLogger& deferred_logger) const
DeferredLogger& deferred_logger,
const bool initialize)
{
OPM_TIMEFUNCTION();
// only bhp and wellRates are used to initilize the primaryvariables for standard wells
@ -1221,39 +1222,42 @@ namespace Opm
}
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);
// 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;
if (initialize) {
auto rates = ws.surface_rates;
Scalar bhp = WellBhpThpCalculator(*this).calculateBhpFromThp(well_state,
rates,
well,
summaryState,
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;
}
case Well::InjectorCMode::BHP:
{
ws.bhp = controls.bhp_limit;
Scalar total_rate = 0.0;
for (int p = 0; p<np; ++p) {
total_rate += ws.surface_rates[p];
if (initialize) {
Scalar total_rate = 0.0;
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;
}
case Well::InjectorCMode::GRUP:
@ -1441,41 +1445,53 @@ namespace Opm
case Well::ProducerCMode::BHP:
{
ws.bhp = controls.bhp_limit;
Scalar total_rate = 0.0;
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){
if (initialize) {
Scalar total_rate = 0.0;
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;
}
case Well::ProducerCMode::THP:
{
const bool update_success = updateWellStateWithTHPTargetProd(simulator, well_state, deferred_logger);
if (!update_success) {
// the following is the original way of initializing well state with THP constraint
// keeping it for robust reason in case that it fails to get a bhp value with THP constraint
// more sophisticated design might be needed in the future
auto rates = ws.surface_rates;
this->adaptRatesForVFP(rates);
const Scalar bhp = WellBhpThpCalculator(*this).calculateBhpFromThp(
well_state, rates, well, summaryState, this->getRefDensity(), deferred_logger);
ws.bhp = bhp;
ws.thp = this->getTHPConstraint(summaryState);
// 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];
{
ws.thp = this->getTHPConstraint(summaryState);
if (initialize) {
const double dt = simulator.timeStepSize();
auto bhp_target = estimateOperableBhp(simulator, dt, well_state, summaryState, deferred_logger);
if (bhp_target.has_value()) {
const Scalar bhp = std::max(bhp_target.value(), static_cast<Scalar>(controls.bhp_limit));
solveWellWithBhp(simulator, dt, bhp, well_state, deferred_logger);
} else {
deferred_logger.debug("Did not find operable bhp for well " + this->name() + ", re-trying initialization." );
const bool update_success = updateWellStateWithTHPTargetProd(simulator, well_state, deferred_logger);
if (!update_success) {
// the following is the original way of initializing well state with THP constraint
// keeping it for robust reason in case that it fails to get a bhp value with THP constraint
// more sophisticated design might be needed in the future
auto rates = ws.surface_rates;
this->adaptRatesForVFP(rates);
const Scalar bhp = WellBhpThpCalculator(*this).calculateBhpFromThp(
well_state, rates, well, summaryState, this->getRefDensity(), deferred_logger);
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];
}
}
}
}
}