mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
first version of the well testing for physical reason
the key difficulty is that we do not have reliable explicit information to do the testing. In this version, we try to obtain the explicit information by finishing one converged solving.
This commit is contained in:
parent
4343ae6be0
commit
eaa3ad19f5
@ -349,6 +349,11 @@ namespace Opm
|
||||
void assembleWellEqWithoutIteration(const Simulator& ebosSimulator,
|
||||
const double dt,
|
||||
WellState& well_state);
|
||||
|
||||
virtual void wellTestingPhysical(Simulator& simulator, const std::vector<double>& B_avg,
|
||||
const double simulation_time, const int report_step,
|
||||
const bool terminal_output,
|
||||
WellState& well_state, WellTestState& welltest_state) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1648,7 +1648,7 @@ namespace Opm
|
||||
checkWellOperability(const Simulator& /* ebos_simulator */,
|
||||
const WellState& /* well_state */)
|
||||
{
|
||||
const std::string msg = "Support of well operatability checking for mutlisegment wells is not implemented "
|
||||
const std::string msg = "Support of well operability checking for multisegment wells is not implemented "
|
||||
"yet, checkWellOperability() for " + name() + " will do nothing";
|
||||
OpmLog::warning("NO_OPERATABILITY_CHECKING_MS_WELLS", msg);
|
||||
}
|
||||
@ -1888,4 +1888,20 @@ namespace Opm
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
MultisegmentWell<TypeTag>::
|
||||
wellTestingPhysical(Simulator& simulator, const std::vector<double>& B_avg,
|
||||
const double simulation_time, const int report_step, const bool terminal_output,
|
||||
WellState& well_state, WellTestState& welltest_state)
|
||||
{
|
||||
const std::string msg = "Support of well testing for physical limits for multisegment wells is not "
|
||||
"implemented yet, wellTestingPhysical() for " + name() + " will do nothing";
|
||||
OpmLog::warning("NO_WELLTESTPHYSICAL_CHECKING_MS_WELLS", msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -348,11 +348,16 @@ namespace Opm
|
||||
// updating the inflow based on the current reservoir condition
|
||||
void updateIPR(const Simulator& ebos_simulator) const;
|
||||
|
||||
// check whether the well is operable under the current reservoir condition
|
||||
// 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 WellState& well_state) 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 WellState& well_state);
|
||||
|
||||
// check whether the well is operable under BHP limit with current reservoir condition
|
||||
void checkOperabilityUnderBHPLimitProducer(const Simulator& ebos_simulator);
|
||||
|
||||
@ -398,6 +403,10 @@ namespace Opm
|
||||
// calculate a relaxation factor to avoid overshoot of total rates
|
||||
static double relaxationFactorRate(const std::vector<double>& primary_variables,
|
||||
const BVectorWell& dwells);
|
||||
|
||||
virtual void wellTestingPhysical(Simulator& simulator, const std::vector<double>& B_avg,
|
||||
const double simulation_time, const int report_step, const bool terminal_output,
|
||||
WellState& well_state, WellTestState& welltest_state);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1307,6 +1307,27 @@ namespace Opm
|
||||
|
||||
const bool old_well_operable = this->operability_status_.isOperable();
|
||||
|
||||
updateWellOperability(ebos_simulator, well_state);
|
||||
|
||||
const bool well_operable = this->operability_status_.isOperable();
|
||||
|
||||
if (!well_operable && old_well_operable) {
|
||||
OpmLog::info(" well " + name() + " gets SHUT during iteration ");
|
||||
} else if (well_operable && !old_well_operable) {
|
||||
OpmLog::info(" well " + name() + " gets REVIVED during iteration ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
StandardWell<TypeTag>::
|
||||
updateWellOperability(const Simulator& ebos_simulator,
|
||||
const WellState& well_state)
|
||||
{
|
||||
this->operability_status_.reset();
|
||||
|
||||
updateIPR(ebos_simulator);
|
||||
@ -1321,14 +1342,6 @@ namespace Opm
|
||||
this->operability_status_.can_produce_inject_with_current_bhp =
|
||||
canProduceInjectWithCurrentBhp(ebos_simulator, well_state);
|
||||
}
|
||||
|
||||
const bool well_operable = this->operability_status_.isOperable();
|
||||
|
||||
if (!well_operable && old_well_operable) {
|
||||
OpmLog::info(" well " + name() + " gets SHUT during iteration ");
|
||||
} else if (well_operable && !old_well_operable) {
|
||||
OpmLog::info(" well " + name() + " gets REVIVED during iteration ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2706,4 +2719,67 @@ namespace Opm
|
||||
|
||||
return relaxation_factor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
StandardWell<TypeTag>::
|
||||
wellTestingPhysical(Simulator& ebos_simulator, const std::vector<double>& B_avg,
|
||||
const double simulation_time, const int report_step, const bool terminal_output,
|
||||
WellState& well_state, WellTestState& welltest_state)
|
||||
{
|
||||
OpmLog::debug(" well " + name() + " is being tested for physical limits");
|
||||
|
||||
// some most difficult things are the explicit quantities, since there is no information
|
||||
// in the WellState to do a decent initialization
|
||||
|
||||
// TODO: Let us assume that the simulator is updated
|
||||
|
||||
// Let us try to do a normal simualtion running, to keep checking the operability status
|
||||
// If the well is not operable during any of the time. It means it does not pass the physical
|
||||
// limit test.
|
||||
|
||||
// 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 = well_state;
|
||||
|
||||
// TODO: well state for this well is kind of all zero status
|
||||
// we should be able to provide a better initialization
|
||||
calculateExplicitQuantities(ebos_simulator, well_state_copy);
|
||||
|
||||
updateWellOperability(ebos_simulator, well_state_copy);
|
||||
|
||||
if ( !this->isOperable() ) {
|
||||
const std::string msg = " well " + name() + " is not operable during well testing for physical reason";
|
||||
OpmLog::debug(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
updateWellStateWithTarget(ebos_simulator, well_state_copy);
|
||||
|
||||
calculateExplicitQuantities(ebos_simulator, well_state_copy);
|
||||
updatePrimaryVariables(well_state_copy);
|
||||
initPrimaryVariablesEvaluation();
|
||||
|
||||
const bool converged = this->solveWellEqUntilConverged(ebos_simulator, B_avg, well_state_copy);
|
||||
|
||||
if (!converged) {
|
||||
const std::string msg = " well " + name() + " did not get converged during well testing for physical reason";
|
||||
OpmLog::debug(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->isOperable() ) {
|
||||
welltest_state.openWell(name() );
|
||||
const std::string msg = " well " + name() + " is re-opened through well testing for physical reason";
|
||||
OpmLog::info(msg);
|
||||
well_state = well_state_copy;
|
||||
} else {
|
||||
const std::string msg = " well " + name() + " is not operable during well testing for physical reason";
|
||||
OpmLog::debug(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,8 +218,8 @@ namespace Opm
|
||||
// Simulator is not const is because that assembleWellEq is non-const Simulator
|
||||
void wellTesting(Simulator& simulator, const std::vector<double>& B_avg,
|
||||
const double simulation_time, const int report_step, const bool terminal_output,
|
||||
const WellTestConfig::Reason testing_reason, const WellState& well_state,
|
||||
WellTestState& welltest_state);
|
||||
const WellTestConfig::Reason testing_reason,
|
||||
/* const */ WellState& well_state, WellTestState& welltest_state);
|
||||
|
||||
void updatePerforatedCell(std::vector<bool>& is_cell_perforated);
|
||||
|
||||
@ -364,6 +364,10 @@ namespace Opm
|
||||
const double simulation_time, const int report_step, const bool terminal_output,
|
||||
const WellState& well_state, WellTestState& welltest_state);
|
||||
|
||||
virtual void wellTestingPhysical(Simulator& simulator, const std::vector<double>& B_avg,
|
||||
const double simulation_time, const int report_step, const bool terminal_output,
|
||||
WellState& well_state, WellTestState& welltest_state) = 0;
|
||||
|
||||
void updateWellTestStateEconomic(const WellState& well_state,
|
||||
const double simulation_time,
|
||||
const bool write_message_to_opmlog,
|
||||
@ -374,7 +378,12 @@ namespace Opm
|
||||
const bool write_message_to_opmlog,
|
||||
WellTestState& well_test_state) const;
|
||||
|
||||
void solveWellForTesting(Simulator& ebosSimulator, WellState& well_state, const std::vector<double>& B_avg, bool terminal_output);
|
||||
void solveWellForTesting(Simulator& ebosSimulator, WellState& well_state,
|
||||
const std::vector<double>& B_avg, bool terminal_output);
|
||||
|
||||
bool solveWellEqUntilConverged(Simulator& ebosSimulator,
|
||||
const std::vector<double>& B_avg,
|
||||
WellState& well_state);
|
||||
|
||||
void scaleProductivityIndex(const int perfIdx, double& productivity_index) const;
|
||||
|
||||
|
@ -923,9 +923,15 @@ namespace Opm
|
||||
WellInterface<TypeTag>::
|
||||
wellTesting(Simulator& simulator, const std::vector<double>& B_avg,
|
||||
const double simulation_time, const int report_step, const bool terminal_output,
|
||||
const WellTestConfig::Reason testing_reason, const WellState& well_state,
|
||||
const WellTestConfig::Reason testing_reason,
|
||||
/* const */ WellState& well_state,
|
||||
WellTestState& well_test_state)
|
||||
{
|
||||
if (testing_reason == WellTestConfig::Reason::PHYSICAL) {
|
||||
wellTestingPhysical(simulator, B_avg, simulation_time, report_step,
|
||||
terminal_output, well_state, well_test_state);
|
||||
}
|
||||
|
||||
if (testing_reason == WellTestConfig::Reason::ECONOMIC) {
|
||||
wellTestingEconomic(simulator, B_avg, simulation_time, report_step,
|
||||
terminal_output, well_state, well_test_state);
|
||||
@ -1139,6 +1145,42 @@ namespace Opm
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
bool
|
||||
WellInterface<TypeTag>::
|
||||
solveWellEqUntilConverged(Simulator& ebosSimulator,
|
||||
const std::vector<double>& B_avg,
|
||||
WellState& well_state)
|
||||
{
|
||||
const int max_iter = param_.max_welleq_iter_;
|
||||
int it = 0;
|
||||
const double dt = 1.0; //not used for the well tests
|
||||
bool converged;
|
||||
WellState well_state0 = well_state;
|
||||
do {
|
||||
assembleWellEq(ebosSimulator, dt, well_state);
|
||||
|
||||
auto report = getWellConvergence(B_avg);
|
||||
converged = report.converged();
|
||||
if (converged) {
|
||||
break;
|
||||
}
|
||||
|
||||
++it;
|
||||
solveEqAndUpdateWellState(well_state);
|
||||
|
||||
wellhelpers::WellSwitchingLogger logger;
|
||||
updateWellControl(ebosSimulator, well_state, logger);
|
||||
initPrimaryVariablesEvaluation();
|
||||
} while (it < max_iter);
|
||||
|
||||
return converged;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
WellInterface<TypeTag>::calculateReservoirRates(WellState& well_state) const
|
||||
@ -1176,37 +1218,24 @@ namespace Opm
|
||||
|
||||
template<typename TypeTag>
|
||||
void
|
||||
WellInterface<TypeTag>::solveWellForTesting(Simulator& ebosSimulator, WellState& well_state, const std::vector<double>& B_avg, bool terminal_output)
|
||||
WellInterface<TypeTag>::
|
||||
solveWellForTesting(Simulator& ebosSimulator, WellState& well_state,
|
||||
const std::vector<double>& B_avg, bool terminal_output)
|
||||
{
|
||||
const int max_iter = param_.max_welleq_iter_;
|
||||
int it = 0;
|
||||
const double dt = 1.0; //not used for the well tests
|
||||
bool converged;
|
||||
WellState well_state0 = well_state;
|
||||
do {
|
||||
assembleWellEq(ebosSimulator, dt, well_state);
|
||||
// keep a copy of the original well state
|
||||
const WellState well_state0 = well_state;
|
||||
|
||||
auto report = getWellConvergence(B_avg);
|
||||
converged = report.converged();
|
||||
if (converged) {
|
||||
break;
|
||||
}
|
||||
|
||||
++it;
|
||||
solveEqAndUpdateWellState(well_state);
|
||||
|
||||
wellhelpers::WellSwitchingLogger logger;
|
||||
updateWellControl(ebosSimulator, well_state, logger);
|
||||
initPrimaryVariablesEvaluation();
|
||||
} while (it < max_iter);
|
||||
const bool converged = solveWellEqUntilConverged(ebosSimulator, B_avg, well_state);
|
||||
|
||||
if (converged) {
|
||||
if ( terminal_output ) {
|
||||
OpmLog::debug("WellTest: Well equation for well " + name() + " solution gets converged with " + std::to_string(it) + " iterations");
|
||||
OpmLog::debug("WellTest: Well equation for well " + name() + " solution gets converged");
|
||||
}
|
||||
} else {
|
||||
if ( terminal_output ) {
|
||||
OpmLog::debug("WellTest: Well equation for well" +name() + " solution failed in getting converged with " + std::to_string(it) + " iterations");
|
||||
const int max_iter = param_.max_welleq_iter_;
|
||||
OpmLog::debug("WellTest: Well equation for well" +name() + " solution failed in getting converged with "
|
||||
+ std::to_string(max_iter) + " iterations");
|
||||
}
|
||||
well_state = well_state0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user