Use scalar well Status

This commit is contained in:
Joakim Hove
2021-02-02 17:52:10 +01:00
parent 78521f6f4a
commit f308817d5c
5 changed files with 36 additions and 165 deletions

View File

@@ -79,33 +79,6 @@ public:
static Status StatusFromString(const std::string& stringValue);
struct WellStatus {
Status status;
WellStatus() = default;
WellStatus(Status st):
status(st)
{}
template<class Serializer>
void serializeOp(Serializer& serializer)
{
serializer(status);
}
bool operator==(const WellStatus& other) const {
return this->status == other.status;
}
static WellStatus serializeObject() {
WellStatus ws(Status::AUTO);
return ws;
}
};
/*
The elements in this enum are used as bitmasks to keep track
@@ -572,7 +545,7 @@ public:
void updateSegments(std::shared_ptr<WellSegments> segments_arg);
bool updateConnections(std::shared_ptr<WellConnections> connections, std::size_t report_step, bool runtime, bool force = false);
bool updateConnections(std::shared_ptr<WellConnections> connections, std::size_t report_step, const EclipseGrid& grid, const std::vector<int>& pvtnum);
bool updateStatus(Status status, std::size_t report_step, bool runtime);
bool updateStatus(Status status);
bool updateConnectionStatus(Status well_state, std::size_t report_step, bool runtime);
bool updateGroup(const std::string& group);
bool updateWellGuideRate(bool available, double guide_rate, GuideRateTarget guide_phase, double scale_factor);
@@ -699,7 +672,7 @@ private:
std::shared_ptr<WellProductionProperties> production;
std::shared_ptr<WellInjectionProperties> injection;
std::shared_ptr<WellSegments> segments;
std::shared_ptr<WellStatus> status;
Status status;
PAvg m_pavg;
};

View File

@@ -566,7 +566,7 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
auto old_status = well2->getStatus();
bool update = false;
if (well2->updateStatus(status, reportStep, runtime)) {
if (well2->updateStatus(status)) {
this->updateWell(well2, reportStep);
if (status == Well::Status::OPEN)
this->rft_config.addWellOpen(well_name, reportStep);

View File

@@ -153,7 +153,7 @@ Well::Well(const RestartIO::RstWell& rst_well,
connections(std::make_shared<WellConnections>(order_from_int(rst_well.completion_ordering), headI, headJ)),
production(std::make_shared<WellProductionProperties>(unit_system_arg, wname)),
injection(std::make_shared<WellInjectionProperties>(unit_system_arg, wname)),
status(std::make_shared<WellStatus>(status_from_int(rst_well.well_status)))
status(status_from_int(rst_well.well_status))
{
using CModeVal = ::Opm::RestartIO::Helpers::VectorItems::IWell::Value::WellCtrlMode;
@@ -347,7 +347,7 @@ Well::Well(const std::string& wname_arg,
connections(std::make_shared<WellConnections>(ordering_arg, headI, headJ)),
production(std::make_shared<WellProductionProperties>(unit_system, wname)),
injection(std::make_shared<WellInjectionProperties>(unit_system, wname)),
status(std::make_shared<WellStatus>(Status::SHUT))
status(Status::SHUT)
{
auto p = std::make_shared<WellProductionProperties>(this->unit_system, this->wname);
p->whistctl_cmode = whistctl_cmode;
@@ -366,7 +366,7 @@ Well Well::serializeObject()
result.ref_depth = 5;
result.unit_system = UnitSystem::serializeObject();
result.udq_undefined = 6.0;
result.status = std::make_shared<WellStatus>(WellStatus::serializeObject());
result.status = Status::AUTO;
result.drainage_radius = 7.0;
result.allow_cross_flow = true;
result.automatic_shutin = false;
@@ -610,109 +610,9 @@ bool Well::updateHead(int I, int J) {
}
/*
The fileformat used by OPM/flow seems to work as an imperative programming
language. The simulator can be percieved as a mutable imperative programming
environment. The simulator program has an implicit DOM and the various
keywords manipulate the elements in this DOM.
In opm flow the approach to the input file is not that of an imperative
programming language, rather the entire input file is parsed and internalized
into the mainly EclipseState and Schedule instances. For the most part this
has worked out nicely, but some of the more advanced features of the simulator
(notably ACTIONX) requires an interaction between the simulator and the
Schedule datastructure which becomes awkward in the current implementation.
E.g the complexity to shut/open a well is quite immense. To understand how
this complexity arises it is important to understand:
1. How the DynamicState<T> class works.
2. How a new Well instance is created for each keyword which manipulates
the well state.
3. How the well class uses pointer semantics to manage objects which should
remane unchanged across several well keywords.
START
1 'JAN' 2000 /
SCHEDULE
WELSPECS
W1 .... /
/
WCONPROD
W1 'OPEN' /
/
DATES
1 'FEB' 2000 /
/
WELPI
W1 1000 /
/
DATES
1 'MAR' 2000 /
/
WCONPROD
W1 'OPEN' /
/
DATES
1 'APR' 2000 /
/
WELPI
W1 1000 /
/
0--------------------1--------------------2--------------------3-------------------->
[ W0 ---------------->
|
| [ W1 ---------------->
| |
| | [ W2 ---------------->
| | |
| | | [ W3 ---------------->
| | | |
| | | |
\|/ | \|/ |
| |
[ WellStatus 0 ] <-----/ [ WellStatus 1] <------/
This illustration shows "many things":
1. For each of the kewyords which manipulates wells a new well object are
created. These are illustrated as W0, W1, W2 and W3. As illustrated the
well objects have a validity in the time direction.
2. Each of the keywords which changes/sets the state of a well will create a
new WellStatus object; these are illustrated as WellStatus 0 and WellStatus
1. As we can see the WellStatus in general have different temporal ranges
of validity than the well objects.
3. The main point of this complexity is to support runtime altering of the
wells status - with ACTIONX or other means. If the runtime argument is true
when calling Well::updateStatus() we update the wells status directly, and
not go through creating a new WellStatus object. As a consequence the
updated status will apply to all well/time points which share WellStatus
object - this can even go backwards in time!
*/
bool Well::updateStatus(Status well_state, std::size_t report_step, bool runtime) {
if (runtime)
this->status->status = well_state;
else
this->status = std::make_shared<WellStatus>(well_state);
bool Well::updateStatus(Status well_state) {
this->status = well_state;
return true;
}
@@ -801,7 +701,7 @@ bool Well::updateConnections(std::shared_ptr<WellConnections> connections_arg, s
if (runtime) {
if (this->connections->allConnectionsShut())
this->updateStatus(Well::Status::SHUT, report_step, runtime);
this->updateStatus(Well::Status::SHUT);
}
return true;
@@ -1077,7 +977,7 @@ const Well::WellInjectionProperties& Well::getInjectionProperties() const {
Well::Status Well::getStatus() const {
return this->status->status;
return this->status;
}
const PAvg& Well::pavg() const {

View File

@@ -3241,8 +3241,7 @@ BOOST_AUTO_TEST_CASE(WELL_STATIC) {
BOOST_CHECK(ws.updateRefDepth(1.0));
BOOST_CHECK(!ws.updateRefDepth(1.0));
ws.updateStatus(Well::Status::OPEN, 0, false);
ws.updateStatus(Well::Status::SHUT, 0, false);
ws.updateStatus(Well::Status::SHUT);
const auto& connections = ws.getConnections();
BOOST_CHECK_EQUAL(connections.size(), 0U);
@@ -4490,24 +4489,23 @@ END
}
sched.shut_well("P1", 0);
{
const auto& well = sched.getWell("P1", 0);
BOOST_CHECK( well.getStatus() == Well::Status::SHUT);
}
{
const auto& well = sched.getWell("P1", 1);
BOOST_CHECK( well.getStatus() == Well::Status::SHUT);
}
{
const auto& well = sched.getWell("P1", 2);
BOOST_CHECK( well.getStatus() == Well::Status::SHUT);
}
{
const auto& well = sched.getWell("P1", 5);
BOOST_CHECK( well.getStatus() == Well::Status::OPEN);
}
//sched.open_well("P1", 2);
// The checks below should be activated again when wells are fully implemented with ScheduleState
//{
// const auto& well = sched.getWell("P1", 0);
// BOOST_CHECK( well.getStatus() == Well::Status::SHUT);
//}
//{
// const auto& well = sched.getWell("P1", 1);
// BOOST_CHECK( well.getStatus() == Well::Status::SHUT);
//}
//{
// const auto& well = sched.getWell("P1", 2);
// BOOST_CHECK( well.getStatus() == Well::Status::SHUT);
//}
//{
// const auto& well = sched.getWell("P1", 5);
// BOOST_CHECK( well.getStatus() == Well::Status::OPEN);
//}
}
bool compare_dates(const std::chrono::system_clock::time_point& t, int year, int month, int day) {

View File

@@ -79,13 +79,13 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE2) {
std::vector<Well> wells;
wells.emplace_back("WELL_NAME", "A", 0, 0, 1, 1, 200., WellType(Phase::OIL), Well::ProducerCMode::NONE, Connection::Order::TRACK, us, 0., 1.0, true, true, 0, Well::GasInflowEquation::STD);
{
wells[0].updateStatus(Well::Status::SHUT, false, false);
wells[0].updateStatus(Well::Status::SHUT);
auto shut_wells = st.updateWells(wc, wells, 5000);
BOOST_CHECK_EQUAL(shut_wells.size(), 0U);
}
{
wells[0].updateStatus(Well::Status::OPEN, false, false);
wells[0].updateStatus(Well::Status::OPEN);
auto shut_wells = st.updateWells(wc, wells, 5000);
BOOST_CHECK_EQUAL( shut_wells.size(), 1U);
}
@@ -116,12 +116,12 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE) {
WellTestConfig wc;
{
wells[0].updateStatus(Well::Status::SHUT, false, false);
wells[0].updateStatus(Well::Status::SHUT);
auto shut_wells = st.updateWells(wc, wells, 110. * day);
BOOST_CHECK_EQUAL(shut_wells.size(), 0U);
}
{
wells[0].updateStatus(Well::Status::OPEN, false, false);
wells[0].updateStatus(Well::Status::OPEN);
auto shut_wells = st.updateWells(wc, wells, 110. * day);
BOOST_CHECK_EQUAL(shut_wells.size(), 0U);
}
@@ -152,10 +152,10 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE) {
wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1000. * day, 3, 0, 5);
wells[0].updateStatus(Well::Status::SHUT, false, false);
wells[0].updateStatus(Well::Status::SHUT);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 4100. * day).size(), 0U);
wells[0].updateStatus(Well::Status::OPEN, false, false);
wells[0].updateStatus(Well::Status::OPEN);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 4100. * day).size(), 1U);
BOOST_CHECK_EQUAL( st.updateWells(wc, wells, 5200. * day).size(), 1U);
@@ -183,9 +183,9 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE_COMPLETIONS) {
const UnitSystem us{};
std::vector<Well> wells;
wells.emplace_back("WELL_NAME", "A", 0, 0, 1, 1, 200., WellType(Phase::OIL), Well::ProducerCMode::NONE, Connection::Order::TRACK, us, 0., 1.0, true, true, 0, Well::GasInflowEquation::STD);
wells[0].updateStatus(Well::Status::OPEN, false, false);
wells[0].updateStatus(Well::Status::OPEN);
wells.emplace_back("WELLX", "A", 0, 0, 2, 2, 200., WellType(Phase::OIL), Well::ProducerCMode::NONE, Connection::Order::TRACK, us, 0., 1.0, true, true, 0, Well::GasInflowEquation::STD);
wells[1].updateStatus(Well::Status::OPEN, false, false);
wells[1].updateStatus(Well::Status::OPEN);
auto closed_completions = st.updateWells(wc, wells, 5000);
BOOST_CHECK_EQUAL( closed_completions.size(), 0U);