mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Remove code duplication between STW and MSW
This commit is contained in:
parent
dae6b61370
commit
70150ab212
@ -142,9 +142,9 @@ namespace Opm
|
||||
Opm::DeferredLogger& deferred_logger) override;
|
||||
|
||||
/// updating the well state based the current control mode
|
||||
virtual void updateWellStateWithTarget(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const override;
|
||||
void updateWellStateWithTarget(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
/// check whether the well equations get converged for this well
|
||||
virtual ConvergenceReport getWellConvergence(const WellState& well_state, const std::vector<double>& B_avg, Opm::DeferredLogger& deferred_logger, const bool relax_tolerance = false) const override;
|
||||
@ -253,6 +253,8 @@ namespace Opm
|
||||
using Base::wellIsStopped;
|
||||
using Base::updateWellOperability;
|
||||
using Base::checkWellOperability;
|
||||
using Base::calculateBhpFromThp;
|
||||
using Base::getALQ;
|
||||
|
||||
// TODO: trying to use the information from the Well opm-parser as much
|
||||
// as possible, it will possibly be re-implemented later for efficiency reason.
|
||||
@ -383,10 +385,6 @@ namespace Opm
|
||||
// convert a Eval from reservoir to contain the derivative related to wells
|
||||
EvalWell extendEval(const Eval& in) const;
|
||||
|
||||
|
||||
template <class ValueType>
|
||||
ValueType calculateBhpFromThp(const std::vector<ValueType>& rates, const Well& well, const SummaryState& summaryState, Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
double calculateThpFromBhp(const std::vector<double>& rates, const double bhp, Opm::DeferredLogger& deferred_logger) const;
|
||||
void updateThp(WellState& well_state, Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
@ -446,6 +444,8 @@ namespace Opm
|
||||
|
||||
void updateWellStateFromPrimaryVariables(WellState& well_state, Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
virtual double getRefDensity() const override;
|
||||
|
||||
bool frictionalPressureLossConsidered() const;
|
||||
|
||||
bool accelerationalPressureLossConsidered() const;
|
||||
|
@ -291,226 +291,7 @@ namespace Opm
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const
|
||||
{
|
||||
// segRates and segPressure are used to initilize the primaryvariables for MSW wells
|
||||
// first initialize wellRates and then use it to compute segRates
|
||||
// When THP is supported for MSW wells this code and its fried in the standard model
|
||||
// can be merge.
|
||||
|
||||
const auto& well = well_ecl_;
|
||||
const int well_index = index_of_well_;
|
||||
const auto& pu = phaseUsage();
|
||||
const int np = well_state.numPhases();
|
||||
const auto& summaryState = ebos_simulator.vanguard().summaryState();
|
||||
|
||||
if (this->wellIsStopped()) {
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] = 0.0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (well.isInjector() )
|
||||
{
|
||||
const auto& controls = well.injectionControls(summaryState);
|
||||
|
||||
InjectorType injectorType = controls.injector_type;
|
||||
int phasePos;
|
||||
switch (injectorType) {
|
||||
case InjectorType::WATER:
|
||||
{
|
||||
phasePos = pu.phase_pos[BlackoilPhases::Aqua];
|
||||
break;
|
||||
}
|
||||
case InjectorType::OIL:
|
||||
{
|
||||
phasePos = pu.phase_pos[BlackoilPhases::Liquid];
|
||||
break;
|
||||
}
|
||||
case InjectorType::GAS:
|
||||
{
|
||||
phasePos = pu.phase_pos[BlackoilPhases::Vapour];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw("Expected WATER, OIL or GAS as type for injectors " + well.name());
|
||||
}
|
||||
|
||||
const Opm::Well::InjectorCMode& current = well_state.currentInjectionControls()[well_index];
|
||||
|
||||
switch(current) {
|
||||
case Well::InjectorCMode::RATE:
|
||||
{
|
||||
well_state.wellRates()[well_index*np + phasePos] = controls.surface_rate;
|
||||
break;
|
||||
}
|
||||
|
||||
case Well::InjectorCMode::RESV:
|
||||
{
|
||||
std::vector<double> convert_coeff(number_of_phases_, 1.0);
|
||||
Base::rateConverter_.calcCoeff(/*fipreg*/ 0, Base::pvtRegionIdx_, convert_coeff);
|
||||
const double coeff = convert_coeff[phasePos];
|
||||
well_state.wellRates()[well_index*np + phasePos] = controls.reservoir_rate/coeff;
|
||||
break;
|
||||
}
|
||||
|
||||
case Well::InjectorCMode::THP:
|
||||
{
|
||||
std::vector<double> rates(3, 0.0);
|
||||
for (int p = 0; p<np; ++p) {
|
||||
rates[p] = well_state.wellRates()[well_index*np + p];
|
||||
}
|
||||
double bhp = calculateBhpFromThp(rates, well, summaryState, deferred_logger);
|
||||
well_state.bhp()[well_index] = bhp;
|
||||
break;
|
||||
}
|
||||
case Well::InjectorCMode::BHP:
|
||||
{
|
||||
well_state.bhp()[well_index] = controls.bhp_limit;
|
||||
break;
|
||||
}
|
||||
case Well::InjectorCMode::GRUP:
|
||||
{
|
||||
// for GRUP the well rates are scaled
|
||||
// in checkGroupConstraints
|
||||
break;
|
||||
}
|
||||
case Well::InjectorCMode::CMODE_UNDEFINED:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Well control must be specified for well " + name(), deferred_logger );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//Producer
|
||||
else
|
||||
{
|
||||
const Well::ProducerCMode& current = well_state.currentProductionControls()[well_index];
|
||||
const auto& controls = well.productionControls(summaryState);
|
||||
|
||||
switch (current) {
|
||||
case Well::ProducerCMode::ORAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Oil] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.oil_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::WRAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Water] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.water_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::GRAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Gas] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.gas_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case Well::ProducerCMode::LRAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Water] ]
|
||||
- well_state.wellRates()[ well_index*np + pu.phase_pos[Oil] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.liquid_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::CRAT:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "CRAT control not supported " << name(), deferred_logger);
|
||||
}
|
||||
case Well::ProducerCMode::RESV:
|
||||
{
|
||||
std::vector<double> convert_coeff(number_of_phases_, 1.0);
|
||||
Base::rateConverter_.calcCoeff(/*fipreg*/ 0, Base::pvtRegionIdx_, convert_coeff);
|
||||
double total_res_rate = 0.0;
|
||||
for (int p = 0; p<np; ++p) {
|
||||
total_res_rate -= well_state.wellRates()[well_index*np + p] * convert_coeff[p];
|
||||
}
|
||||
if (total_res_rate == 0.0)
|
||||
break;
|
||||
|
||||
if (controls.prediction_mode) {
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.resv_rate/total_res_rate;
|
||||
}
|
||||
} else {
|
||||
std::vector<double> hrates(number_of_phases_,0.);
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
|
||||
hrates[pu.phase_pos[Water]] = controls.water_rate;
|
||||
}
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
|
||||
hrates[pu.phase_pos[Oil]] = controls.oil_rate;
|
||||
}
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
|
||||
hrates[pu.phase_pos[Gas]] = controls.gas_rate;
|
||||
}
|
||||
std::vector<double> hrates_resv(number_of_phases_,0.);
|
||||
Base::rateConverter_.calcReservoirVoidageRates(/*fipreg*/ 0, Base::pvtRegionIdx_, hrates, hrates_resv);
|
||||
double target = std::accumulate(hrates_resv.begin(), hrates_resv.end(), 0.0);
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= target/total_res_rate;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::BHP:
|
||||
{
|
||||
well_state.bhp()[well_index] = controls.bhp_limit;
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::THP:
|
||||
{
|
||||
std::vector<double> rates(3, 0.0);
|
||||
for (int p = 0; p<np; ++p) {
|
||||
rates[p] = well_state.wellRates()[well_index*np + p];
|
||||
}
|
||||
double bhp = calculateBhpFromThp(rates, well, summaryState, deferred_logger);
|
||||
well_state.bhp()[well_index] = bhp;
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::GRUP:
|
||||
{
|
||||
// for GRUP the well rates are scaled
|
||||
// in checkGroupConstraints
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::CMODE_UNDEFINED:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Well control must be specified for well " + name(), deferred_logger );
|
||||
}
|
||||
case Well::ProducerCMode::NONE:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Well control must be specified for well " + name() , deferred_logger);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Base::updateWellStateWithTarget(ebos_simulator, well_state, deferred_logger);
|
||||
// scale segment rates based on the wellRates
|
||||
// and segment pressure based on bhp
|
||||
scaleSegmentPressuresWithBhp(well_state);
|
||||
@ -2058,7 +1839,7 @@ namespace Opm
|
||||
// Setup function for evaluation of BHP from THP (used only if needed).
|
||||
auto bhp_from_thp = [&]() {
|
||||
const auto rates = getRates();
|
||||
return calculateBhpFromThp(rates, well, summaryState, deferred_logger);
|
||||
return calculateBhpFromThp(well_state, rates, well, summaryState, deferred_logger);
|
||||
};
|
||||
// Call generic implementation.
|
||||
Base::assembleControlEqInj(well_state, group_state, schedule, summaryState, inj_controls, getBhp(), injection_rate, bhp_from_thp, control_eq, deferred_logger);
|
||||
@ -2067,7 +1848,7 @@ namespace Opm
|
||||
const auto rates = getRates();
|
||||
// Setup function for evaluation of BHP from THP (used only if needed).
|
||||
auto bhp_from_thp = [&]() {
|
||||
return calculateBhpFromThp(rates, well, summaryState, deferred_logger);
|
||||
return calculateBhpFromThp(well_state, rates, well, summaryState, deferred_logger);
|
||||
};
|
||||
// Call generic implementation.
|
||||
Base::assembleControlEqProd(well_state, group_state, schedule, summaryState, prod_controls, getBhp(), rates, bhp_from_thp, control_eq, deferred_logger);
|
||||
@ -2128,7 +1909,7 @@ namespace Opm
|
||||
const double vapour = rates[Gas];
|
||||
|
||||
// pick the density in the top segment
|
||||
const double rho = segment_densities_[0].value();
|
||||
const double rho = getRefDensity();
|
||||
|
||||
double thp = 0.0;
|
||||
if (this->isInjector()) {
|
||||
@ -2155,50 +1936,13 @@ namespace Opm
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
template<class ValueType>
|
||||
ValueType
|
||||
double
|
||||
MultisegmentWell<TypeTag>::
|
||||
calculateBhpFromThp(const std::vector<ValueType>& rates,
|
||||
const Well& well,
|
||||
const SummaryState& summaryState,
|
||||
Opm::DeferredLogger& deferred_logger) const
|
||||
getRefDensity() const
|
||||
{
|
||||
// TODO: when well is under THP control, the BHP is dependent on the rates,
|
||||
// the well rates is also dependent on the BHP, so it might need to do some iteration.
|
||||
// However, when group control is involved, change of the rates might impacts other wells
|
||||
// so iterations on a higher level will be required. Some investigation might be needed when
|
||||
// we face problems under THP control.
|
||||
|
||||
assert(int(rates.size()) == 3); // the vfp related only supports three phases now.
|
||||
|
||||
const ValueType aqua = rates[Water];
|
||||
const ValueType liquid = rates[Oil];
|
||||
const ValueType vapour = rates[Gas];
|
||||
|
||||
// pick the density in the top layer
|
||||
// TODO: it is possible it should be a Evaluation
|
||||
const double rho = segment_densities_[0].value();
|
||||
|
||||
if (well.isInjector() )
|
||||
{
|
||||
const auto& controls = well.injectionControls(summaryState);
|
||||
const double vfp_ref_depth = vfp_properties_->getInj()->getTable(controls.vfp_table_number).getDatumDepth();
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
return vfp_properties_->getInj()->bhp(controls.vfp_table_number, aqua, liquid, vapour, this->getTHPConstraint(summaryState)) - dp;
|
||||
}
|
||||
else if (well.isProducer()) {
|
||||
const auto& controls = well.productionControls(summaryState);
|
||||
const double vfp_ref_depth = vfp_properties_->getProd()->getTable(controls.vfp_table_number).getDatumDepth();
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
return vfp_properties_->getProd()->bhp(controls.vfp_table_number, aqua, liquid, vapour, this->getTHPConstraint(summaryState), controls.alq_value) - dp;
|
||||
}
|
||||
else {
|
||||
OPM_DEFLOG_THROW(std::logic_error, "Expected INJECTOR or PRODUCER well", deferred_logger);
|
||||
}
|
||||
return segment_densities_[0].value();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
@ -3600,7 +3344,7 @@ namespace Opm
|
||||
const auto& controls = well_ecl_.productionControls(summary_state);
|
||||
const auto& table = vfp_properties_->getProd()->getTable(controls.vfp_table_number);
|
||||
const double vfp_ref_depth = table.getDatumDepth();
|
||||
const double rho = segment_densities_[0].value(); // Use the density at the top perforation.
|
||||
const double rho = getRefDensity(); // Use the density at the top perforation.
|
||||
const double thp_limit = this->getTHPConstraint(summary_state);
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
auto fbhp = [this, &controls, thp_limit, dp](const std::vector<double>& rates) {
|
||||
@ -3822,7 +3566,7 @@ namespace Opm
|
||||
const auto& controls = well_ecl_.injectionControls(summary_state);
|
||||
const auto& table = vfp_properties_->getInj()->getTable(controls.vfp_table_number);
|
||||
const double vfp_ref_depth = table.getDatumDepth();
|
||||
const double rho = segment_densities_[0].value(); // Use the density at the top perforation.
|
||||
const double rho = getRefDensity(); // Use the density at the top perforation.
|
||||
const double thp_limit = this->getTHPConstraint(summary_state);
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
auto fbhp = [this, &controls, thp_limit, dp](const std::vector<double>& rates) {
|
||||
|
@ -187,9 +187,9 @@ namespace Opm
|
||||
const GroupState& group_state,
|
||||
Opm::DeferredLogger& deferred_logger) override;
|
||||
|
||||
virtual void updateWellStateWithTarget(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const override;
|
||||
void updateWellStateWithTarget(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
/// check whether the well equations get converged for this well
|
||||
virtual ConvergenceReport getWellConvergence(const WellState& well_state,
|
||||
@ -345,6 +345,8 @@ namespace Opm
|
||||
using Base::updateWellOperability;
|
||||
using Base::checkWellOperability;
|
||||
using Base::wellIsStopped;
|
||||
using Base::calculateBhpFromThp;
|
||||
using Base::getALQ;
|
||||
|
||||
// protected member variables from the Base class
|
||||
using Base::current_step_;
|
||||
@ -489,12 +491,11 @@ namespace Opm
|
||||
Opm::DeferredLogger& deferred_logger,
|
||||
const WellState &well_state) const;
|
||||
|
||||
template <class ValueType>
|
||||
ValueType calculateBhpFromThp(const WellState& well_state, const std::vector<ValueType>& rates, const Well& well, const SummaryState& summaryState, Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
|
||||
double calculateThpFromBhp(const WellState &well_state, const std::vector<double>& rates, const double bhp, Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
virtual double getRefDensity() const override;
|
||||
|
||||
// get the mobility for specific perforation
|
||||
void getMobility(const Simulator& ebosSimulator,
|
||||
const int perf,
|
||||
@ -517,7 +518,6 @@ namespace Opm
|
||||
|
||||
void updateThp(WellState& well_state, Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
double getALQ(const WellState& well_state) const;
|
||||
|
||||
void assembleControlEq(const WellState& well_state,
|
||||
const GroupState& group_state,
|
||||
|
@ -1360,222 +1360,7 @@ namespace Opm
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const
|
||||
{
|
||||
|
||||
// only bhp and wellRates are used to initilize the primaryvariables for standard wells
|
||||
const auto& well = well_ecl_;
|
||||
const int well_index = index_of_well_;
|
||||
const auto& pu = phaseUsage();
|
||||
const int np = well_state.numPhases();
|
||||
const auto& summaryState = ebos_simulator.vanguard().summaryState();
|
||||
|
||||
if (this->wellIsStopped()) {
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] = 0.0;
|
||||
}
|
||||
well_state.thp()[well_index] = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->isInjector() )
|
||||
{
|
||||
const auto& controls = well.injectionControls(summaryState);
|
||||
|
||||
InjectorType injectorType = controls.injector_type;
|
||||
int phasePos;
|
||||
switch (injectorType) {
|
||||
case InjectorType::WATER:
|
||||
{
|
||||
phasePos = pu.phase_pos[BlackoilPhases::Aqua];
|
||||
break;
|
||||
}
|
||||
case InjectorType::OIL:
|
||||
{
|
||||
phasePos = pu.phase_pos[BlackoilPhases::Liquid];
|
||||
break;
|
||||
}
|
||||
case InjectorType::GAS:
|
||||
{
|
||||
phasePos = pu.phase_pos[BlackoilPhases::Vapour];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw("Expected WATER, OIL or GAS as type for injectors " + well.name());
|
||||
}
|
||||
|
||||
const Opm::Well::InjectorCMode& current = well_state.currentInjectionControls()[well_index];
|
||||
|
||||
switch(current) {
|
||||
case Well::InjectorCMode::RATE:
|
||||
{
|
||||
well_state.wellRates()[well_index*np + phasePos] = controls.surface_rate;
|
||||
break;
|
||||
}
|
||||
|
||||
case Well::InjectorCMode::RESV:
|
||||
{
|
||||
std::vector<double> convert_coeff(number_of_phases_, 1.0);
|
||||
Base::rateConverter_.calcCoeff(/*fipreg*/ 0, Base::pvtRegionIdx_, convert_coeff);
|
||||
const double coeff = convert_coeff[phasePos];
|
||||
well_state.wellRates()[well_index*np + phasePos] = controls.reservoir_rate/coeff;
|
||||
break;
|
||||
}
|
||||
|
||||
case Well::InjectorCMode::THP:
|
||||
{
|
||||
std::vector<double> rates(3, 0.0);
|
||||
for (int p = 0; p<np; ++p) {
|
||||
rates[p] = well_state.wellRates()[well_index*np + p];
|
||||
}
|
||||
double bhp = calculateBhpFromThp(well_state, rates, well, summaryState, deferred_logger);
|
||||
well_state.bhp()[well_index] = bhp;
|
||||
break;
|
||||
}
|
||||
case Well::InjectorCMode::BHP:
|
||||
{
|
||||
well_state.bhp()[well_index] = controls.bhp_limit;
|
||||
break;
|
||||
}
|
||||
case Well::InjectorCMode::GRUP:
|
||||
{
|
||||
//do nothing at the moment
|
||||
break;
|
||||
}
|
||||
case Well::InjectorCMode::CMODE_UNDEFINED:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Well control must be specified for well " + name(), deferred_logger );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//Producer
|
||||
else
|
||||
{
|
||||
const Well::ProducerCMode& current = well_state.currentProductionControls()[well_index];
|
||||
const auto& controls = well.productionControls(summaryState);
|
||||
|
||||
switch (current) {
|
||||
case Well::ProducerCMode::ORAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Oil] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.oil_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::WRAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Water] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.water_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::GRAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Gas] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.gas_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case Well::ProducerCMode::LRAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Water] ]
|
||||
- well_state.wellRates()[ well_index*np + pu.phase_pos[Oil] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.liquid_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::CRAT:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "CRAT control not supported " << name(), deferred_logger);
|
||||
}
|
||||
case Well::ProducerCMode::RESV:
|
||||
{
|
||||
std::vector<double> convert_coeff(number_of_phases_, 1.0);
|
||||
Base::rateConverter_.calcCoeff(/*fipreg*/ 0, Base::pvtRegionIdx_, convert_coeff);
|
||||
double total_res_rate = 0.0;
|
||||
for (int p = 0; p<np; ++p) {
|
||||
total_res_rate -= well_state.wellRates()[well_index*np + p] * convert_coeff[p];
|
||||
}
|
||||
if (total_res_rate == 0.0)
|
||||
break;
|
||||
|
||||
if (controls.prediction_mode) {
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.resv_rate/total_res_rate;
|
||||
}
|
||||
} else {
|
||||
std::vector<double> hrates(number_of_phases_,0.);
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
|
||||
hrates[pu.phase_pos[Water]] = controls.water_rate;
|
||||
}
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
|
||||
hrates[pu.phase_pos[Oil]] = controls.oil_rate;
|
||||
}
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
|
||||
hrates[pu.phase_pos[Gas]] = controls.gas_rate;
|
||||
}
|
||||
std::vector<double> hrates_resv(number_of_phases_,0.);
|
||||
Base::rateConverter_.calcReservoirVoidageRates(/*fipreg*/ 0, Base::pvtRegionIdx_, hrates, hrates_resv);
|
||||
double target = std::accumulate(hrates_resv.begin(), hrates_resv.end(), 0.0);
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= target/total_res_rate;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::BHP:
|
||||
{
|
||||
well_state.bhp()[well_index] = controls.bhp_limit;
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::THP:
|
||||
{
|
||||
std::vector<double> rates(3, 0.0);
|
||||
for (int p = 0; p<np; ++p) {
|
||||
rates[p] = well_state.wellRates()[well_index*np + p];
|
||||
}
|
||||
double bhp = calculateBhpFromThp(well_state, rates, well, summaryState, deferred_logger);
|
||||
well_state.bhp()[well_index] = bhp;
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::GRUP:
|
||||
{
|
||||
//do nothing at the moment
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::CMODE_UNDEFINED:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Well control must be specified for well " + name(), deferred_logger );
|
||||
}
|
||||
case Well::ProducerCMode::NONE:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Well control must be specified for well " + name() , deferred_logger);
|
||||
}
|
||||
|
||||
break;
|
||||
} // end of switch
|
||||
}
|
||||
Base::updateWellStateWithTarget(ebos_simulator, well_state, deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
@ -2668,16 +2453,6 @@ namespace Opm
|
||||
return potentials;
|
||||
}
|
||||
|
||||
template<typename TypeTag>
|
||||
double
|
||||
StandardWell<TypeTag>::
|
||||
getALQ(const WellState &well_state) const
|
||||
{
|
||||
const auto& well = well_ecl_;
|
||||
const std::string &well_name = well.name();
|
||||
return well_state.getALQ(well_name);
|
||||
}
|
||||
|
||||
/* At this point we know that the well does not have BHP control mode and
|
||||
that it does have THP constraints, see computeWellPotentials().
|
||||
* TODO: Currently we limit the application of gas lift optimization to wells
|
||||
@ -3014,54 +2789,6 @@ namespace Opm
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
template<class ValueType>
|
||||
ValueType
|
||||
StandardWell<TypeTag>::
|
||||
calculateBhpFromThp(const WellState &well_state,
|
||||
const std::vector<ValueType>& rates,
|
||||
const Well& well,
|
||||
const SummaryState& summaryState,
|
||||
Opm::DeferredLogger& deferred_logger) const
|
||||
{
|
||||
// TODO: when well is under THP control, the BHP is dependent on the rates,
|
||||
// the well rates is also dependent on the BHP, so it might need to do some iteration.
|
||||
// However, when group control is involved, change of the rates might impacts other wells
|
||||
// so iterations on a higher level will be required. Some investigation might be needed when
|
||||
// we face problems under THP control.
|
||||
|
||||
assert(int(rates.size()) == 3); // the vfp related only supports three phases now.
|
||||
|
||||
const ValueType aqua = rates[Water];
|
||||
const ValueType liquid = rates[Oil];
|
||||
const ValueType vapour = rates[Gas];
|
||||
|
||||
// pick the density in the top layer
|
||||
// TODO: it is possible it should be a Evaluation
|
||||
const double rho = perf_densities_[0];
|
||||
|
||||
if (this->isInjector() )
|
||||
{
|
||||
const auto& controls = well.injectionControls(summaryState);
|
||||
const double vfp_ref_depth = vfp_properties_->getInj()->getTable(controls.vfp_table_number).getDatumDepth();
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
return vfp_properties_->getInj()->bhp(controls.vfp_table_number, aqua, liquid, vapour, this->getTHPConstraint(summaryState)) - dp;
|
||||
}
|
||||
else if (this->isProducer()) {
|
||||
const auto& controls = well.productionControls(summaryState);
|
||||
const double vfp_ref_depth = vfp_properties_->getProd()->getTable(controls.vfp_table_number).getDatumDepth();
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
return vfp_properties_->getProd()->bhp(controls.vfp_table_number, aqua, liquid, vapour, this->getTHPConstraint(summaryState), getALQ(well_state)) - dp;
|
||||
}
|
||||
else {
|
||||
OPM_DEFLOG_THROW(std::logic_error, "Expected INJECTOR or PRODUCER well", deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
double
|
||||
@ -3077,7 +2804,7 @@ namespace Opm
|
||||
const double vapour = rates[Gas];
|
||||
|
||||
// pick the density in the top layer
|
||||
const double rho = perf_densities_[0];
|
||||
const double rho = getRefDensity();
|
||||
|
||||
double thp = 0.0;
|
||||
if (this->isInjector()) {
|
||||
@ -3103,7 +2830,13 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
double
|
||||
StandardWell<TypeTag>::
|
||||
getRefDensity() const
|
||||
{
|
||||
return perf_densities_[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -3732,7 +3465,7 @@ namespace Opm
|
||||
const auto& controls = well_ecl_.productionControls(summary_state);
|
||||
const auto& table = vfp_properties_->getProd()->getTable(controls.vfp_table_number);
|
||||
const double vfp_ref_depth = table.getDatumDepth();
|
||||
const double rho = perf_densities_[0]; // Use the density at the top perforation.
|
||||
const double rho = getRefDensity(); // Use the density at the top perforation.
|
||||
const double thp_limit = this->getTHPConstraint(summary_state);
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
auto fbhp = [this, &controls, thp_limit, dp, alq_value](const std::vector<double>& rates) {
|
||||
@ -3937,7 +3670,7 @@ namespace Opm
|
||||
const auto& controls = well_ecl_.injectionControls(summary_state);
|
||||
const auto& table = vfp_properties_->getInj()->getTable(controls.vfp_table_number);
|
||||
const double vfp_ref_depth = table.getDatumDepth();
|
||||
const double rho = perf_densities_[0]; // Use the density at the top perforation.
|
||||
const double rho = getRefDensity(); // Use the density at the top perforation.
|
||||
const double thp_limit = this->getTHPConstraint(summary_state);
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
auto fbhp = [this, &controls, thp_limit, dp](const std::vector<double>& rates) {
|
||||
|
@ -226,9 +226,9 @@ namespace Opm
|
||||
std::vector<double>& well_potentials,
|
||||
Opm::DeferredLogger& deferred_logger) = 0;
|
||||
|
||||
virtual void updateWellStateWithTarget(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const = 0;
|
||||
void updateWellStateWithTarget(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
enum class IndividualOrGroup { Individual, Group, Both };
|
||||
bool updateWellControl(const Simulator& ebos_simulator,
|
||||
@ -476,6 +476,13 @@ namespace Opm
|
||||
|
||||
double getTHPConstraint(const SummaryState& summaryState) const;
|
||||
|
||||
template <class ValueType>
|
||||
ValueType calculateBhpFromThp(const WellState& well_state, const std::vector<ValueType>& rates, const Well& well, const SummaryState& summaryState, Opm::DeferredLogger& deferred_logger) const;
|
||||
|
||||
double getALQ(const WellState& well_state) const;
|
||||
|
||||
virtual double getRefDensity() const = 0;
|
||||
|
||||
// Component fractions for each phase for the well
|
||||
const std::vector<double>& compFrac() const;
|
||||
|
||||
|
@ -631,6 +631,61 @@ namespace Opm
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
template<class ValueType>
|
||||
ValueType
|
||||
WellInterface<TypeTag>::
|
||||
calculateBhpFromThp(const WellState &well_state,
|
||||
const std::vector<ValueType>& rates,
|
||||
const Well& well,
|
||||
const SummaryState& summaryState,
|
||||
Opm::DeferredLogger& deferred_logger) const
|
||||
{
|
||||
// TODO: when well is under THP control, the BHP is dependent on the rates,
|
||||
// the well rates is also dependent on the BHP, so it might need to do some iteration.
|
||||
// However, when group control is involved, change of the rates might impacts other wells
|
||||
// so iterations on a higher level will be required. Some investigation might be needed when
|
||||
// we face problems under THP control.
|
||||
|
||||
assert(int(rates.size()) == 3); // the vfp related only supports three phases now.
|
||||
|
||||
const ValueType aqua = rates[Water];
|
||||
const ValueType liquid = rates[Oil];
|
||||
const ValueType vapour = rates[Gas];
|
||||
|
||||
// pick the reference density
|
||||
// typically the reference in the top layer
|
||||
const double rho = getRefDensity();
|
||||
|
||||
if (this->isInjector() )
|
||||
{
|
||||
const auto& controls = well.injectionControls(summaryState);
|
||||
const double vfp_ref_depth = vfp_properties_->getInj()->getTable(controls.vfp_table_number).getDatumDepth();
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
return vfp_properties_->getInj()->bhp(controls.vfp_table_number, aqua, liquid, vapour, this->getTHPConstraint(summaryState)) - dp;
|
||||
}
|
||||
else if (this->isProducer()) {
|
||||
const auto& controls = well.productionControls(summaryState);
|
||||
const double vfp_ref_depth = vfp_properties_->getProd()->getTable(controls.vfp_table_number).getDatumDepth();
|
||||
const double dp = wellhelpers::computeHydrostaticCorrection(ref_depth_, vfp_ref_depth, rho, gravity_);
|
||||
return vfp_properties_->getProd()->bhp(controls.vfp_table_number, aqua, liquid, vapour, this->getTHPConstraint(summaryState), getALQ(well_state)) - dp;
|
||||
}
|
||||
else {
|
||||
OPM_DEFLOG_THROW(std::logic_error, "Expected INJECTOR or PRODUCER for well " + name(), deferred_logger);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
double
|
||||
WellInterface<TypeTag>::
|
||||
getALQ(const WellState &well_state) const
|
||||
{
|
||||
return well_state.getALQ(name());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1565,6 +1620,227 @@ namespace Opm
|
||||
}
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
WellInterface<TypeTag>::
|
||||
updateWellStateWithTarget(const Simulator& ebos_simulator,
|
||||
WellState& well_state,
|
||||
Opm::DeferredLogger& deferred_logger) const
|
||||
{
|
||||
|
||||
// only bhp and wellRates are used to initilize the primaryvariables for standard wells
|
||||
const auto& well = well_ecl_;
|
||||
const int well_index = index_of_well_;
|
||||
const auto& pu = phaseUsage();
|
||||
const int np = well_state.numPhases();
|
||||
const auto& summaryState = ebos_simulator.vanguard().summaryState();
|
||||
|
||||
if (this->wellIsStopped()) {
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] = 0.0;
|
||||
}
|
||||
well_state.thp()[well_index] = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->isInjector() )
|
||||
{
|
||||
const auto& controls = well.injectionControls(summaryState);
|
||||
|
||||
InjectorType injectorType = controls.injector_type;
|
||||
int phasePos;
|
||||
switch (injectorType) {
|
||||
case InjectorType::WATER:
|
||||
{
|
||||
phasePos = pu.phase_pos[BlackoilPhases::Aqua];
|
||||
break;
|
||||
}
|
||||
case InjectorType::OIL:
|
||||
{
|
||||
phasePos = pu.phase_pos[BlackoilPhases::Liquid];
|
||||
break;
|
||||
}
|
||||
case InjectorType::GAS:
|
||||
{
|
||||
phasePos = pu.phase_pos[BlackoilPhases::Vapour];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Expected WATER, OIL or GAS as type for injectors " + name(), deferred_logger );
|
||||
}
|
||||
|
||||
const Opm::Well::InjectorCMode& current = well_state.currentInjectionControls()[well_index];
|
||||
|
||||
switch(current) {
|
||||
case Well::InjectorCMode::RATE:
|
||||
{
|
||||
well_state.wellRates()[well_index*np + phasePos] = controls.surface_rate;
|
||||
break;
|
||||
}
|
||||
|
||||
case Well::InjectorCMode::RESV:
|
||||
{
|
||||
std::vector<double> convert_coeff(number_of_phases_, 1.0);
|
||||
rateConverter_.calcCoeff(/*fipreg*/ 0, pvtRegionIdx_, convert_coeff);
|
||||
const double coeff = convert_coeff[phasePos];
|
||||
well_state.wellRates()[well_index*np + phasePos] = controls.reservoir_rate/coeff;
|
||||
break;
|
||||
}
|
||||
|
||||
case Well::InjectorCMode::THP:
|
||||
{
|
||||
std::vector<double> rates(3, 0.0);
|
||||
for (int p = 0; p<np; ++p) {
|
||||
rates[p] = well_state.wellRates()[well_index*np + p];
|
||||
}
|
||||
double bhp = calculateBhpFromThp(well_state, rates, well, summaryState, deferred_logger);
|
||||
well_state.bhp()[well_index] = bhp;
|
||||
break;
|
||||
}
|
||||
case Well::InjectorCMode::BHP:
|
||||
{
|
||||
well_state.bhp()[well_index] = controls.bhp_limit;
|
||||
break;
|
||||
}
|
||||
case Well::InjectorCMode::GRUP:
|
||||
{
|
||||
//do nothing at the moment
|
||||
break;
|
||||
}
|
||||
case Well::InjectorCMode::CMODE_UNDEFINED:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Well control must be specified for well " + name(), deferred_logger );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//Producer
|
||||
else
|
||||
{
|
||||
const Well::ProducerCMode& current = well_state.currentProductionControls()[well_index];
|
||||
const auto& controls = well.productionControls(summaryState);
|
||||
|
||||
switch (current) {
|
||||
case Well::ProducerCMode::ORAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Oil] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.oil_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::WRAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Water] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.water_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::GRAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Gas] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.gas_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case Well::ProducerCMode::LRAT:
|
||||
{
|
||||
double current_rate = -well_state.wellRates()[ well_index*np + pu.phase_pos[Water] ]
|
||||
- well_state.wellRates()[ well_index*np + pu.phase_pos[Oil] ];
|
||||
|
||||
if (current_rate == 0.0)
|
||||
break;
|
||||
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.liquid_rate/current_rate;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::CRAT:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "CRAT control not supported " << name(), deferred_logger);
|
||||
}
|
||||
case Well::ProducerCMode::RESV:
|
||||
{
|
||||
std::vector<double> convert_coeff(number_of_phases_, 1.0);
|
||||
rateConverter_.calcCoeff(/*fipreg*/ 0, pvtRegionIdx_, convert_coeff);
|
||||
double total_res_rate = 0.0;
|
||||
for (int p = 0; p<np; ++p) {
|
||||
total_res_rate -= well_state.wellRates()[well_index*np + p] * convert_coeff[p];
|
||||
}
|
||||
if (total_res_rate == 0.0)
|
||||
break;
|
||||
|
||||
if (controls.prediction_mode) {
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= controls.resv_rate/total_res_rate;
|
||||
}
|
||||
} else {
|
||||
std::vector<double> hrates(number_of_phases_,0.);
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
|
||||
hrates[pu.phase_pos[Water]] = controls.water_rate;
|
||||
}
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
|
||||
hrates[pu.phase_pos[Oil]] = controls.oil_rate;
|
||||
}
|
||||
if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
|
||||
hrates[pu.phase_pos[Gas]] = controls.gas_rate;
|
||||
}
|
||||
std::vector<double> hrates_resv(number_of_phases_,0.);
|
||||
rateConverter_.calcReservoirVoidageRates(/*fipreg*/ 0, pvtRegionIdx_, hrates, hrates_resv);
|
||||
double target = std::accumulate(hrates_resv.begin(), hrates_resv.end(), 0.0);
|
||||
for (int p = 0; p<np; ++p) {
|
||||
well_state.wellRates()[well_index*np + p] *= target/total_res_rate;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::BHP:
|
||||
{
|
||||
well_state.bhp()[well_index] = controls.bhp_limit;
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::THP:
|
||||
{
|
||||
std::vector<double> rates(3, 0.0);
|
||||
for (int p = 0; p<np; ++p) {
|
||||
rates[p] = well_state.wellRates()[well_index*np + p];
|
||||
}
|
||||
double bhp = calculateBhpFromThp(well_state, rates, well, summaryState, deferred_logger);
|
||||
well_state.bhp()[well_index] = bhp;
|
||||
}
|
||||
case Well::ProducerCMode::GRUP:
|
||||
{
|
||||
//do nothing at the moment
|
||||
break;
|
||||
}
|
||||
case Well::ProducerCMode::CMODE_UNDEFINED:
|
||||
case Well::ProducerCMode::NONE:
|
||||
{
|
||||
OPM_DEFLOG_THROW(std::runtime_error, "Well control must be specified for well " + name() , deferred_logger);
|
||||
}
|
||||
|
||||
break;
|
||||
} // end of switch
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
bool
|
||||
|
Loading…
Reference in New Issue
Block a user