Use scalar well Status
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user