diff --git a/opm/common/utility/OpmInputError.hpp b/opm/common/utility/OpmInputError.hpp index 760437e82..0e41d900b 100644 --- a/opm/common/utility/OpmInputError.hpp +++ b/opm/common/utility/OpmInputError.hpp @@ -19,9 +19,9 @@ #ifndef OPM_ERROR_HPP #define OPM_ERROR_HPP -#include #include #include +#include #include @@ -67,8 +67,8 @@ public: */ OpmInputError(const std::string& msg_fmt, const KeywordLocation& loc) : - m_what { OpmInputError::format(msg_fmt, loc) }, - location { loc } + m_what { OpmInputError::format(msg_fmt, loc) }, + locations { loc } {} /* @@ -87,12 +87,13 @@ public: } */ OpmInputError(const KeywordLocation& loc, const std::exception& e) : - m_what { OpmInputError::formatException(loc, e) }, - location { loc } + m_what { OpmInputError::formatException(loc, e) }, + locations { loc } {} - OpmInputError(const std::string& msg) : - m_what(msg) + OpmInputError(const std::vector& locations, const std::string& reason) + : m_what { OpmInputError::formatMultiple(reason, locations) } + , locations { locations } {} const char * what() const throw() @@ -103,6 +104,7 @@ public: static std::string format(const std::string& msg_format, const KeywordLocation& loc); static std::string formatException(const KeywordLocation& loc, const std::exception& e); + static std::string formatMultiple(const std::string& reason, const std::vector&); private: std::string m_what; @@ -110,7 +112,7 @@ private: // The location member is here for debugging; depending on the msg_fmt // passed in the constructor we might not have captured all the information // in the location argument passed to the constructor. - std::optional location; + std::vector locations; }; } diff --git a/src/opm/common/utility/OpmInputError.cpp b/src/opm/common/utility/OpmInputError.cpp index dd2340c24..8c6182330 100644 --- a/src/opm/common/utility/OpmInputError.cpp +++ b/src/opm/common/utility/OpmInputError.cpp @@ -16,6 +16,9 @@ You should have received a copy of the GNU General Public License along with OPM. If not, see . */ + +#include +#include #include #include @@ -46,4 +49,20 @@ std::string OpmInputError::format(const std::string& msg_format, const KeywordLo ); } +namespace { + + std::string formatSingle(const KeywordLocation& loc) { + return OpmInputError::format("\n {keyword} in {file}, line {line}", loc); + } +} + +std::string OpmInputError::formatMultiple(const std::string& reason, const std::vector& locations) { + std::vector locationStrings; + std::transform(locations.begin(), locations.end(), std::back_inserter(locationStrings), &formatSingle); + const std::string messages { std::accumulate(locationStrings.begin(), locationStrings.end(), std::string {}) } ; + + return fmt::format(R"(Problem parsing keywords {} +Parse error: {})", messages, reason); +} + } diff --git a/src/opm/parser/eclipse/EclipseState/Tables/TableManager.cpp b/src/opm/parser/eclipse/EclipseState/Tables/TableManager.cpp index 0a5d1df8e..07631f08d 100644 --- a/src/opm/parser/eclipse/EclipseState/Tables/TableManager.cpp +++ b/src/opm/parser/eclipse/EclipseState/Tables/TableManager.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -571,12 +572,20 @@ namespace Opm { // the TEMPVD (E300) and RTEMPVD (E300 + E100) keywords are // synonymous, but we want to provide only a single cannonical // API here, so we jump through some small hoops... - if (deck.hasKeyword("TEMPVD") && deck.hasKeyword("RTEMPVD")) - throw std::invalid_argument("The TEMPVD and RTEMPVD tables are mutually exclusive!"); - else if (deck.hasKeyword("TEMPVD")) - initSimpleTableContainer(deck, "TEMPVD", "RTEMPVD", m_eqldims.getNumEquilRegions()); - else if (deck.hasKeyword("RTEMPVD")) - initSimpleTableContainer(deck, "RTEMPVD", "RTEMPVD" , m_eqldims.getNumEquilRegions()); + const bool + hasTEMPVD { deck.hasKeyword() } , + hasRTEMPVD { deck.hasKeyword() } ; + + if (hasTEMPVD && hasRTEMPVD) { + throw OpmInputError({ + deck.getKeyword().location(), + deck.getKeyword().location(), + }, "The TEMPVD and RTEMPVD tables are mutually exclusive."); + } else if (hasTEMPVD) { + initSimpleTableContainer(deck, "TEMPVD", "RTEMPVD", m_eqldims.getNumEquilRegions()); + } else if (hasRTEMPVD) { + initSimpleTableContainer(deck, "RTEMPVD", "RTEMPVD", m_eqldims.getNumEquilRegions()); + } }