WELOPEN and WCON* interact with WECON and WTEST

WELOPEN and WCON* can open well closed due to various reasons, physical
or economic.

If a well is shut with WELOPEN and WCON*, we do not try to re-open it
through WTEST.
This commit is contained in:
Kai Bao
2019-07-02 16:30:57 +02:00
parent 0694515c69
commit 011666b3f9
3 changed files with 97 additions and 17 deletions

View File

@@ -24,6 +24,7 @@
#include <vector>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Well2.hpp>
namespace Opm {
@@ -81,7 +82,9 @@ public:
update method will update the internal state of the object by counting up
the openiing attempts, and also set the time for the last attempt to open.
*/
std::vector<std::pair<std::string, WellTestConfig::Reason>> updateWell(const WellTestConfig& config, double sim_time);
std::vector<std::pair<std::string, WellTestConfig::Reason>> updateWells(const WellTestConfig& config,
const std::vector<Well2>& wells_ecl,
double sim_time);
/*
The update will consult the WellTestConfig object and return a list of
@@ -100,8 +103,17 @@ public:
bool hasWellClosed(const std::string& well_name, WellTestConfig::Reason reason) const;
/* whether there is a well with the well_name closed in the WellTestState,
* no matter what is the closing cause */
bool hasWellClosed(const std::string& well_name) const;
void openWell(const std::string& well_name, WellTestConfig::Reason reason);
/* open the well no matter what is the closing cause.
* it is used when WELOPEN or WCON* keyword request to open the well */
void openWell(const std::string& well_name);
bool hasCompletion(const std::string& well_name, const int complnum) const;
size_t sizeWells() const;

View File

@@ -60,6 +60,21 @@ namespace Opm {
}
void WellTestState::openWell(const std::string& well_name) {
for (auto& well : wells)
if (well.name == well_name)
well.closed = false;
}
bool WellTestState::hasWellClosed(const std::string& well_name) const {
for (const auto& well : wells)
if (well.name == well_name && well.closed)
return true;
return false;
}
bool WellTestState::hasWellClosed(const std::string& well_name, WellTestConfig::Reason reason) const {
const auto well_iter = std::find_if(wells.begin(),
wells.end(),
@@ -85,12 +100,28 @@ namespace Opm {
return this->wells.size();
}
std::vector<std::pair<std::string, WellTestConfig::Reason>> WellTestState::updateWell(const WellTestConfig& config, double sim_time) {
std::vector<std::pair<std::string, WellTestConfig::Reason>>
WellTestState::updateWells(const WellTestConfig& config,
const std::vector<Well2>& wells_ecl,
double sim_time) {
std::vector<std::pair<std::string, WellTestConfig::Reason>> output;
updateForNewWTEST(config);
for (auto& well : this->wells) {
auto well_ecl = std::find_if(wells_ecl.begin(), wells_ecl.end(),
[&well](const Well2& w)
{
return w.name() == well.name;
});
if (well_ecl == wells_ecl.end())
throw std::runtime_error("No well named " + well.name + " is found in wells_ecl.");
// if the well is SHUT, we do not consider to test it
if (well_ecl->getStatus() != WellCommon::OPEN)
continue;
if (well.closed && config.has(well.name, well.reason)) {
const auto& well_config = config.get(well.name, well.reason);
double elapsed = sim_time - well.last_test;
@@ -167,7 +198,7 @@ namespace Opm {
return (well.name == well_name);
});
if (well_iter == wells.end())
throw std::runtime_error("No well named " + well_name + " found in WellTestState.");
throw std::runtime_error("No well named " + well_name + " is found in WellTestState.");
return well_iter->last_test;
}

View File

@@ -75,8 +75,20 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE2) {
st.closeWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 100);
BOOST_CHECK_EQUAL(st.sizeWells(), 1);
auto shut_wells = st.updateWell(wc, 5000);
BOOST_CHECK_EQUAL( shut_wells.size(), 1);
const UnitSystem us{};
std::vector<Well2> wells;
wells.emplace_back("WELL_NAME", "A", 0, 0, 1, 1, 200., Phase::OIL, WellProducer::NONE, WellCompletion::TRACK, us, 0.);
{
wells[0].updateStatus(WellCommon::SHUT);
auto shut_wells = st.updateWells(wc, wells, 5000);
BOOST_CHECK_EQUAL(shut_wells.size(), 0);
}
{
wells[0].updateStatus(WellCommon::OPEN);
auto shut_wells = st.updateWells(wc, wells, 5000);
BOOST_CHECK_EQUAL( shut_wells.size(), 1);
}
}
BOOST_AUTO_TEST_CASE(WTEST_STATE) {
@@ -97,41 +109,59 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE) {
st.closeWell("WELLX", WellTestConfig::Reason::PHYSICAL, 100. * day);
BOOST_CHECK_EQUAL(st.sizeWells(), 3);
const UnitSystem us{};
std::vector<Well2> wells;
wells.emplace_back("WELL_NAME", "A", 0, 0, 1, 1, 200., Phase::OIL, WellProducer::NONE, WellCompletion::TRACK, us, 0.);
wells.emplace_back("WELLX", "A", 0, 0, 2, 2, 200., Phase::OIL, WellProducer::NONE, WellCompletion::TRACK, us, 0.);
WellTestConfig wc;
auto shut_wells = st.updateWell(wc, 110. * day);
BOOST_CHECK_EQUAL( shut_wells.size(), 0);
{
wells[0].updateStatus(WellCommon::SHUT);
auto shut_wells = st.updateWells(wc, wells, 110. * day);
BOOST_CHECK_EQUAL(shut_wells.size(), 0);
}
{
wells[0].updateStatus(WellCommon::OPEN);
auto shut_wells = st.updateWells(wc, wells, 110. * day);
BOOST_CHECK_EQUAL(shut_wells.size(), 0);
}
wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1000. * day, 2, 0, 1);
// Not sufficient time has passed.
BOOST_CHECK_EQUAL( st.updateWell(wc, 200. * day).size(), 0);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 200. * day).size(), 0);
// We should test it:
BOOST_CHECK_EQUAL( st.updateWell(wc, 1200. * day).size(), 1);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 1200. * day).size(), 1);
// Not sufficient time has passed.
BOOST_CHECK_EQUAL( st.updateWell(wc, 1700. * day).size(), 0);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 1700. * day).size(), 0);
st.openWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL);
st.closeWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1900. * day);
// We should not test it:
BOOST_CHECK_EQUAL( st.updateWell(wc, 2400. * day).size(), 0);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 2400. * day).size(), 0);
// We should test it now:
BOOST_CHECK_EQUAL( st.updateWell(wc, 3000. * day).size(), 1);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 3000. * day).size(), 1);
// Too many attempts:
BOOST_CHECK_EQUAL( st.updateWell(wc, 4000. * day).size(), 0);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 4000. * day).size(), 0);
wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1000. * day, 3, 0, 5);
BOOST_CHECK_EQUAL( st.updateWell(wc, 4100. * day).size(), 1);
BOOST_CHECK_EQUAL( st.updateWell(wc, 5200. * day).size(), 1);
wells[0].updateStatus(WellCommon::SHUT);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 4100. * day).size(), 0);
wells[0].updateStatus(WellCommon::OPEN);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 4100. * day).size(), 1);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 5200. * day).size(), 1);
wc.drop_well("WELL_NAME");
BOOST_CHECK_EQUAL( st.updateWell(wc, 6300. * day).size(), 0);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 6300. * day).size(), 0);
}
@@ -150,7 +180,14 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE_COMPLETIONS) {
st.addClosedCompletion("WELLX", 3, 100);
BOOST_CHECK_EQUAL(st.sizeCompletions(), 3);
auto closed_completions = st.updateWell(wc, 5000);
const UnitSystem us{};
std::vector<Well2> wells;
wells.emplace_back("WELL_NAME", "A", 0, 0, 1, 1, 200., Phase::OIL, WellProducer::NONE, WellCompletion::TRACK, us, 0.);
wells[0].updateStatus(WellCommon::OPEN);
wells.emplace_back("WELLX", "A", 0, 0, 2, 2, 200., Phase::OIL, WellProducer::NONE, WellCompletion::TRACK, us, 0.);
wells[1].updateStatus(WellCommon::OPEN);
auto closed_completions = st.updateWells(wc, wells, 5000);
BOOST_CHECK_EQUAL( closed_completions.size(), 0);
wc.add_well("WELL_NAME", WellTestConfig::Reason::COMPLETION, 1000, 2, 0, 0);