diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake
index f16fe2cfdd0..dc1d856971a 100644
--- a/CMakeLists_files.cmake
+++ b/CMakeLists_files.cmake
@@ -284,6 +284,7 @@ if(ENABLE_ECL_INPUT)
opm/input/eclipse/Schedule/ResCoup/GrupSlav.cpp
opm/input/eclipse/Schedule/ResCoup/MasterGroup.cpp
opm/input/eclipse/Schedule/ResCoup/Slaves.cpp
+ opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.cpp
opm/input/eclipse/Schedule/UDQ/UDQKeywordHandlers.cpp
opm/input/eclipse/Schedule/UDQ/UDQActive.cpp
opm/input/eclipse/Schedule/UDQ/UDQAssign.cpp
@@ -1307,6 +1308,7 @@ if(ENABLE_ECL_INPUT)
opm/input/eclipse/Schedule/ResCoup/GrupSlav.hpp
opm/input/eclipse/Schedule/ResCoup/MasterGroup.hpp
opm/input/eclipse/Schedule/ResCoup/Slaves.hpp
+ opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.hpp
opm/input/eclipse/Schedule/VFPInjTable.hpp
opm/input/eclipse/Schedule/VFPProdTable.hpp
opm/input/eclipse/Schedule/Well/Connection.hpp
diff --git a/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.cpp b/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.cpp
new file mode 100644
index 00000000000..7fc4084d497
--- /dev/null
+++ b/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.cpp
@@ -0,0 +1,58 @@
+/*
+ Copyright 2024 Equinor 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
+#include
+#include
+#include "../HandlerContext.hpp"
+
+
+namespace Opm {
+
+void handleRCMASTS(HandlerContext& handlerContext)
+{
+ auto& schedule_state = handlerContext.state();
+ auto rescoup = schedule_state.rescoup();
+ auto tuning = schedule_state.tuning();
+ const auto& keyword = handlerContext.keyword;
+ if (keyword.size() != 1) {
+ throw OpmInputError("RCMASTS keyword requires exactly one record.", keyword.location());
+ }
+ auto record = keyword[0];
+ auto deck_item = record.getItem();
+ if (deck_item.defaultApplied(0)) {
+ // The default value is the current value TSMINZ
+ rescoup.masterMinTimeStep(tuning.TSMINZ);
+ }
+ else {
+ auto tstep = deck_item.getSIDouble(0);
+ if (tstep < 0.0) {
+ throw OpmInputError("Negative value for RCMASTS is not allowed.", keyword.location());
+ }
+ rescoup.masterMinTimeStep(tstep);
+ }
+ schedule_state.rescoup.update( std::move( rescoup ));
+}
+
+} // namespace Opm
+
diff --git a/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.hpp b/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.hpp
new file mode 100644
index 00000000000..a963a9fbc45
--- /dev/null
+++ b/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.hpp
@@ -0,0 +1,28 @@
+/*
+ Copyright 2024 Equinor 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 RESERVOIR_COUPLING_MASTER_MINIMUM_TIMESTEP_HPP
+#define RESERVOIR_COUPLING_MASTER_MINIMUM_TIMESTEP_HPP
+namespace Opm {
+
+class HandlerContext;
+
+extern void handleRCMASTS(HandlerContext& handlerContext);
+
+} // namespace Opm
+#endif // RESERVOIR_COUPLING_MASTER_MINIMUM_TIMESTEP_HPP
diff --git a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.cpp b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.cpp
index 6e5e867c7a4..8462e81abca 100644
--- a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.cpp
+++ b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.cpp
@@ -28,7 +28,8 @@ bool CouplingInfo::operator==(const CouplingInfo& rhs) const {
return this->m_slaves == rhs.m_slaves &&
this->m_master_groups == rhs.m_master_groups &&
this->m_grup_slavs == rhs.m_grup_slavs &&
- this->m_master_mode == rhs.m_master_mode;
+ this->m_master_mode == rhs.m_master_mode &&
+ this->m_master_min_time_step == rhs.m_master_min_time_step;
}
CouplingInfo CouplingInfo::serializationTestObject()
diff --git a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.hpp b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.hpp
index 317e47e03f1..d1f0884ba95 100644
--- a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.hpp
+++ b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.hpp
@@ -34,56 +34,80 @@ class CouplingInfo {
public:
CouplingInfo() = default;
- static CouplingInfo serializationTestObject();
- const std::map& slaves() const {
- return this->m_slaves;
- }
- std::map& slaves() {
- return this->m_slaves;
- }
- const std::map& masterGroups() const {
- return this->m_master_groups;
- }
- std::map& masterGroups() {
- return this->m_master_groups;
- }
+ // Inline methods (alphabetically)
+
const std::map& grupSlavs() const {
return this->m_grup_slavs;
}
+
+ const GrupSlav& grupSlav(const std::string& name) const {
+ return m_grup_slavs.at(name);
+ }
+
std::map& grupSlavs() {
return this->m_grup_slavs;
}
- bool operator==(const CouplingInfo& other) const;
- bool hasSlave(const std::string& name) const {
- return m_slaves.find(name) != m_slaves.end();
- }
- const Slave& slave(const std::string& name) const {
- return m_slaves.at(name);
- }
- int slaveCount() const {
- return m_slaves.size();
- }
+
bool hasGrupSlav(const std::string& name) const {
return m_grup_slavs.find(name) != m_grup_slavs.end();
}
- const GrupSlav& grupSlav(const std::string& name) const {
- return m_grup_slavs.at(name);
- }
+
bool hasMasterGroup(const std::string& name) const {
return m_master_groups.find(name) != m_master_groups.end();
}
+
+ bool hasSlave(const std::string& name) const {
+ return m_slaves.find(name) != m_slaves.end();
+ }
+
const MasterGroup& masterGroup(const std::string& name) const {
return m_master_groups.at(name);
}
+
int masterGroupCount() const {
return m_master_groups.size();
}
+
+ const std::map& masterGroups() const {
+ return this->m_master_groups;
+ }
+
bool masterMode() const {
return m_master_mode;
}
+
void masterMode(bool master_mode) {
m_master_mode = master_mode;
}
+
+ std::map& masterGroups() {
+ return this->m_master_groups;
+ }
+
+ double masterMinTimeStep() const {
+ return m_master_min_time_step;
+ }
+
+ void masterMinTimeStep(double tstep) {
+ m_master_min_time_step = tstep;
+ }
+
+ const Slave& slave(const std::string& name) const {
+ return m_slaves.at(name);
+ }
+
+ const std::map& slaves() const {
+ return this->m_slaves;
+ }
+
+ int slaveCount() const {
+ return m_slaves.size();
+ }
+
+ std::map& slaves() {
+ return this->m_slaves;
+ }
+
template
void serializeOp(Serializer& serializer)
{
@@ -91,12 +115,21 @@ class CouplingInfo {
serializer(m_master_groups);
serializer(m_grup_slavs);
serializer(m_master_mode);
+ serializer(m_master_min_time_step);
}
+
+ // Non-inline methods (defined in CouplingInfo.cpp)
+
+ bool operator==(const CouplingInfo& other) const;
+ static CouplingInfo serializationTestObject();
+
private:
std::map m_slaves;
std::map m_master_groups;
std::map m_grup_slavs;
bool m_master_mode{false};
+ // Default value: No limit, however a positive value can be set by using keyword RCMASTS
+ double m_master_min_time_step{0.0};
};
} // namespace Opm::ReservoirCoupling
diff --git a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.cpp b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.cpp
index 4e7a0082b76..3d2301566cd 100644
--- a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.cpp
+++ b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.cpp
@@ -23,22 +23,20 @@
#include "GrupSlav.hpp"
#include "Slaves.hpp"
#include "MasterGroup.hpp"
+#include "MasterMinimumTimeStep.hpp"
#include
namespace Opm {
-namespace {
-
-} // anonymous namespace
-
std::vector>
getReservoirCouplingHandlers()
{
return {
{ "SLAVES", &handleSLAVES },
{ "GRUPMAST", &handleGRUPMAST},
- { "GRUPSLAV", &handleGRUPSLAV}
+ { "GRUPSLAV", &handleGRUPSLAV},
+ { "RCMASTS", &handleRCMASTS},
};
}
diff --git a/tests/parser/ReservoirCouplingTests.cpp b/tests/parser/ReservoirCouplingTests.cpp
index ddf8c710bba..11f3878b795 100644
--- a/tests/parser/ReservoirCouplingTests.cpp
+++ b/tests/parser/ReservoirCouplingTests.cpp
@@ -41,7 +41,7 @@
using namespace Opm;
namespace {
-Schedule make_schedule(const std::string& schedule_string, bool slave_mode) {
+Schedule makeSchedule(const std::string& schedule_string, bool slave_mode) {
Parser parser;
auto python = std::make_shared();
Deck deck = parser.parseString(schedule_string);
@@ -61,11 +61,11 @@ void addStringLogger(std::ostringstream& stream_buffer) {
}
void assertRaisesInputErrorException(const std::string& schedule_string, bool slave_mode, const std::string& exception_string) {
- BOOST_CHECK_THROW(make_schedule(schedule_string, slave_mode), Opm::OpmInputError);
+ BOOST_CHECK_THROW(makeSchedule(schedule_string, slave_mode), Opm::OpmInputError);
try {
// Now that we know that it will throw the specific exception Opm::OpmInputError,
// we can check that the exception message is correct
- make_schedule(schedule_string, slave_mode);
+ makeSchedule(schedule_string, slave_mode);
}
catch (const Opm::OpmInputError& e) {
BOOST_CHECK_EQUAL(std::string(e.what()), exception_string);
@@ -96,51 +96,85 @@ void checkLastLineStringBuffer(
}
}
+std::string getMinimumMasterTimeStepDeckString(const std::string &end_of_deck_string)
+{
+ std::string prefix = R"(
+SCHEDULE
+
+GRUPTREE
+ 'PLAT-A' 'FIELD' /
+
+ 'MOD1' 'PLAT-A' /
+
+ 'B1_M' 'MOD1' /
+ 'D1_M' 'MOD1' /
+ 'C1_M' 'MOD1' /
+
+ 'E1_M' 'PLAT-A' /
+/
+
+SLAVES
+ 'RES-1' 'RC-01_MOD1_PRED' 1* '../mod1' 4 /
+ 'RES-2' 'RC-01_MOD2_PRED' 1* '../mod2' 1 /
+/
+
+GRUPMAST
+ 'D1_M' 'RES-1' 'MANI-D' 1* /
+ 'B1_M' 'RES-1' 'MANI-B' 1* /
+ 'C1_M' 'RES-1' 'MANI-C' 1* /
+ 'E1_M' 'RES-2' 'E1' 1* /
+/
+)";
+ return prefix + end_of_deck_string;
+}
+
void removeStringLogger() {
OpmLog::removeBackend("MYLOGGER");
}
} // namespace
-// -------------------------------
-// Testing SLAVES keyword
-// -------------------------------
+// ----------------------------------------------
+// Testing SLAVES keyword (sorted alphabetically)
+// ----------------------------------------------
+BOOST_AUTO_TEST_SUITE(SlaveTests)
-BOOST_AUTO_TEST_CASE(SLAVES_OK) {
+BOOST_AUTO_TEST_CASE(FAIL_NEGATIVE_NUMPROCS) {
std::string deck_string = R"(
-
SCHEDULE
SLAVES
- 'RES-1' 'RC-01_MOD1_PRED' 1* '../mod1' 4 /
+ 'RES-1' 'RC-01_MOD1_PRED' 1* '../mod1' -4 /
'RES-2' 'RC-01_MOD2_PRED' 1* '../mod2' 1 /
/
)";
- const auto& schedule = make_schedule(deck_string, /*slave_mode=*/false);
- const auto& rescoup = schedule[0].rescoup();
- BOOST_CHECK(rescoup.hasSlave("RES-1"));
- auto slave = rescoup.slave("RES-1");
- BOOST_CHECK_EQUAL(slave.name(), "RES-1");
- BOOST_CHECK_EQUAL(slave.dataFilename(), "RC-01_MOD1_PRED");
- BOOST_CHECK_EQUAL(slave.directoryPath(), "../mod1");
- BOOST_CHECK_EQUAL(slave.numprocs(), 4);
+ assertRaisesInputErrorException(deck_string, /*slave_mode=*/false, /*exception_string=*/ "Problem with keyword SLAVES\nIn line 3\nNumber of processors must be positive. Got: -4.");
}
-BOOST_AUTO_TEST_CASE(SLAVES_FAIL_NEGATIVE_NUMPROCS) {
+BOOST_AUTO_TEST_CASE(SYNTAX_OK) {
std::string deck_string = R"(
+
SCHEDULE
SLAVES
- 'RES-1' 'RC-01_MOD1_PRED' 1* '../mod1' -4 /
+ 'RES-1' 'RC-01_MOD1_PRED' 1* '../mod1' 4 /
'RES-2' 'RC-01_MOD2_PRED' 1* '../mod2' 1 /
/
)";
- assertRaisesInputErrorException(deck_string, /*slave_mode=*/false, /*exception_string=*/ "Problem with keyword SLAVES\nIn line 3\nNumber of processors must be positive. Got: -4.");
+ const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/false);
+ const auto& rescoup = schedule[0].rescoup();
+ BOOST_CHECK(rescoup.hasSlave("RES-1"));
+ auto slave = rescoup.slave("RES-1");
+ BOOST_CHECK_EQUAL(slave.name(), "RES-1");
+ BOOST_CHECK_EQUAL(slave.dataFilename(), "RC-01_MOD1_PRED");
+ BOOST_CHECK_EQUAL(slave.directoryPath(), "../mod1");
+ BOOST_CHECK_EQUAL(slave.numprocs(), 4);
}
-BOOST_AUTO_TEST_CASE(SLAVES_WARN_DUPLICATE_NAME) {
+
+BOOST_AUTO_TEST_CASE(WARN_DUPLICATE_NAME) {
std::string deck_string = R"(
SCHEDULE
SLAVES
@@ -151,7 +185,7 @@ SLAVES
)";
std::ostringstream stream_buffer;
addStringLogger(stream_buffer);
- const auto& schedule = make_schedule(deck_string, /*slave_mode=*/false);
+ const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/false);
checkLastLineStringBuffer(
stream_buffer,
"Slave reservoir 'RES-1' already defined. Redefining",
@@ -159,32 +193,23 @@ SLAVES
);
removeStringLogger();
}
+BOOST_AUTO_TEST_SUITE_END()
-// -------------------------------
-// Testing GRUPMAST keyword
-// -------------------------------
+// ------------------------------------------------
+// Testing GRUPMAST keyword (sorted alphabetically)
+// ------------------------------------------------
-BOOST_AUTO_TEST_CASE(GRUPMAST_OK) {
- std::string deck_string = R"(
+BOOST_AUTO_TEST_SUITE(GrupMastTests)
+BOOST_AUTO_TEST_CASE(FAIL_MISSING_MASTER_GROUP) {
+ std::string deck_string = R"(
SCHEDULE
+
SLAVES
'RES-1' 'RC-01_MOD1_PRED' 1* '../mod1' 4 /
'RES-2' 'RC-01_MOD2_PRED' 1* '../mod2' 1 /
/
-GRUPTREE
- 'PLAT-A' 'FIELD' /
-
- 'MOD1' 'PLAT-A' /
-
- 'B1_M' 'MOD1' /
- 'D1_M' 'MOD1' /
- 'C1_M' 'MOD1' /
-
- 'E1_M' 'PLAT-A' /
-/
-
GRUPMAST
'D1_M' 'RES-1' 'MANI-D' 1* /
'B1_M' 'RES-1' 'MANI-B' 1* /
@@ -193,23 +218,24 @@ GRUPMAST
/
)";
- const auto& schedule = make_schedule(deck_string, /*slave_mode=*/false);
- const auto& rescoup = schedule[0].rescoup();
- BOOST_CHECK(rescoup.hasMasterGroup("D1_M"));
- auto master_group = rescoup.masterGroup("D1_M");
- BOOST_CHECK_EQUAL(master_group.name(), "D1_M");
- BOOST_CHECK_EQUAL(master_group.slaveName(), "RES-1");
- BOOST_CHECK_EQUAL(master_group.slaveGroupName(), "MANI-D");
- BOOST_CHECK_EQUAL(master_group.flowLimitFraction(), 1e+20);
+ assertRaisesInputErrorException(deck_string, /*slave_mode=*/false, /*exception_string=*/"Problem with keyword GRUPMAST\nIn line 9\nGroup 'D1_M': Not defined. Master groups should be defined in advance by using GRUPTREE before referenced in GRUPMAST.");
}
-BOOST_AUTO_TEST_CASE(GRUPMAST_FAIL_MISSING_MASTER_GROUP) {
+BOOST_AUTO_TEST_CASE(FAIL_MISSING_SLAVE) {
std::string deck_string = R"(
+
SCHEDULE
-SLAVES
- 'RES-1' 'RC-01_MOD1_PRED' 1* '../mod1' 4 /
- 'RES-2' 'RC-01_MOD2_PRED' 1* '../mod2' 1 /
+GRUPTREE
+ 'PLAT-A' 'FIELD' /
+
+ 'MOD1' 'PLAT-A' /
+
+ 'B1_M' 'MOD1' /
+ 'D1_M' 'MOD1' /
+ 'C1_M' 'MOD1' /
+
+ 'E1_M' 'PLAT-A' /
/
GRUPMAST
@@ -220,10 +246,10 @@ GRUPMAST
/
)";
- assertRaisesInputErrorException(deck_string, /*slave_mode=*/false, /*exception_string=*/"Problem with keyword GRUPMAST\nIn line 9\nGroup 'D1_M': Not defined. Master groups should be defined in advance by using GRUPTREE before referenced in GRUPMAST.");
+ assertRaisesInputErrorException(deck_string, /*slave_mode=*/false, /*exception_string=*/"Problem with keyword GRUPMAST\nIn line 17\nSlave reservoir 'RES-1': Not defined. Slave reservoirs should be defined in advance by using SLAVES before referenced in GRUPMAST.");
}
-BOOST_AUTO_TEST_CASE(GRUPMAST_FAIL_SUBORDINATE_GROUPS) {
+BOOST_AUTO_TEST_CASE(FAIL_SUBORDINATE_GROUPS) {
std::string deck_string = R"(
SCHEDULE
@@ -255,7 +281,7 @@ GRUPMAST
assertRaisesInputErrorException(deck_string, /*slave_mode=*/false, /*exception_string=*/"Problem with keyword GRUPMAST\nIn line 21\nGroup 'FIELD' has subgroups: A master group cannot contain any wells or subordinate groups.");
}
-BOOST_AUTO_TEST_CASE(GRUPMAST_FAIL_SUBORDINATE_WELLS) {
+BOOST_AUTO_TEST_CASE(FAIL_SUBORDINATE_WELLS) {
std::string deck_string = R"(
SCHEDULE
@@ -292,10 +318,14 @@ GRUPMAST
assertRaisesInputErrorException(deck_string, /*slave_mode=*/false, /*exception_string=*/"Problem with keyword GRUPMAST\nIn line 26\nGroup 'D1_M' has wells: A master group cannot contain any wells or subordinate groups.");
}
-BOOST_AUTO_TEST_CASE(GRUPMAST_FAIL_MISSING_SLAVE) {
- std::string deck_string = R"(
+BOOST_AUTO_TEST_CASE(SYNTAX_OK) {
+ std::string deck_string = R"(
SCHEDULE
+SLAVES
+ 'RES-1' 'RC-01_MOD1_PRED' 1* '../mod1' 4 /
+ 'RES-2' 'RC-01_MOD2_PRED' 1* '../mod2' 1 /
+/
GRUPTREE
'PLAT-A' 'FIELD' /
@@ -317,13 +347,25 @@ GRUPMAST
/
)";
- assertRaisesInputErrorException(deck_string, /*slave_mode=*/false, /*exception_string=*/"Problem with keyword GRUPMAST\nIn line 17\nSlave reservoir 'RES-1': Not defined. Slave reservoirs should be defined in advance by using SLAVES before referenced in GRUPMAST.");
+ const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/false);
+ const auto& rescoup = schedule[0].rescoup();
+ BOOST_CHECK(rescoup.hasMasterGroup("D1_M"));
+ auto master_group = rescoup.masterGroup("D1_M");
+ BOOST_CHECK_EQUAL(master_group.name(), "D1_M");
+ BOOST_CHECK_EQUAL(master_group.slaveName(), "RES-1");
+ BOOST_CHECK_EQUAL(master_group.slaveGroupName(), "MANI-D");
+ BOOST_CHECK_EQUAL(master_group.flowLimitFraction(), 1e+20);
}
-// -------------------------------
-// Testing GRUPSLAV keyword
-// -------------------------------
-BOOST_AUTO_TEST_CASE(GRUPSLAV_OK) {
+BOOST_AUTO_TEST_SUITE_END()
+
+// ------------------------------------------------
+// Testing GRUPSLAV keyword (sorted alphabetically)
+// ------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE(GrupSlavTests)
+
+BOOST_AUTO_TEST_CASE(DEFAULT_APPLIED) {
std::string deck_string = R"(
SCHEDULE
@@ -335,28 +377,21 @@ GRUPTREE
/
GRUPSLAV
- 'MANI-D' 'D1_M' /
+ 'MANI-D' 1* /
'MANI-B' 'B1_M' /
'MANI-C' 'C1_M' /
/
)";
- const auto& schedule = make_schedule(deck_string, /*slave_mode=*/true);
+ const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/true);
const auto& rescoup = schedule[0].rescoup();
BOOST_CHECK(rescoup.hasGrupSlav("MANI-D"));
auto grup_slav = rescoup.grupSlav("MANI-D");
BOOST_CHECK_EQUAL(grup_slav.name(), "MANI-D");
- BOOST_CHECK_EQUAL(grup_slav.masterGroupName(), "D1_M");
- BOOST_CHECK_EQUAL(grup_slav.oilProdFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
- BOOST_CHECK_EQUAL(grup_slav.liquidProdFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
- BOOST_CHECK_EQUAL(grup_slav.gasProdFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
- BOOST_CHECK_EQUAL(grup_slav.fluidVolumeProdFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
- BOOST_CHECK_EQUAL(grup_slav.oilInjFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
- BOOST_CHECK_EQUAL(grup_slav.waterInjFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
- BOOST_CHECK_EQUAL(grup_slav.gasInjFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
+ BOOST_CHECK_EQUAL(grup_slav.masterGroupName(), "MANI-D");
}
-BOOST_AUTO_TEST_CASE(GRUPSLAV_FAIL_MISSING_GROUP) {
+BOOST_AUTO_TEST_CASE(FAIL_MISSING_GROUP) {
std::string deck_string = R"(
SCHEDULE
@@ -370,7 +405,7 @@ GRUPSLAV
assertRaisesInputErrorException(deck_string, /*slave_mode=*/true, /*exception_string=*/"Problem with keyword GRUPSLAV\nIn line 4\nGroup 'MANI-D': Not defined. Slave groups should be defined in advance by using GRUPTREE or WELSPECS before referenced in GRUPSLAV.");
}
-BOOST_AUTO_TEST_CASE(GRUPSLAV_DEFAULT_APPLIED) {
+BOOST_AUTO_TEST_CASE(SYNTAX_OK) {
std::string deck_string = R"(
SCHEDULE
@@ -382,16 +417,106 @@ GRUPTREE
/
GRUPSLAV
- 'MANI-D' 1* /
+ 'MANI-D' 'D1_M' /
'MANI-B' 'B1_M' /
'MANI-C' 'C1_M' /
/
)";
- const auto& schedule = make_schedule(deck_string, /*slave_mode=*/true);
+ const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/true);
const auto& rescoup = schedule[0].rescoup();
BOOST_CHECK(rescoup.hasGrupSlav("MANI-D"));
auto grup_slav = rescoup.grupSlav("MANI-D");
BOOST_CHECK_EQUAL(grup_slav.name(), "MANI-D");
- BOOST_CHECK_EQUAL(grup_slav.masterGroupName(), "MANI-D");
+ BOOST_CHECK_EQUAL(grup_slav.masterGroupName(), "D1_M");
+ BOOST_CHECK_EQUAL(grup_slav.oilProdFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
+ BOOST_CHECK_EQUAL(grup_slav.liquidProdFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
+ BOOST_CHECK_EQUAL(grup_slav.gasProdFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
+ BOOST_CHECK_EQUAL(grup_slav.fluidVolumeProdFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
+ BOOST_CHECK_EQUAL(grup_slav.oilInjFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
+ BOOST_CHECK_EQUAL(grup_slav.waterInjFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
+ BOOST_CHECK_EQUAL(grup_slav.gasInjFlag(), Opm::ReservoirCoupling::GrupSlav::FilterFlag::MAST);
}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+// ------------------------------------------------
+// Testing RCMASTS keyword (sorted alphabetically)
+// ------------------------------------------------
+
+BOOST_AUTO_TEST_SUITE(MinimumMasterTimeStep)
+
+BOOST_AUTO_TEST_CASE(DEFAULT_APPLIED1) {
+ std::string end_of_deck_string = R"(
+TUNING
+-- TSINIT TSMAXZ TSMINZ
+ * * 0.1 /
+/
+/
+)";
+ std::string deck_string = getMinimumMasterTimeStepDeckString(end_of_deck_string);
+ const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/false);
+ const auto& rescoup = schedule[0].rescoup();
+ BOOST_CHECK(rescoup.masterMinTimeStep() == 0.0); // Default value when RCMASTS is not given
+
+}
+
+BOOST_AUTO_TEST_CASE(DEFAULT_APPLIED2) {
+ std::string end_of_deck_string = R"(
+TUNING
+-- TSINIT TSMAXZ TSMINZ
+ * * 0.1 /
+/
+/
+
+RCMASTS
+ * /
+)";
+ std::string deck_string = getMinimumMasterTimeStepDeckString(end_of_deck_string);
+ const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/false);
+ const auto& rescoup = schedule[0].rescoup();
+ const auto& tuning = schedule[0].tuning();
+ // Default value when RCMASTS is given but no value is provided
+ BOOST_CHECK(rescoup.masterMinTimeStep() == tuning.TSMINZ);
+
+}
+
+BOOST_AUTO_TEST_CASE(VALUE_PROVIDED) {
+ std::string end_of_deck_string = R"(
+TUNING
+-- TSINIT TSMAXZ TSMINZ
+ * * 0.1 /
+/
+/
+
+RCMASTS
+ 0.01 /
+)";
+ std::string deck_string = getMinimumMasterTimeStepDeckString(end_of_deck_string);
+ const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/false);
+ const auto& rescoup = schedule[0].rescoup();
+ BOOST_CHECK(rescoup.masterMinTimeStep() == 0.01);
+
+}
+
+BOOST_AUTO_TEST_CASE(NEGATIVE_VALUE_PROVIDED) {
+ std::string end_of_deck_string = R"(
+TUNING
+-- TSINIT TSMAXZ TSMINZ
+ * * 0.1 /
+/
+/
+
+RCMASTS
+ -0.1 /
+)";
+ std::string deck_string = getMinimumMasterTimeStepDeckString(end_of_deck_string);
+ assertRaisesInputErrorException(
+ deck_string,
+ /*slave_mode=*/false,
+ /*exception_string=*/"Problem with keyword RCMASTS\nIn line 34\nNegative value for RCMASTS is not allowed."
+ );
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()