diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 1eac974ab9d..00ab7823798 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -287,7 +287,8 @@ if(ENABLE_ECL_INPUT) 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/ResCoup/CouplingFile.cpp + opm/input/eclipse/Schedule/ResCoup/ReadCouplingFile.cpp + opm/input/eclipse/Schedule/ResCoup/WriteCouplingFile.cpp opm/input/eclipse/Schedule/UDQ/UDQKeywordHandlers.cpp opm/input/eclipse/Schedule/UDQ/UDQActive.cpp opm/input/eclipse/Schedule/UDQ/UDQAssign.cpp @@ -1320,7 +1321,8 @@ if(ENABLE_ECL_INPUT) 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/ResCoup/CouplingFile.hpp + opm/input/eclipse/Schedule/ResCoup/ReadCouplingFile.hpp + opm/input/eclipse/Schedule/ResCoup/WriteCouplingFile.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/GrupSlav.hpp b/opm/input/eclipse/Schedule/ResCoup/GrupSlav.hpp index 9300a9f494e..d816d7f0b64 100644 --- a/opm/input/eclipse/Schedule/ResCoup/GrupSlav.hpp +++ b/opm/input/eclipse/Schedule/ResCoup/GrupSlav.hpp @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with OPM. If not, see . */ -#ifndef RESERVOIR_COUPLING_GRUPSLAV_HPP -#define RESERVOIR_COUPLING_GRUPSLAV_HPP +#ifndef OPM_RESERVOIR_COUPLING_GRUPSLAV_HPP +#define OPM_RESERVOIR_COUPLING_GRUPSLAV_HPP #include #include @@ -155,4 +155,4 @@ extern void handleGRUPSLAV(HandlerContext& handlerContext); } // namespace Opm -#endif // RESERVOIR_COUPLING_GRUPSLAV_HPP +#endif // OPM_RESERVOIR_COUPLING_GRUPSLAV_HPP diff --git a/opm/input/eclipse/Schedule/ResCoup/MasterGroup.hpp b/opm/input/eclipse/Schedule/ResCoup/MasterGroup.hpp index d97fc9c5865..8fbc58404d0 100644 --- a/opm/input/eclipse/Schedule/ResCoup/MasterGroup.hpp +++ b/opm/input/eclipse/Schedule/ResCoup/MasterGroup.hpp @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with OPM. If not, see . */ -#ifndef RESERVOIR_COUPLING_MASTER_GROUP_HPP -#define RESERVOIR_COUPLING_MASTER_GROUP_HPP +#ifndef OPM_RESERVOIR_COUPLING_MASTER_GROUP_HPP +#define OPM_RESERVOIR_COUPLING_MASTER_GROUP_HPP #include #include @@ -95,4 +95,4 @@ extern void handleGRUPMAST(HandlerContext& handlerContext); } // namespace Opm -#endif // RESERVOIR_COUPLING_MASTER_GROUP_HPP +#endif // OPM_RESERVOIR_COUPLING_MASTER_GROUP_HPP diff --git a/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.hpp b/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.hpp index a963a9fbc45..54ba315f2e2 100644 --- a/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.hpp +++ b/opm/input/eclipse/Schedule/ResCoup/MasterMinimumTimeStep.hpp @@ -16,8 +16,8 @@ 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 +#ifndef OPM_RESERVOIR_COUPLING_MASTER_MINIMUM_TIMESTEP_HPP +#define OPM_RESERVOIR_COUPLING_MASTER_MINIMUM_TIMESTEP_HPP namespace Opm { class HandlerContext; @@ -25,4 +25,4 @@ class HandlerContext; extern void handleRCMASTS(HandlerContext& handlerContext); } // namespace Opm -#endif // RESERVOIR_COUPLING_MASTER_MINIMUM_TIMESTEP_HPP +#endif // OPM_RESERVOIR_COUPLING_MASTER_MINIMUM_TIMESTEP_HPP diff --git a/opm/input/eclipse/Schedule/ResCoup/ReadCouplingFile.cpp b/opm/input/eclipse/Schedule/ResCoup/ReadCouplingFile.cpp new file mode 100644 index 00000000000..0bd505cbaf0 --- /dev/null +++ b/opm/input/eclipse/Schedule/ResCoup/ReadCouplingFile.cpp @@ -0,0 +1,62 @@ +/* + 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 handleUSECUPL(HandlerContext& handlerContext) +{ + auto& schedule_state = handlerContext.state(); + auto rescoup = schedule_state.rescoup(); + const auto& keyword = handlerContext.keyword; + // Opm::Parser::parseFile() (see readDeck.cpp in opm-simulators) will throw an exception if there + // is more than one record for this keyword, so we can assume that there is exactly one record here. + auto record = keyword[0]; + { + auto deck_item = record.getItem(); + if (deck_item.defaultApplied(0)) { + throw OpmInputError("Root name of coupling file (item 1) cannot be defaulted.", keyword.location()); + } + auto root_name = deck_item.getTrimmedString(0); + rescoup.setReadCouplingFileName(root_name); + } + { + auto deck_item = record.getItem(); + if (deck_item.defaultApplied(0)) { + throw OpmInputError("Format of coupling file (item 2) cannot be defaulted.", keyword.location()); + } + auto flag_str = deck_item.getTrimmedString(0); + auto coupling_file_flag = ReservoirCoupling::CouplingInfo::couplingFileFlagFromString( + flag_str, keyword); + rescoup.setReadCouplingFileFlag(coupling_file_flag); + } + schedule_state.rescoup.update( std::move( rescoup )); +} + +} // namespace Opm + diff --git a/opm/input/eclipse/Schedule/ResCoup/ReadCouplingFile.hpp b/opm/input/eclipse/Schedule/ResCoup/ReadCouplingFile.hpp new file mode 100644 index 00000000000..bee4aad14df --- /dev/null +++ b/opm/input/eclipse/Schedule/ResCoup/ReadCouplingFile.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 OPM_READ_RESERVOIR_COUPLING_FILE_HPP +#define OPM_READ_RESERVOIR_COUPLING_FILE_HPP +namespace Opm { + +class HandlerContext; + +extern void handleUSECUPL(HandlerContext& handlerContext); + +} // namespace Opm +#endif // OPM_READ_RESERVOIR_COUPLING_FILE_HPP diff --git a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.cpp b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.cpp index 20fb89a0cc6..5a8bf146335 100644 --- a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.cpp +++ b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.cpp @@ -19,17 +19,33 @@ #include #include +#include #include namespace Opm { namespace ReservoirCoupling { +CouplingInfo::CouplingFileFlag CouplingInfo::couplingFileFlagFromString( + const std::string& flag_str, const DeckKeyword& keyword +) +{ + if (flag_str == "F") { + return CouplingInfo::CouplingFileFlag::FORMATTED; + } else if (flag_str == "U") { + return CouplingInfo::CouplingFileFlag::UNFORMATTED; + } else { + throw Opm::OpmInputError("Invalid DUMPCUPL value: " + flag_str, keyword.location()); + } +} + 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_min_time_step == rhs.m_master_min_time_step && - this->m_coupling_file_flag == rhs.m_coupling_file_flag; + this->m_write_coupling_file_flag == rhs.m_write_coupling_file_flag && + this->m_read_coupling_file_name == rhs.m_read_coupling_file_name && + this->m_read_coupling_file_flag == rhs.m_read_coupling_file_flag; } CouplingInfo CouplingInfo::serializationTestObject() diff --git a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.hpp b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.hpp index 38f85081c71..67fe251a387 100644 --- a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.hpp +++ b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingInfo.hpp @@ -16,9 +16,10 @@ You should have received a copy of the GNU General Public License along with OPM. If not, see . */ -#ifndef RESERVOIR_COUPLING_INFO_HPP -#define RESERVOIR_COUPLING_INFO_HPP +#ifndef OPM_RESERVOIR_COUPLING_INFO_HPP +#define OPM_RESERVOIR_COUPLING_INFO_HPP +#include #include #include #include @@ -43,12 +44,6 @@ class CouplingInfo { static CouplingInfo serializationTestObject(); bool operator==(const CouplingInfo& other) const; - void setCouplingFileFlag(CouplingFileFlag flag) { - m_coupling_file_flag = flag; - } - CouplingFileFlag couplingFileFlag() const { - return m_coupling_file_flag; - } const GrupSlav& grupSlav(const std::string& name) const { return m_grup_slavs.at(name); @@ -91,10 +86,31 @@ class CouplingInfo { double masterMinTimeStep() const { return m_master_min_time_step; } + + CouplingFileFlag readCouplingFileFlag() const { + return m_read_coupling_file_flag; + } + + const std::string& readCouplingFileName() const { + return m_read_coupling_file_name; + } + void setMasterMinTimeStep(double tstep) { m_master_min_time_step = tstep; } + void setReadCouplingFileFlag(CouplingFileFlag flag) { + m_read_coupling_file_flag = flag; + } + + void setReadCouplingFileName(const std::string file_name) { + m_read_coupling_file_name = file_name; + } + + void setWriteCouplingFileFlag(CouplingFileFlag flag) { + m_write_coupling_file_flag = flag; + } + const std::map& slaves() const { return this->m_slaves; } @@ -109,6 +125,7 @@ class CouplingInfo { } + template void serializeOp(Serializer& serializer) { @@ -116,17 +133,31 @@ class CouplingInfo { serializer(m_master_groups); serializer(m_grup_slavs); serializer(m_master_min_time_step); - serializer(m_coupling_file_flag); + serializer(m_write_coupling_file_flag); + serializer(m_read_coupling_file_flag); + serializer(m_read_coupling_file_name); } + CouplingFileFlag writeCouplingFileFlag() const { + return m_write_coupling_file_flag; + } + + + // Non-inline methods (defined in CouplingInfo.cpp) + + static CouplingFileFlag couplingFileFlagFromString( + const std::string& flag_str, const DeckKeyword& keyword); + private: std::map m_slaves; std::map m_master_groups; std::map m_grup_slavs; double m_master_min_time_step{0.0}; - CouplingFileFlag m_coupling_file_flag{CouplingFileFlag::NONE}; + CouplingFileFlag m_write_coupling_file_flag{CouplingFileFlag::NONE}; + CouplingFileFlag m_read_coupling_file_flag{CouplingFileFlag::NONE}; + std::string m_read_coupling_file_name{}; }; } // namespace Opm::ReservoirCoupling -#endif +#endif // OPM_RESERVOIR_COUPLING_INFO_HPP diff --git a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.cpp b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.cpp index cc0df2a00c6..1374044d61b 100644 --- a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.cpp +++ b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.cpp @@ -24,7 +24,8 @@ #include "Slaves.hpp" #include "MasterGroup.hpp" #include "MasterMinimumTimeStep.hpp" -#include "CouplingFile.hpp" +#include "WriteCouplingFile.hpp" +#include "ReadCouplingFile.hpp" #include @@ -39,6 +40,7 @@ getReservoirCouplingHandlers() { "GRUPSLAV", &handleGRUPSLAV}, { "RCMASTS", &handleRCMASTS}, { "DUMPCUPL", &handleDUMPCUPL}, + { "USECUPL", &handleUSECUPL}, }; } diff --git a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.hpp b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.hpp index d32b38139ba..9a19ae9cae4 100644 --- a/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.hpp +++ b/opm/input/eclipse/Schedule/ResCoup/ReservoirCouplingKeywordHandlers.hpp @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with OPM. If not, see . */ -#ifndef RESERVOIR_COUPLING_KEYWORD_HANDLERS_HPP -#define RESERVOIR_COUPLING_KEYWORD_HANDLERS_HPP +#ifndef OPM_RESERVOIR_COUPLING_KEYWORD_HANDLERS_HPP +#define OPM_RESERVOIR_COUPLING_KEYWORD_HANDLERS_HPP #include "../KeywordHandlers.hpp" @@ -32,4 +32,4 @@ std::vector> getReservo } -#endif +#endif // OPM_RESERVOIR_COUPLING_KEYWORD_HANDLERS_HPP diff --git a/opm/input/eclipse/Schedule/ResCoup/Slaves.hpp b/opm/input/eclipse/Schedule/ResCoup/Slaves.hpp index 1722301f268..e092361994d 100644 --- a/opm/input/eclipse/Schedule/ResCoup/Slaves.hpp +++ b/opm/input/eclipse/Schedule/ResCoup/Slaves.hpp @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with OPM. If not, see . */ -#ifndef RESERVOIR_COUPLING_SLAVES_HPP -#define RESERVOIR_COUPLING_SLAVES_HPP +#ifndef OPM_RESERVOIR_COUPLING_SLAVES_HPP +#define OPM_RESERVOIR_COUPLING_SLAVES_HPP #include #include @@ -91,4 +91,4 @@ class Slave { extern void handleSLAVES(HandlerContext& handlerContext); } // namespace Opm -#endif // RESERVOIR_COUPLING_SLAVES_HPP +#endif // OPM_RESERVOIR_COUPLING_SLAVES_HPP diff --git a/opm/input/eclipse/Schedule/ResCoup/CouplingFile.cpp b/opm/input/eclipse/Schedule/ResCoup/WriteCouplingFile.cpp similarity index 73% rename from opm/input/eclipse/Schedule/ResCoup/CouplingFile.cpp rename to opm/input/eclipse/Schedule/ResCoup/WriteCouplingFile.cpp index 5cb7df6919c..d7c0de40ff7 100644 --- a/opm/input/eclipse/Schedule/ResCoup/CouplingFile.cpp +++ b/opm/input/eclipse/Schedule/ResCoup/WriteCouplingFile.cpp @@ -18,7 +18,7 @@ */ -#include +#include #include #include #include @@ -29,19 +29,6 @@ namespace Opm { -ReservoirCoupling::CouplingInfo::CouplingFileFlag couplingFileFlagFromString( - const std::string& flag_str, const DeckKeyword& keyword -) -{ - if (flag_str == "F") { - return ReservoirCoupling::CouplingInfo::CouplingFileFlag::FORMATTED; - } else if (flag_str == "U") { - return ReservoirCoupling::CouplingInfo::CouplingFileFlag::UNFORMATTED; - } else { - throw OpmInputError("Invalid DUMPCUPL value: " + flag_str, keyword.location()); - } -} - void handleDUMPCUPL(HandlerContext& handlerContext) { auto& schedule_state = handlerContext.state(); @@ -55,8 +42,9 @@ void handleDUMPCUPL(HandlerContext& handlerContext) throw OpmInputError("DUMPCUPL keyword cannot be defaulted.", keyword.location()); } auto flag_str = deck_item.getTrimmedString(0); - auto coupling_file_flag = couplingFileFlagFromString(flag_str, keyword); - rescoup.setCouplingFileFlag(coupling_file_flag); + auto coupling_file_flag = ReservoirCoupling::CouplingInfo::couplingFileFlagFromString( + flag_str, keyword); + rescoup.setWriteCouplingFileFlag(coupling_file_flag); schedule_state.rescoup.update( std::move( rescoup )); } diff --git a/opm/input/eclipse/Schedule/ResCoup/CouplingFile.hpp b/opm/input/eclipse/Schedule/ResCoup/WriteCouplingFile.hpp similarity index 87% rename from opm/input/eclipse/Schedule/ResCoup/CouplingFile.hpp rename to opm/input/eclipse/Schedule/ResCoup/WriteCouplingFile.hpp index 8cbbe6376f1..cdccfb6b79a 100644 --- a/opm/input/eclipse/Schedule/ResCoup/CouplingFile.hpp +++ b/opm/input/eclipse/Schedule/ResCoup/WriteCouplingFile.hpp @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with OPM. If not, see . */ -#ifndef RESERVOIR_COUPLING_FILE_HPP -#define RESERVOIR_COUPLING_FILE_HPP +#ifndef OPM_RESERVOIR_COUPLING_FILE_HPP +#define OPM_RESERVOIR_COUPLING_FILE_HPP namespace Opm { class HandlerContext; @@ -25,4 +25,4 @@ class HandlerContext; extern void handleDUMPCUPL(HandlerContext& handlerContext); } // namespace Opm -#endif // RESERVOIR_COUPLING_FILE_HPP +#endif // OPM_RESERVOIR_COUPLING_FILE_HPP diff --git a/opm/input/eclipse/share/keywords/000_Eclipse100/U/USECUPL b/opm/input/eclipse/share/keywords/000_Eclipse100/U/USECUPL index 0b018f59dbc..dff973129bb 100644 --- a/opm/input/eclipse/share/keywords/000_Eclipse100/U/USECUPL +++ b/opm/input/eclipse/share/keywords/000_Eclipse100/U/USECUPL @@ -3,6 +3,7 @@ "sections": [ "SCHEDULE" ], + "size": 1, "items": [ { "name": "BASE", diff --git a/tests/parser/ReservoirCouplingTests.cpp b/tests/parser/ReservoirCouplingTests.cpp index ffe7714abb6..f904604bb7d 100644 --- a/tests/parser/ReservoirCouplingTests.cpp +++ b/tests/parser/ReservoirCouplingTests.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -542,7 +543,7 @@ DUMPCUPL std::string deck_string = getCouplingFileDeckString(end_of_deck_string); const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/false); const auto& rescoup = schedule[0].rescoup(); - BOOST_CHECK(rescoup.couplingFileFlag() == + BOOST_CHECK(rescoup.writeCouplingFileFlag() == Opm::ReservoirCoupling::CouplingInfo::CouplingFileFlag::FORMATTED); } @@ -574,3 +575,34 @@ DUMPCUPL } BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(UseCouplingFile) + +BOOST_AUTO_TEST_CASE(FORMATTED_FILE) { + std::string end_of_deck_string = R"( +USECUPL + 'BASE' 'F' / +)"; + std::string deck_string = getCouplingFileDeckString(end_of_deck_string); + const auto& schedule = makeSchedule(deck_string, /*slave_mode=*/false); + const auto& rescoup = schedule[0].rescoup(); + BOOST_CHECK(rescoup.readCouplingFileFlag() == + Opm::ReservoirCoupling::CouplingInfo::CouplingFileFlag::FORMATTED); + BOOST_CHECK(rescoup.readCouplingFileName() == "BASE"); + +} + +BOOST_AUTO_TEST_CASE(DEFAULT_NOT_ALLOWED1) { + std::string end_of_deck_string = R"( +USECUPL + * 'U' / +)"; + std::string deck_string = getCouplingFileDeckString(end_of_deck_string); + assertRaisesInputErrorException( + deck_string, + /*slave_mode=*/false, + /*exception_string=*/"Problem with keyword USECUPL\nIn line 28\nRoot name of coupling file (item 1) cannot be defaulted." + ); +} + +BOOST_AUTO_TEST_SUITE_END()