diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake
index bd5defda8..4d34bcb99 100644
--- a/CMakeLists_files.cmake
+++ b/CMakeLists_files.cmake
@@ -94,6 +94,7 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/WellProductionProperties.cpp
src/opm/parser/eclipse/EclipseState/Schedule/WellTestConfig.cpp
+ src/opm/parser/eclipse/EclipseState/Schedule/WellTestState.cpp
src/opm/parser/eclipse/EclipseState/SimulationConfig/SimulationConfig.cpp
src/opm/parser/eclipse/EclipseState/SimulationConfig/ThresholdPressure.cpp
src/opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.cpp
@@ -459,6 +460,7 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/Schedule/MSW/updatingCompletionsWithSegments.hpp
opm/parser/eclipse/EclipseState/Schedule/WellProductionProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/WellTestConfig.hpp
+ opm/parser/eclipse/EclipseState/Schedule/WellTestState.hpp
opm/parser/eclipse/EclipseState/Schedule/CompletionSet.hpp
opm/parser/eclipse/EclipseState/SimulationConfig/ThresholdPressure.hpp
opm/parser/eclipse/EclipseState/SimulationConfig/SimulationConfig.hpp
diff --git a/opm/parser/eclipse/EclipseState/Schedule/WellTestState.hpp b/opm/parser/eclipse/EclipseState/Schedule/WellTestState.hpp
new file mode 100644
index 000000000..ce63e82c3
--- /dev/null
+++ b/opm/parser/eclipse/EclipseState/Schedule/WellTestState.hpp
@@ -0,0 +1,82 @@
+/*
+ Copyright 2018 Statoil ASA.
+
+ This file is part of the Open Porous Media project (OPM).
+
+ OPM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OPM is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OPM. If not, see .
+*/
+#ifndef WELLTEST_STATE_H
+#define WELLTEST_STATE_H
+
+#include
+#include
+#include
+
+#include
+
+namespace Opm {
+
+class WellTestState {
+public:
+ /*
+ This class implements a small mutable state object which keeps track of
+ which wells have been automatically closed by the simulator, and by
+ checking with the WTEST configuration object the class can return a list
+ (well_name,reason) pairs for wells which should be checked as candiates
+ for opening.
+ */
+
+
+
+ struct ClosedWell {
+ std::string name;
+ WellTestConfig::Reason reason;
+ double last_test;
+ int num_attempt;
+ };
+
+ /*
+ The simulator has decided to close a particular well; we then add it here
+ as a closed well with a particualar reason.
+ */
+ void addClosedWell(const std::string& well_name, WellTestConfig::Reason reason, double sim_time);
+
+ /*
+ The update will consult the WellTestConfig object and return a list of
+ wells which should be checked for possible reopening; observe that the
+ 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> update(const WellTestConfig& config, double sim_time);
+
+ /*
+ If the simulator decides that a constraint is no longer met the drop()
+ method should be called to indicate that this reason for keeping the well
+ closed is no longer active.
+ */
+ void drop(const std::string& well_name, WellTestConfig::Reason reason);
+
+
+ bool has(const std::string well_name, WellTestConfig::Reason reason) const;
+ void openWell(const std::string& well_name);
+ size_t size() const;
+private:
+ std::vector wells;
+};
+
+
+}
+
+#endif
+
diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/WellTestState.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/WellTestState.cpp
new file mode 100644
index 000000000..2bf0f55cb
--- /dev/null
+++ b/src/opm/parser/eclipse/EclipseState/Schedule/WellTestState.cpp
@@ -0,0 +1,86 @@
+/*
+ Copyright 2018 Statoil ASA.
+
+ This file is part of the Open Porous Media project (OPM).
+
+ OPM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OPM is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with OPM. If not, see .
+*/
+#include
+#include
+
+#include
+#include
+
+namespace Opm {
+
+ void WellTestState::addClosedWell(const std::string& well_name, WellTestConfig::Reason reason, double sim_time) {
+ if (this->has(well_name, reason))
+ return;
+
+ this->wells.push_back({well_name, reason, sim_time, 0});
+ }
+
+
+ void WellTestState::openWell(const std::string& well_name) {
+ wells.erase(std::remove_if(wells.begin(),
+ wells.end(),
+ [&well_name](const ClosedWell& well) { return (well.name == well_name); }),
+ wells.end());
+ }
+
+
+ void WellTestState::drop(const std::string& well_name, WellTestConfig::Reason reason) {
+ wells.erase(std::remove_if(wells.begin(),
+ wells.end(),
+ [&well_name, reason](const ClosedWell& well) { return (well.name == well_name && well.reason == reason); }),
+ wells.end());
+ }
+
+
+ bool WellTestState::has(const std::string well_name, WellTestConfig::Reason reason) const {
+ const auto well_iter = std::find_if(wells.begin(),
+ wells.end(),
+ [&well_name, &reason](const ClosedWell& well)
+ {
+ return (reason == well.reason && well.name == well_name);
+ });
+ return (well_iter != wells.end());
+ }
+
+ size_t WellTestState::size() const {
+ return this->wells.size();
+ }
+
+
+ std::vector> WellTestState::update(const WellTestConfig& config, double sim_time) {
+ std::vector> output;
+ for (auto& closed_well : this->wells) {
+ if (config.has(closed_well.name, closed_well.reason)) {
+ const auto& well_config = config.get(closed_well.name, closed_well.reason);
+ double elapsed = sim_time - closed_well.last_test;
+
+ if (elapsed >= well_config.test_interval)
+ if (well_config.num_test == 0 || (closed_well.num_attempt < well_config.num_test)) {
+ closed_well.last_test = sim_time;
+ closed_well.num_attempt += 1;
+ output.push_back(std::make_pair(closed_well.name, closed_well.reason));
+ }
+
+ }
+ }
+ return output;
+ }
+}
+
+
diff --git a/tests/parser/WTEST.cpp b/tests/parser/WTEST.cpp
index 27e2e4fab..563d360e5 100644
--- a/tests/parser/WTEST.cpp
+++ b/tests/parser/WTEST.cpp
@@ -24,6 +24,7 @@
#define BOOST_TEST_MODULE WTEST
#include
+#include
#include
#include
#include
@@ -61,10 +62,60 @@ BOOST_AUTO_TEST_CASE(CreateWellTestConfig) {
BOOST_CHECK(!wc.has("NAMEX", WellTestConfig::Reason::ECONOMIC));
BOOST_CHECK(!wc.has("NAME"));
-
BOOST_CHECK_THROW(wc.get("NAMEX", WellTestConfig::Reason::ECONOMIC), std::invalid_argument);
BOOST_CHECK_THROW(wc.get("NO_NAME", WellTestConfig::Reason::ECONOMIC), std::invalid_argument);
const auto& wt = wc.get("NAMEX", WellTestConfig::Reason::PHYSICAL);
BOOST_CHECK_EQUAL(wt.name, "NAMEX");
}
+
+BOOST_AUTO_TEST_CASE(WTEST_STATE2) {
+ WellTestConfig wc;
+ WellTestState st;
+ wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 0, 0, 0);
+ st.addClosedWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 100);
+ BOOST_CHECK_EQUAL(st.size(), 1);
+
+ auto shut_wells = st.update(wc, 5000);
+ BOOST_CHECK_EQUAL( shut_wells.size(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(WTEST_STATE) {
+ WellTestConfig wc;
+ WellTestState st;
+ st.addClosedWell("WELL_NAME", WellTestConfig::Reason::ECONOMIC, 100);
+ BOOST_CHECK_EQUAL(st.size(), 1);
+
+ st.addClosedWell("WELL_NAME", WellTestConfig::Reason::ECONOMIC, 100);
+ BOOST_CHECK_EQUAL(st.size(), 1);
+
+ st.addClosedWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 100);
+ BOOST_CHECK_EQUAL(st.size(), 2);
+
+ st.addClosedWell("WELLX", WellTestConfig::Reason::PHYSICAL, 100);
+ BOOST_CHECK_EQUAL(st.size(), 3);
+
+ auto shut_wells = st.update(wc, 5000);
+ BOOST_CHECK_EQUAL( shut_wells.size(), 0);
+
+ wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1000, 2, 0);
+ // Not sufficient time has passed.
+ BOOST_CHECK_EQUAL( st.update(wc, 200).size(), 0);
+
+ // We should test it:
+ BOOST_CHECK_EQUAL( st.update(wc, 1200).size(), 1);
+
+ // Not sufficient time has passed.
+ BOOST_CHECK_EQUAL( st.update(wc, 1700).size(), 0);
+
+ // We should test it:
+ BOOST_CHECK_EQUAL( st.update(wc, 2400).size(), 1);
+
+ // Too many attempts:
+ BOOST_CHECK_EQUAL( st.update(wc, 24000).size(), 0);
+
+ st.drop("WELL_NAME", WellTestConfig::Reason::ECONOMIC);
+
+ st.openWell("WELL_NAME");
+ BOOST_CHECK_EQUAL(st.size(), 1);
+}