Address PR comments

This commit is contained in:
Tor Harald Sandve 2019-05-24 16:45:27 +02:00
parent 821794b0ad
commit 613473082f
10 changed files with 195 additions and 214 deletions

View File

@ -337,11 +337,9 @@ namespace Opm {
// xw to update Well State
void recoverWellSolutionAndUpdateWellState(const BVector& x);
void updateWellControls(const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger);
void updateWellControls(Opm::DeferredLogger& deferred_logger);
void updateGroupControls(const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger);
void updateGroupControls(Opm::DeferredLogger& deferred_logger);
// setting the well_solutions_ based on well_state.
void updatePrimaryVariables(Opm::DeferredLogger& deferred_logger);
@ -389,8 +387,7 @@ namespace Opm {
// some preparation work, mostly related to group control and RESV,
// at the beginning of each time step (Not report step)
void prepareTimeStep(const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger);
void prepareTimeStep(Opm::DeferredLogger& deferred_logger);
void prepareGroupControl(Opm::DeferredLogger& deferred_logger);

View File

@ -681,18 +681,18 @@ namespace Opm {
int exception_thrown = 0;
try {
std::vector< Scalar > B_avg(numComponents(), Scalar() );
computeAverageFormationFactor(B_avg);
if (iterationIdx == 0) {
calculateExplicitQuantities(local_deferredLogger);
prepareTimeStep(B_avg, local_deferredLogger);
prepareTimeStep(local_deferredLogger);
}
updateWellControls(B_avg, local_deferredLogger);
updateWellControls(local_deferredLogger);
// Set the well primary variables based on the value of well solutions
initPrimaryVariablesEvaluation();
std::vector< Scalar > B_avg(numComponents(), Scalar() );
computeAverageFormationFactor(B_avg);
if (param_.solve_welleq_initially_ && iterationIdx == 0) {
// solve the well equations as a pre-processing step
last_report_ = solveWellEq(B_avg, dt, local_deferredLogger);
@ -701,7 +701,7 @@ namespace Opm {
if (initial_step_) {
// update the explicit quantities to get the initial fluid distribution in the well correct.
calculateExplicitQuantities(local_deferredLogger);
prepareTimeStep(B_avg, local_deferredLogger);
prepareTimeStep(local_deferredLogger);
last_report_ = solveWellEq(B_avg, dt, local_deferredLogger);
initial_step_ = false;
}
@ -923,7 +923,7 @@ namespace Opm {
// are active wells anywhere in the global domain.
if( wellsActive() )
{
updateWellControls(B_avg, deferred_logger);
updateWellControls(deferred_logger);
initPrimaryVariablesEvaluation();
}
} catch (std::exception& e) {
@ -1027,8 +1027,7 @@ namespace Opm {
template<typename TypeTag>
void
BlackoilWellModel<TypeTag>::
updateWellControls(const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger)
updateWellControls(Opm::DeferredLogger& deferred_logger)
{
// Even if there are no wells active locally, we cannot
// return as the DeferredLogger uses global communication.
@ -1036,10 +1035,10 @@ namespace Opm {
if( !wellsActive() ) return ;
for (const auto& well : well_container_) {
well->updateWellControl(ebosSimulator_, B_avg, well_state_, deferred_logger);
well->updateWellControl(ebosSimulator_, well_state_, deferred_logger);
}
updateGroupControls(B_avg, deferred_logger);
updateGroupControls(deferred_logger);
}
@ -1171,8 +1170,7 @@ namespace Opm {
template<typename TypeTag>
void
BlackoilWellModel<TypeTag>::
prepareTimeStep(const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger)
prepareTimeStep(Opm::DeferredLogger& deferred_logger)
{
if ( wellCollection().havingVREPGroups() ) {
@ -1193,7 +1191,7 @@ namespace Opm {
int exception_thrown = 0;
try {
for (const auto& well : well_container_) {
well->checkWellOperability(ebosSimulator_, B_avg, well_state_, deferred_logger);
well->checkWellOperability(ebosSimulator_, well_state_, deferred_logger);
}
// since the controls are all updated, we should update well_state accordingly
for (const auto& well : well_container_) {
@ -1205,7 +1203,7 @@ namespace Opm {
if (!well->isOperable() ) continue;
if (well_state_.effectiveEventsOccurred(w) ) {
well->updateWellStateWithTarget(ebosSimulator_, B_avg, well_state_, deferred_logger);
well->updateWellStateWithTarget(ebosSimulator_, well_state_, deferred_logger);
}
// there is no new well control change input within a report step,
@ -1433,8 +1431,7 @@ namespace Opm {
template<typename TypeTag>
void
BlackoilWellModel<TypeTag>::
updateGroupControls(const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger)
updateGroupControls(Opm::DeferredLogger& deferred_logger)
{
if (wellCollection().groupControlActive()) {
@ -1461,7 +1458,7 @@ namespace Opm {
// TODO: we should only do the well is involved in the update group targets
for (auto& well : well_container_) {
well->updateWellStateWithTarget(ebosSimulator_, B_avg, well_state_, deferred_logger);
well->updateWellStateWithTarget(ebosSimulator_, well_state_, deferred_logger);
well->updatePrimaryVariables(well_state_, deferred_logger);
}
}

View File

@ -120,9 +120,8 @@ namespace Opm
/// updating the well state based the current control mode
virtual void updateWellStateWithTarget(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) override;
Opm::DeferredLogger& deferred_logger) const override;
/// check whether the well equations get converged for this well
virtual ConvergenceReport getWellConvergence(const std::vector<double>& B_avg, Opm::DeferredLogger& deferred_logger) const override;
@ -331,12 +330,11 @@ namespace Opm
const int perf,
std::vector<EvalWell>& mob) const;
virtual void computeWellRatesWithBhp(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
const bool iterate,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger) override;
void computeWellRatesWithBhpPotential(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger);
void assembleControlEq(Opm::DeferredLogger& deferred_logger) const;
@ -356,7 +354,6 @@ namespace Opm
// checking the operability of the well based on current reservoir condition
// it is not implemented for multisegment well yet
virtual void checkWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& well_state,
Opm::DeferredLogger& deferred_logger) override;

View File

@ -260,9 +260,8 @@ namespace Opm
void
MultisegmentWell<TypeTag>::
updateWellStateWithTarget(const Simulator& /* ebos_simulator */,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& /* deferred_logger */)
Opm::DeferredLogger& /* deferred_logger */) const
{
// Updating well state bas on well control
// Target values are used as initial conditions for BHP, THP, and SURFACE_RATE
@ -564,7 +563,7 @@ namespace Opm
if ( !Base::wellHasTHPConstraints() ) {
assert(std::abs(bhp) != std::numeric_limits<double>::max());
computeWellRatesWithBhp(ebosSimulator, B_avg, bhp, /*iterate=*/ true, well_potentials, deferred_logger);
computeWellRatesWithBhpPotential(ebosSimulator, B_avg, bhp, well_potentials, deferred_logger);
} else {
const std::string msg = std::string("Well potential calculation is not supported for thp controlled multisegment wells \n")
@ -582,23 +581,29 @@ namespace Opm
template<typename TypeTag>
void
MultisegmentWell<TypeTag>::
computeWellRatesWithBhp(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
const bool iterate,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger)
computeWellRatesWithBhpPotential(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger)
{
WellControls* wc = well_controls_;
const int bhp_index = Base::getControlIndex(BHP);
const double orig_bhp = well_controls_iget_target(wc, bhp_index);
const auto orig_current = well_controls_get_current(wc);
well_controls_iset_target(wc, bhp_index, bhp);
well_controls_set_current(wc, bhp_index);
// store a copy of the well state, we don't want to update the real well state
WellState copy = ebosSimulator.problem().wellModel().wellState();
initPrimaryVariablesEvaluation();
if (iterate) {
const double dt = ebosSimulator.timeStepSize();
// iterate to get a solution that satisfies the bhp potential.
iterateWellEquations(ebosSimulator, B_avg, dt, copy, deferred_logger);
}
const double dt = ebosSimulator.timeStepSize();
// iterate to get a solution that satisfies the bhp potential.
iterateWellEquations(ebosSimulator, B_avg, dt, copy, deferred_logger);
// compute the potential and store in the flux vector.
const int np = number_of_phases_;
@ -608,6 +613,10 @@ namespace Opm
well_flux[ebosCompIdxToFlowCompIdx(compIdx)] += rate.value();
}
// reset bhp limit
well_controls_iset_target(wc, bhp_index, orig_bhp);
well_controls_set_current(wc, orig_current);
}
@ -1748,7 +1757,6 @@ namespace Opm
void
MultisegmentWell<TypeTag>::
checkWellOperability(const Simulator& /* ebos_simulator */,
const std::vector<Scalar>& /*B_avg */,
const WellState& /* well_state */,
Opm::DeferredLogger& deferred_logger)
{
@ -1905,7 +1913,7 @@ namespace Opm
updateWellState(dx_well, well_state, deferred_logger, relaxation_factor);
// TODO: should we do something more if a switching of control happens
this->updateWellControl(ebosSimulator, B_avg, well_state, deferred_logger);
this->updateWellControl(ebosSimulator, well_state, deferred_logger);
initPrimaryVariablesEvaluation();
}

View File

@ -148,9 +148,8 @@ namespace Opm
Opm::DeferredLogger& deferred_logger) override;
virtual void updateWellStateWithTarget(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) override;
Opm::DeferredLogger& deferred_logger) const override;
/// check whether the well equations get converged for this well
virtual ConvergenceReport getWellConvergence(const std::vector<double>& B_avg,
@ -329,12 +328,16 @@ namespace Opm
double& perf_vap_oil_rate,
Opm::DeferredLogger& deferred_logger) const;
virtual void computeWellRatesWithBhp(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
void computeWellRatesWithBhp(const Simulator& ebosSimulator,
const double& bhp,
const bool iterate,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger) override;
Opm::DeferredLogger& deferred_logger) const;
void computeWellRatesWithBhpPotential(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger);
std::vector<double> computeWellPotentialWithTHP(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
@ -376,7 +379,6 @@ namespace Opm
// update the operability status of the well is operable under the current reservoir condition
// mostly related to BHP limit and THP limit
virtual void checkWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& well_state,
Opm::DeferredLogger& deferred_logger
) override;
@ -384,29 +386,24 @@ namespace Opm
// check whether the well is operable under the current reservoir condition
// mostly related to BHP limit and THP limit
void updateWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& well_state,
Opm::DeferredLogger& deferred_logger
);
// check whether the well is operable under BHP limit with current reservoir condition
void checkOperabilityUnderBHPLimitProducer(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger);
void checkOperabilityUnderBHPLimitProducer(const Simulator& ebos_simulator, Opm::DeferredLogger& deferred_logger);
// check whether the well is operable under THP limit with current reservoir condition
void checkOperabilityUnderTHPLimitProducer(const Simulator& ebos_simulator, Opm::DeferredLogger& deferred_logger);
// update WellState based on IPR and associated VFP table
void updateWellStateWithTHPTargetIPR(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger);
Opm::DeferredLogger& deferred_logger) const;
void updateWellStateWithTHPTargetIPRProducer(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger);
Opm::DeferredLogger& deferred_logger) const;
// for a well, when all drawdown are in the wrong direction, then this well will not
// be able to produce/inject .

View File

@ -149,9 +149,8 @@ namespace Opm
Opm::DeferredLogger& deferred_logger) override;
virtual void updateWellStateWithTarget(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) override;
Opm::DeferredLogger& deferred_logger) const override;
/// check whether the well equations get converged for this well
virtual ConvergenceReport getWellConvergence(const std::vector<double>& B_avg, Opm::DeferredLogger& deferred_logger) const override;
@ -332,12 +331,16 @@ namespace Opm
double& perf_vap_oil_rate,
Opm::DeferredLogger& deferred_logger) const;
virtual void computeWellRatesWithBhp(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
void computeWellRatesWithBhp(const Simulator& ebosSimulator,
const double& bhp,
const bool iterate,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger) override;
Opm::DeferredLogger& deferred_logger) const;
void computeWellRatesWithBhpPotential(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger);
std::vector<double> computeWellPotentialWithTHP(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
@ -379,35 +382,29 @@ namespace Opm
// update the operability status of the well is operable under the current reservoir condition
// mostly related to BHP limit and THP limit
virtual void checkWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& well_state,
Opm::DeferredLogger& deferred_logger) override;
// check whether the well is operable under the current reservoir condition
// mostly related to BHP limit and THP limit
void updateWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& well_state,
Opm::DeferredLogger& deferred_logger);
// check whether the well is operable under BHP limit with current reservoir condition
void checkOperabilityUnderBHPLimitProducer(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger);
void checkOperabilityUnderBHPLimitProducer(const Simulator& ebos_simulator, Opm::DeferredLogger& deferred_logger);
// check whether the well is operable under THP limit with current reservoir condition
void checkOperabilityUnderTHPLimitProducer(const Simulator& ebos_simulator, Opm::DeferredLogger& deferred_logger);
// update WellState based on IPR and associated VFP table
void updateWellStateWithTHPTargetIPR(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger);
Opm::DeferredLogger& deferred_logger) const;
void updateWellStateWithTHPTargetIPRProducer(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger);
Opm::DeferredLogger& deferred_logger) const;
// for a well, when all drawdown are in the wrong direction, then this well will not
// be able to produce/inject .

View File

@ -480,7 +480,7 @@ namespace Opm
void
StandardWellV<TypeTag>::
assembleWellEq(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const std::vector<Scalar>& /* B_avg */,
const double dt,
WellState& well_state,
Opm::DeferredLogger& deferred_logger
@ -488,7 +488,7 @@ namespace Opm
{
// TODO: only_wells should be put back to save some computation
checkWellOperability(ebosSimulator, B_avg, well_state, deferred_logger);
checkWellOperability(ebosSimulator, well_state, deferred_logger);
if (!this->isOperable()) return;
@ -1194,9 +1194,8 @@ namespace Opm
void
StandardWellV<TypeTag>::
updateWellStateWithTarget(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger)
Opm::DeferredLogger& deferred_logger) const
{
// number of phases
const int np = number_of_phases_;
@ -1221,7 +1220,7 @@ namespace Opm
case THP: {
// when a well can not work under THP target, it switches to BHP control
if (this->operability_status_.isOperableUnderTHPLimit() ) {
updateWellStateWithTHPTargetIPR(ebos_simulator, B_avg, well_state, deferred_logger);
updateWellStateWithTHPTargetIPR(ebos_simulator, well_state, deferred_logger);
} else { // go to BHP limit
assert(this->operability_status_.isOperableUnderBHPLimit() );
@ -1399,7 +1398,6 @@ namespace Opm
void
StandardWellV<TypeTag>::
checkWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& well_state,
Opm::DeferredLogger& deferred_logger)
{
@ -1414,7 +1412,7 @@ namespace Opm
const bool old_well_operable = this->operability_status_.isOperable();
updateWellOperability(ebos_simulator, B_avg, well_state, deferred_logger);
updateWellOperability(ebos_simulator, well_state, deferred_logger);
const bool well_operable = this->operability_status_.isOperable();
@ -1433,7 +1431,6 @@ namespace Opm
void
StandardWellV<TypeTag>::
updateWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& /* well_state */,
Opm::DeferredLogger& deferred_logger)
{
@ -1442,7 +1439,7 @@ namespace Opm
updateIPR(ebos_simulator, deferred_logger);
// checking the BHP limit related
checkOperabilityUnderBHPLimitProducer(ebos_simulator, B_avg, deferred_logger);
checkOperabilityUnderBHPLimitProducer(ebos_simulator, deferred_logger);
// checking whether the well can operate under the THP constraints.
if (this->wellHasTHPConstraints()) {
@ -1457,9 +1454,7 @@ namespace Opm
template<typename TypeTag>
void
StandardWellV<TypeTag>::
checkOperabilityUnderBHPLimitProducer(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger)
checkOperabilityUnderBHPLimitProducer(const Simulator& ebos_simulator, Opm::DeferredLogger& deferred_logger)
{
const double bhp_limit = mostStrictBhpFromBhpLimits(deferred_logger);
// Crude but works: default is one atmosphere.
@ -1483,7 +1478,7 @@ namespace Opm
// option 2: stick with the above IPR curve
// we use IPR here
std::vector<double> well_rates_bhp_limit;
computeWellRatesWithBhp(ebos_simulator, B_avg, bhp_limit, /*iterate=*/false, well_rates_bhp_limit, deferred_logger);
computeWellRatesWithBhp(ebos_simulator, bhp_limit, well_rates_bhp_limit, deferred_logger);
const double thp = calculateThpFromBhp(well_rates_bhp_limit, bhp_limit, deferred_logger);
const double thp_limit = this->getTHPConstraint(deferred_logger);
@ -1588,7 +1583,7 @@ namespace Opm
{
const double bhp = well_state.bhp()[index_of_well_];
std::vector<double> well_rates;
computeWellRatesWithBhp(ebos_simulator, bhp, /*iterate=*/ false, well_rates, deferred_logger);
computeWellRatesWithBhp(ebos_simulator, bhp, well_rates, deferred_logger);
const double sign = (well_type_ == PRODUCER) ? -1. : 1.;
const double threshold = sign * std::numeric_limits<double>::min();
@ -1631,13 +1626,11 @@ namespace Opm
void
StandardWellV<TypeTag>::
updateWellStateWithTHPTargetIPR(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger)
Opm::DeferredLogger& deferred_logger) const
{
if (well_type_ == PRODUCER) {
updateWellStateWithTHPTargetIPRProducer(ebos_simulator,
B_avg,
well_state,
deferred_logger);
}
@ -1657,9 +1650,8 @@ namespace Opm
void
StandardWellV<TypeTag>::
updateWellStateWithTHPTargetIPRProducer(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger)
Opm::DeferredLogger& deferred_logger) const
{
well_state.thp()[index_of_well_] = this->getTHPConstraint(deferred_logger);
@ -1675,7 +1667,7 @@ namespace Opm
initPrimaryVariablesEvaluation();
std::vector<double> rates;
computeWellRatesWithBhp(ebos_simulator, B_avg, bhp, /*iterate=*/false, rates, deferred_logger);
computeWellRatesWithBhp(ebos_simulator, bhp, rates, deferred_logger);
// TODO: double checke the obtained rates
// this is another places we might obtain negative rates
@ -2271,42 +2263,13 @@ namespace Opm
void
StandardWellV<TypeTag>::
computeWellRatesWithBhp(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
const bool iterate,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger)
Opm::DeferredLogger& deferred_logger) const
{
const int np = number_of_phases_;
well_flux.resize(np, 0.0);
WellControls* wc = well_controls_;
const int bhp_index = Base::getControlIndex(BHP);
const double orig_bhp = well_controls_iget_target(wc, bhp_index);
const auto orig_current = well_controls_get_current(wc);
well_controls_iset_target(wc, bhp_index, bhp);
well_controls_set_current(wc, bhp_index);
// iterate to get a more accurate well density
if (iterate) {
// create a copy of the well_state to use. If the operability checking is sucessful, we use this one
// to replace the original one
WellState well_state_copy = ebosSimulator.problem().wellModel().wellState();
well_state_copy.currentControls()[index_of_well_] = bhp_index;
bool converged = this->solveWellEqUntilConverged(ebosSimulator, B_avg, well_state_copy, deferred_logger);
if (!converged) {
const std::string msg = " well " + name() + " did not get converged during well potential calculations "
"returning zero values for the potential";
deferred_logger.debug(msg);
return;
}
updatePrimaryVariables(well_state_copy, deferred_logger);
computeWellConnectionPressures(ebosSimulator, well_state_copy);
initPrimaryVariablesEvaluation();
}
const bool allow_cf = getAllowCrossFlow();
@ -2329,8 +2292,49 @@ namespace Opm
well_flux[ebosCompIdxToFlowCompIdx(p)] += cq_s[p].value();
}
}
}
template<typename TypeTag>
void
StandardWellV<TypeTag>::
computeWellRatesWithBhpPotential(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger)
{
WellControls* wc = well_controls_;
const int bhp_index = Base::getControlIndex(BHP);
const double orig_bhp = well_controls_iget_target(wc, bhp_index);
const auto orig_current = well_controls_get_current(wc);
well_controls_iset_target(wc, bhp_index, bhp);
well_controls_set_current(wc, bhp_index);
// iterate to get a more accurate well density
// create a copy of the well_state to use. If the operability checking is sucessful, we use this one
// to replace the original one
WellState well_state_copy = ebosSimulator.problem().wellModel().wellState();
well_state_copy.currentControls()[index_of_well_] = bhp_index;
bool converged = this->solveWellEqUntilConverged(ebosSimulator, B_avg, well_state_copy, deferred_logger);
if (!converged) {
const std::string msg = " well " + name() + " did not get converged during well potential calculations "
"returning zero values for the potential";
deferred_logger.debug(msg);
return;
}
updatePrimaryVariables(well_state_copy, deferred_logger);
computeWellConnectionPressures(ebosSimulator, well_state_copy);
initPrimaryVariablesEvaluation();
computeWellRatesWithBhp(ebosSimulator, bhp, well_flux, deferred_logger);
// reset bhp limit
well_controls_iset_target(wc, bhp_index, orig_bhp);
well_controls_set_current(wc, orig_current);
@ -2338,8 +2342,6 @@ namespace Opm
template<typename TypeTag>
std::vector<double>
StandardWellV<TypeTag>::
@ -2411,7 +2413,7 @@ namespace Opm
converged = std::abs(old_bhp - bhp) < bhp_tolerance;
computeWellRatesWithBhp(ebosSimulator, B_avg, bhp, /*iterate=*/ true, potentials, deferred_logger);
computeWellRatesWithBhpPotential(ebosSimulator, B_avg, bhp, potentials, deferred_logger);
// checking whether the potentials have valid values
for (const double value : potentials) {
@ -2471,7 +2473,7 @@ namespace Opm
if ( !wellHasTHPConstraints() ) {
assert(std::abs(bhp) != std::numeric_limits<double>::max());
computeWellRatesWithBhp(ebosSimulator, B_avg, bhp, /*iterate=*/ true, well_potentials, deferred_logger);
computeWellRatesWithBhpPotential(ebosSimulator, B_avg, bhp, well_potentials, deferred_logger);
} else {
// the well has a THP related constraint
// checking whether a well is newly added, it only happens at the beginning of the report step
@ -2483,7 +2485,7 @@ namespace Opm
}
} else {
// We need to generate a reasonable rates to start the iteration process
computeWellRatesWithBhp(ebosSimulator, B_avg, bhp, /*iterate=*/ true, well_potentials, deferred_logger);
computeWellRatesWithBhpPotential(ebosSimulator, B_avg, bhp, well_potentials, deferred_logger);
for (double& value : well_potentials) {
// make the value a little safer in case the BHP limits are default ones
// TODO: a better way should be a better rescaling based on the investigation of the VFP table.
@ -2931,7 +2933,7 @@ namespace Opm
// we should be able to provide a better initialization
calculateExplicitQuantities(ebos_simulator, well_state_copy, deferred_logger);
updateWellOperability(ebos_simulator, B_avg, well_state_copy, deferred_logger);
updateWellOperability(ebos_simulator, well_state_copy, deferred_logger);
if ( !this->isOperable() ) {
const std::string msg = " well " + name() + " is not operable during well testing for physical reason";
@ -2939,7 +2941,7 @@ namespace Opm
return;
}
updateWellStateWithTarget(ebos_simulator, B_avg, well_state_copy, deferred_logger);
updateWellStateWithTarget(ebos_simulator, well_state_copy, deferred_logger);
calculateExplicitQuantities(ebos_simulator, well_state_copy, deferred_logger);
updatePrimaryVariables(well_state_copy, deferred_logger);

View File

@ -444,13 +444,13 @@ namespace Opm
void
StandardWell<TypeTag>::
assembleWellEq(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const std::vector<Scalar>& /* B_avg */,
const double dt,
WellState& well_state,
Opm::DeferredLogger& deferred_logger)
{
checkWellOperability(ebosSimulator, B_avg, well_state, deferred_logger);
checkWellOperability(ebosSimulator, well_state, deferred_logger);
if (!this->isOperable()) return;
@ -1117,9 +1117,8 @@ namespace Opm
void
StandardWell<TypeTag>::
updateWellStateWithTarget(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger)
Opm::DeferredLogger& deferred_logger) const
{
// number of phases
@ -1145,7 +1144,7 @@ namespace Opm
case THP: {
// when a well can not work under THP target, it switches to BHP control
if (this->operability_status_.isOperableUnderTHPLimit() ) {
updateWellStateWithTHPTargetIPR(ebos_simulator, B_avg, well_state, deferred_logger);
updateWellStateWithTHPTargetIPR(ebos_simulator, well_state, deferred_logger);
} else { // go to BHP limit
assert(this->operability_status_.isOperableUnderBHPLimit() );
@ -1323,7 +1322,6 @@ namespace Opm
void
StandardWell<TypeTag>::
checkWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& well_state,
Opm::DeferredLogger& deferred_logger
)
@ -1339,7 +1337,7 @@ namespace Opm
const bool old_well_operable = this->operability_status_.isOperable();
updateWellOperability(ebos_simulator, B_avg, well_state, deferred_logger);
updateWellOperability(ebos_simulator, well_state, deferred_logger);
const bool well_operable = this->operability_status_.isOperable();
@ -1358,7 +1356,6 @@ namespace Opm
void
StandardWell<TypeTag>::
updateWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& /* well_state */,
Opm::DeferredLogger& deferred_logger
)
@ -1368,7 +1365,7 @@ namespace Opm
updateIPR(ebos_simulator, deferred_logger);
// checking the BHP limit related
checkOperabilityUnderBHPLimitProducer(ebos_simulator, B_avg, deferred_logger);
checkOperabilityUnderBHPLimitProducer(ebos_simulator, deferred_logger);
// checking whether the well can operate under the THP constraints.
if (this->wellHasTHPConstraints()) {
@ -1383,9 +1380,7 @@ namespace Opm
template<typename TypeTag>
void
StandardWell<TypeTag>::
checkOperabilityUnderBHPLimitProducer(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
Opm::DeferredLogger& deferred_logger)
checkOperabilityUnderBHPLimitProducer(const Simulator& ebos_simulator, Opm::DeferredLogger& deferred_logger)
{
const double bhp_limit = mostStrictBhpFromBhpLimits(deferred_logger);
// Crude but works: default is one atmosphere.
@ -1409,7 +1404,7 @@ namespace Opm
// option 2: stick with the above IPR curve
// we use IPR here
std::vector<double> well_rates_bhp_limit;
computeWellRatesWithBhp(ebos_simulator, B_avg, bhp_limit, /*iterate=*/ false, well_rates_bhp_limit, deferred_logger);
computeWellRatesWithBhp(ebos_simulator, bhp_limit, well_rates_bhp_limit, deferred_logger);
const double thp = calculateThpFromBhp(well_rates_bhp_limit, bhp_limit, deferred_logger);
const double thp_limit = this->getTHPConstraint(deferred_logger);
@ -1515,7 +1510,7 @@ namespace Opm
{
const double bhp = well_state.bhp()[index_of_well_];
std::vector<double> well_rates;
computeWellRatesWithBhp(ebos_simulator, bhp, /*iterate=*/ false, well_rates, deferred_logger);
computeWellRatesWithBhp(ebos_simulator, bhp, well_rates, deferred_logger);
const double sign = (well_type_ == PRODUCER) ? -1. : 1.;
const double threshold = sign * std::numeric_limits<double>::min();
@ -1558,13 +1553,11 @@ namespace Opm
void
StandardWell<TypeTag>::
updateWellStateWithTHPTargetIPR(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger)
Opm::DeferredLogger& deferred_logger) const
{
if (well_type_ == PRODUCER) {
updateWellStateWithTHPTargetIPRProducer(ebos_simulator,
B_avg,
well_state,
deferred_logger);
}
@ -1584,9 +1577,8 @@ namespace Opm
void
StandardWell<TypeTag>::
updateWellStateWithTHPTargetIPRProducer(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger)
Opm::DeferredLogger& deferred_logger) const
{
well_state.thp()[index_of_well_] = this->getTHPConstraint(deferred_logger);
@ -1602,7 +1594,7 @@ namespace Opm
initPrimaryVariablesEvaluation();
std::vector<double> rates;
computeWellRatesWithBhp(ebos_simulator, B_avg, bhp, /*iterate=*/ false, rates, deferred_logger);
computeWellRatesWithBhp(ebos_simulator, bhp, rates, deferred_logger);
// TODO: double checke the obtained rates
// this is another places we might obtain negative rates
@ -2160,48 +2152,17 @@ namespace Opm
template<typename TypeTag>
void
StandardWell<TypeTag>::
computeWellRatesWithBhp(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
const bool iterate,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger)
Opm::DeferredLogger& deferred_logger) const
{
const int np = number_of_phases_;
well_flux.resize(np, 0.0);
WellControls* wc = well_controls_;
const int bhp_index = Base::getControlIndex(BHP);
const double orig_bhp = well_controls_iget_target(wc, bhp_index);
const auto orig_current = well_controls_get_current(wc);
well_controls_iset_target(wc, bhp_index, bhp);
well_controls_set_current(wc, bhp_index);
// iterate to get a more accurate well density
if (iterate) {
// create a copy of the well_state to use. If the operability checking is sucessful, we use this one
// to replace the original one
WellState well_state_copy = ebosSimulator.problem().wellModel().wellState();
well_state_copy.currentControls()[index_of_well_] = bhp_index;
bool converged = this->solveWellEqUntilConverged(ebosSimulator, B_avg, well_state_copy, deferred_logger);
if (!converged) {
const std::string msg = " well " + name() + " did not get converged during well potential calculations "
"returning zero values for the potential";
deferred_logger.debug(msg);
return;
}
updatePrimaryVariables(well_state_copy, deferred_logger);
computeWellConnectionPressures(ebosSimulator, well_state_copy);
initPrimaryVariablesEvaluation();
}
const bool allow_cf = getAllowCrossFlow();
@ -2217,15 +2178,56 @@ namespace Opm
std::vector<EvalWell> cq_s(num_components_, 0.0);
double perf_dis_gas_rate = 0.;
double perf_vap_oil_rate = 0.;
computePerfRate(intQuants, mob, bhp, Tw, perf, allow_cf,
computePerfRate(intQuants, mob, EvalWell(bhp), Tw, perf, allow_cf,
cq_s, perf_dis_gas_rate, perf_vap_oil_rate, deferred_logger);
for(int p = 0; p < np; ++p) {
well_flux[ebosCompIdxToFlowCompIdx(p)] += cq_s[p].value();
}
}
}
template<typename TypeTag>
void
StandardWell<TypeTag>::
computeWellRatesWithBhpPotential(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger)
{
WellControls* wc = well_controls_;
const int bhp_index = Base::getControlIndex(BHP);
const double orig_bhp = well_controls_iget_target(wc, bhp_index);
const auto orig_current = well_controls_get_current(wc);
well_controls_iset_target(wc, bhp_index, bhp);
well_controls_set_current(wc, bhp_index);
// iterate to get a more accurate well density
// create a copy of the well_state to use. If the operability checking is sucessful, we use this one
// to replace the original one
WellState well_state_copy = ebosSimulator.problem().wellModel().wellState();
well_state_copy.currentControls()[index_of_well_] = bhp_index;
bool converged = this->solveWellEqUntilConverged(ebosSimulator, B_avg, well_state_copy, deferred_logger);
if (!converged) {
const std::string msg = " well " + name() + " did not get converged during well potential calculations "
"returning zero values for the potential";
deferred_logger.debug(msg);
return;
}
updatePrimaryVariables(well_state_copy, deferred_logger);
computeWellConnectionPressures(ebosSimulator, well_state_copy);
initPrimaryVariablesEvaluation();
computeWellRatesWithBhp(ebosSimulator, bhp, well_flux, deferred_logger);
// reset bhp limit
well_controls_iset_target(wc, bhp_index, orig_bhp);
well_controls_set_current(wc, orig_current);
@ -2234,7 +2236,6 @@ namespace Opm
template<typename TypeTag>
std::vector<double>
StandardWell<TypeTag>::
@ -2306,7 +2307,7 @@ namespace Opm
converged = std::abs(old_bhp - bhp) < bhp_tolerance;
computeWellRatesWithBhp(ebosSimulator, B_avg, bhp, /*iterate=*/ true, potentials, deferred_logger);
computeWellRatesWithBhpPotential(ebosSimulator, B_avg, bhp, potentials, deferred_logger);
// checking whether the potentials have valid values
for (const double value : potentials) {
@ -2361,7 +2362,6 @@ namespace Opm
// TODO: for computeWellPotentials, no derivative is required actually
initPrimaryVariablesEvaluation();
const int np = number_of_phases_;
well_potentials.resize(np, 0.0);
@ -2371,7 +2371,7 @@ namespace Opm
// does the well have a THP related constraint?
if ( !wellHasTHPConstraints() ) {
assert(std::abs(bhp) != std::numeric_limits<double>::max());
computeWellRatesWithBhp(ebosSimulator, B_avg, bhp, /*iterate=*/ true, well_potentials, deferred_logger);
computeWellRatesWithBhpPotential(ebosSimulator, B_avg, bhp, well_potentials, deferred_logger);
} else {
// the well has a THP related constraint
// checking whether a well is newly added, it only happens at the beginning of the report step
@ -2383,7 +2383,7 @@ namespace Opm
}
} else {
// We need to generate a reasonable rates to start the iteration process
computeWellRatesWithBhp(ebosSimulator, B_avg, bhp, /*iterate=*/ true, well_potentials, deferred_logger);
computeWellRatesWithBhpPotential(ebosSimulator, B_avg, bhp, well_potentials, deferred_logger);
for (double& value : well_potentials) {
// make the value a little safer in case the BHP limits are default ones
// TODO: a better way should be a better rescaling based on the investigation of the VFP table.
@ -2825,7 +2825,7 @@ namespace Opm
// we should be able to provide a better initialization
calculateExplicitQuantities(ebos_simulator, well_state_copy, deferred_logger);
updateWellOperability(ebos_simulator, B_avg, well_state_copy, deferred_logger);
updateWellOperability(ebos_simulator, well_state_copy, deferred_logger);
if ( !this->isOperable() ) {
const std::string msg = " well " + name() + " is not operable during well testing for physical reason";
@ -2833,7 +2833,7 @@ namespace Opm
return;
}
updateWellStateWithTarget(ebos_simulator, B_avg, well_state_copy, deferred_logger);
updateWellStateWithTarget(ebos_simulator, well_state_copy, deferred_logger);
calculateExplicitQuantities(ebos_simulator, well_state_copy, deferred_logger);
updatePrimaryVariables(well_state_copy, deferred_logger);

View File

@ -188,12 +188,10 @@ namespace Opm
Opm::DeferredLogger& deferred_logger) = 0;
virtual void updateWellStateWithTarget(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) = 0;
Opm::DeferredLogger& deferred_logger) const = 0;
void updateWellControl(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) /* const */;
@ -246,10 +244,7 @@ namespace Opm
void updatePerforatedCell(std::vector<bool>& is_cell_perforated);
virtual void checkWellOperability(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
const WellState& well_state,
Opm::DeferredLogger& deferred_logger) = 0;
virtual void checkWellOperability(const Simulator& ebos_simulator, const WellState& well_state, Opm::DeferredLogger& deferred_logger) = 0;
// whether the well is operable
bool isOperable() const;
@ -422,14 +417,6 @@ namespace Opm
void scaleProductivityIndex(const int perfIdx, double& productivity_index, const bool new_well, Opm::DeferredLogger& deferred_logger);
virtual void computeWellRatesWithBhp(const Simulator& ebosSimulator,
const std::vector<Scalar>& B_avg,
const double& bhp,
const bool iterate,
std::vector<double>& well_flux,
Opm::DeferredLogger& deferred_logger) = 0;
// count the number of times an output log message is created in the productivity
// index calculations
int well_productivity_index_logger_counter_;

View File

@ -426,7 +426,6 @@ namespace Opm
void
WellInterface<TypeTag>::
updateWellControl(const Simulator& ebos_simulator,
const std::vector<Scalar>& B_avg,
WellState& well_state,
Opm::DeferredLogger& deferred_logger) /* const */
{
@ -505,7 +504,7 @@ namespace Opm
}
if (updated_control_index != old_control_index) { // || well_collection_->groupControlActive()) {
updateWellStateWithTarget(ebos_simulator, B_avg, well_state, deferred_logger);
updateWellStateWithTarget(ebos_simulator, well_state, deferred_logger);
updatePrimaryVariables(well_state, deferred_logger);
}
}
@ -1190,7 +1189,7 @@ namespace Opm
++it;
solveEqAndUpdateWellState(well_state, deferred_logger);
updateWellControl(ebosSimulator, B_avg, well_state, deferred_logger);
updateWellControl(ebosSimulator, well_state, deferred_logger);
initPrimaryVariablesEvaluation();
} while (it < max_iter);