Separate keyword validation for fully supported keywords

This commit is contained in:
Vegard Kippe 2025-01-13 13:31:09 +01:00
parent cbc12a915b
commit 495831c090
8 changed files with 202 additions and 45 deletions

View File

@ -148,6 +148,7 @@ list (APPEND MAIN_SOURCE_FILES
opm/simulators/utils/BlackoilPhases.cpp opm/simulators/utils/BlackoilPhases.cpp
opm/simulators/utils/ComponentName.cpp opm/simulators/utils/ComponentName.cpp
opm/simulators/utils/DeferredLogger.cpp opm/simulators/utils/DeferredLogger.cpp
opm/simulators/utils/FullySupportedFlowKeywords.cpp
opm/simulators/utils/ParallelFileMerger.cpp opm/simulators/utils/ParallelFileMerger.cpp
opm/simulators/utils/ParallelRestart.cpp opm/simulators/utils/ParallelRestart.cpp
opm/simulators/utils/PartiallySupportedFlowKeywords.cpp opm/simulators/utils/PartiallySupportedFlowKeywords.cpp

View File

@ -123,29 +123,32 @@ namespace Opm::KeywordValidation {
void KeywordValidator::validateDeckKeyword(const DeckKeyword& keyword, std::vector<ValidationError>& errors) const void KeywordValidator::validateDeckKeyword(const DeckKeyword& keyword, std::vector<ValidationError>& errors) const
{ {
const auto& it = m_keywords.find(keyword.name()); const auto& it = m_unsupported_keywords.find(keyword.name());
if (it != m_keywords.end()) { if (it != m_unsupported_keywords.end()) {
// If the keyword is not supported, add an error for that. // If the keyword is not supported, add an error for that.
const auto& properties = it->second; const auto& properties = it->second;
errors.push_back(ValidationError { errors.push_back(ValidationError {
properties.critical, keyword.location(), 1, std::nullopt, std::nullopt, properties.message}); properties.critical, keyword.location(), 1, std::nullopt, std::nullopt, properties.message});
} else { } else {
// Otherwise, check all its items. // Otherwise, check all its items.
validateKeywordItems(keyword, m_string_items, errors); validateKeywordItems(keyword, m_partially_supported_string_items, errors);
validateKeywordItems(keyword, m_int_items, errors); validateKeywordItems(keyword, m_partially_supported_int_items, errors);
validateKeywordItems(keyword, m_double_items, errors); validateKeywordItems(keyword, m_partially_supported_double_items, errors);
validateKeywordItems(keyword, m_fully_supported_string_items, errors);
validateKeywordItems(keyword, m_fully_supported_int_items, errors);
validateKeywordItems(keyword, m_fully_supported_double_items, errors);
} }
} }
template <typename T> template <typename T>
void KeywordValidator::validateKeywordItems(const DeckKeyword& keyword, void KeywordValidator::validateKeywordItems(const DeckKeyword& keyword,
const PartiallySupportedKeywords<T>& partially_supported_items, const SupportedKeywords<T>& partially_or_fully_supported_items,
std::vector<ValidationError>& errors) const std::vector<ValidationError>& errors) const
{ {
const auto& keyword_properties = partially_supported_items.find(keyword.name()); const auto& keyword_properties = partially_or_fully_supported_items.find(keyword.name());
if (keyword_properties != partially_supported_items.end()) { if (keyword_properties != partially_or_fully_supported_items.end()) {
// If this keyworcs has partially supported items, iterate over all of them. // If this keywords has partially or fully supported items to validate, iterate over all of them.
for (std::size_t record_index = 0; record_index < keyword.size(); record_index++) { for (std::size_t record_index = 0; record_index < keyword.size(); record_index++) {
const auto& record = keyword.getRecord(record_index); const auto& record = keyword.getRecord(record_index);
for (std::size_t item_index = 0; item_index < record.size(); item_index++) { for (std::size_t item_index = 0; item_index < record.size(); item_index++) {
@ -154,7 +157,7 @@ namespace Opm::KeywordValidation {
const auto& item_properties = keyword_properties->second.find(item_index + 1); const auto& item_properties = keyword_properties->second.find(item_index + 1);
if (item_properties != keyword_properties->second.end()) { if (item_properties != keyword_properties->second.end()) {
if (item.hasValue(0)) { if (item.hasValue(0)) {
// Validate the item, if it is partially supported. // Validate the item
validateKeywordItem<T>(keyword, validateKeywordItem<T>(keyword,
item_properties->second, item_properties->second,
keyword.size() > 1, keyword.size() > 1,
@ -172,7 +175,7 @@ namespace Opm::KeywordValidation {
template <typename T> template <typename T>
void KeywordValidator::validateKeywordItem(const DeckKeyword& keyword, void KeywordValidator::validateKeywordItem(const DeckKeyword& keyword,
const PartiallySupportedKeywordProperties<T>& properties, const SupportedKeywordProperties<T>& properties,
const bool multiple_records, const bool multiple_records,
const std::size_t record_index, const std::size_t record_index,
const std::size_t item_index, const std::size_t item_index,

View File

@ -20,6 +20,7 @@
#ifndef OPM_KEYWORDVALIDATION_HEADER_INCLUDED #ifndef OPM_KEYWORDVALIDATION_HEADER_INCLUDED
#define OPM_KEYWORDVALIDATION_HEADER_INCLUDED #define OPM_KEYWORDVALIDATION_HEADER_INCLUDED
#include <opm/input/eclipse/Deck/DeckItem.hpp>
#include <opm/common/OpmLog/KeywordLocation.hpp> #include <opm/common/OpmLog/KeywordLocation.hpp>
#include <opm/simulators/flow/ValidationFunctions.hpp> #include <opm/simulators/flow/ValidationFunctions.hpp>
@ -49,10 +50,10 @@ namespace KeywordValidation
std::optional<std::string> message; // An optional message to show if the keyword is present std::optional<std::string> message; // An optional message to show if the keyword is present
}; };
// Describe a partially supported keyword item, by listing legal values: // Describe a partially or fully supported keyword item, by listing legal values:
template <typename T> template <typename T>
struct PartiallySupportedKeywordProperties { struct SupportedKeywordProperties {
bool critical; // Set to true if the unsupported item value should be an error bool critical; // Set to true if an unsupported or invalid item value should be an error
std::function<bool(T)> validator; // Predicate function to test values std::function<bool(T)> validator; // Predicate function to test values
std::optional<std::string> message; // An optional message to show if an illegal item is encountered std::optional<std::string> message; // An optional message to show if an illegal item is encountered
}; };
@ -62,11 +63,11 @@ namespace KeywordValidation
// This is used to list the partially supported items of a keyword: // This is used to list the partially supported items of a keyword:
template <typename T> template <typename T>
using PartiallySupportedKeywordItems = std::map<std::size_t, PartiallySupportedKeywordProperties<T>>; using SupportedKeywordItems = std::map<std::size_t, SupportedKeywordProperties<T>>;
// This is used to list the keywords that have partially supported items: // This is used to list the keywords that have partially supported items or items that benefit from early validation:
template <typename T> template <typename T>
using PartiallySupportedKeywords = std::map<std::string, PartiallySupportedKeywordItems<T>>; using SupportedKeywords = std::map<std::string, SupportedKeywordItems<T>>;
// This contains the information needed to report a single error occurence. // This contains the information needed to report a single error occurence.
// The validator will construct a vector of these, copying the relevant // The validator will construct a vector of these, copying the relevant
@ -91,15 +92,21 @@ namespace KeywordValidation
class KeywordValidator class KeywordValidator
{ {
public: public:
KeywordValidator(const UnsupportedKeywords& keywords, KeywordValidator(const UnsupportedKeywords& unsupported_keywords,
const PartiallySupportedKeywords<std::string>& string_items, const SupportedKeywords<std::string>& partially_supported_string_items,
const PartiallySupportedKeywords<int>& int_items, const SupportedKeywords<int>& partially_supported_int_items,
const PartiallySupportedKeywords<double>& double_items, const SupportedKeywords<double>& partially_supported_double_items,
const SupportedKeywords<std::string>& fully_supported_string_items,
const SupportedKeywords<int>& fully_supported_int_items,
const SupportedKeywords<double>& fully_supported_double_items,
const std::unordered_map<std::string, ValidationFunction>& special_validation) const std::unordered_map<std::string, ValidationFunction>& special_validation)
: m_keywords(keywords) : m_unsupported_keywords(unsupported_keywords)
, m_string_items(string_items) , m_partially_supported_string_items(partially_supported_string_items)
, m_int_items(int_items) , m_partially_supported_int_items(partially_supported_int_items)
, m_double_items(double_items) , m_partially_supported_double_items(partially_supported_double_items)
, m_fully_supported_string_items(fully_supported_string_items)
, m_fully_supported_int_items(fully_supported_int_items)
, m_fully_supported_double_items(fully_supported_double_items)
, m_special_validation(special_validation) , m_special_validation(special_validation)
{ {
} }
@ -121,7 +128,7 @@ namespace KeywordValidation
private: private:
template <typename T> template <typename T>
void validateKeywordItem(const DeckKeyword& keyword, void validateKeywordItem(const DeckKeyword& keyword,
const PartiallySupportedKeywordProperties<T>& properties, const SupportedKeywordProperties<T>& properties,
const bool multiple_records, const bool multiple_records,
const std::size_t record_number, const std::size_t record_number,
const std::size_t item_number, const std::size_t item_number,
@ -131,13 +138,16 @@ namespace KeywordValidation
template <typename T> template <typename T>
void validateKeywordItems(const DeckKeyword& keyword, void validateKeywordItems(const DeckKeyword& keyword,
const PartiallySupportedKeywords<T>& partially_supported_options, const SupportedKeywords<T>& supported_options,
std::vector<ValidationError>& errors) const; std::vector<ValidationError>& errors) const;
const UnsupportedKeywords m_keywords; const UnsupportedKeywords m_unsupported_keywords;
const PartiallySupportedKeywords<std::string> m_string_items; const SupportedKeywords<std::string> m_partially_supported_string_items;
const PartiallySupportedKeywords<int> m_int_items; const SupportedKeywords<int> m_partially_supported_int_items;
const PartiallySupportedKeywords<double> m_double_items; const SupportedKeywords<double> m_partially_supported_double_items;
const SupportedKeywords<std::string> m_fully_supported_string_items;
const SupportedKeywords<int> m_fully_supported_int_items;
const SupportedKeywords<double> m_fully_supported_double_items;
const std::unordered_map<std::string, ValidationFunction> m_special_validation; const std::unordered_map<std::string, ValidationFunction> m_special_validation;
}; };
@ -163,6 +173,17 @@ namespace KeywordValidation
std::vector<T> m_allowed_values; std::vector<T> m_allowed_values;
}; };
// Helper to test if given string value is convertible to bool (see DeckItem::to_bool)
struct is_bool_convertible {
is_bool_convertible() {}
bool operator()(const std::string& value) const {
try {
return DeckItem::to_bool(value) || true;
} catch (const std::invalid_argument& e) {
return false;
}
}
};
} // namespace KeywordValidation } // namespace KeywordValidation

View File

@ -0,0 +1,80 @@
/*
Copyright 2021 Equinor.
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 <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H
#include <opm/simulators/utils/FullySupportedFlowKeywords.hpp>
using namespace Opm::KeywordValidation;
namespace Opm::FlowKeywordValidation
{
template <>
const SupportedKeywords<std::string>&
fullySupported()
{
static const SupportedKeywords<std::string> fully_supported_keywords_strings = {
{
"NEXTSTEP",
{
{2,{true, is_bool_convertible {}, "NEXTSTEP(NSTEP2): String value must be convertible to bool."}}, // APPLY_TO_FUTURE_REPORT_STEPS
},
},
{
"WCONHIST",
{
{3,{true, allow_values<std::string> {"ORAT", "WRAT", "GRAT", "LRAT", "RESV", "BHP"}, "WCONHIST(TARGET): should be set to ORAT/WRAT/GRAT/LRAT/RESV or BHP"}}, // CMODE
},
},
};
return fully_supported_keywords_strings;
}
template <>
const SupportedKeywords<int>&
fullySupported()
{
static const SupportedKeywords<int> fully_supported_keywords_int = {
};
return fully_supported_keywords_int;
}
template <>
const SupportedKeywords<double>&
fullySupported()
{
static const SupportedKeywords<double> fully_supported_keywords_double = {
{
"WPIMULT",
{
{2,{true, [](double x) { return x > 0; }, "WPIMULT(PIMULT): Well PI multiplier must be a positive number."}}, // PI_MULTIPLIER
},
},
};
return fully_supported_keywords_double;
}
} // namespace Opm::FlowKeywordValidation

View File

@ -0,0 +1,55 @@
/*
Copyright 2024 Equinor.
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 <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_FULLYSUPPORTEDFLOWKEYWORDS_HEADER_INCLUDED
#define OPM_FULLYSUPPORTEDFLOWKEYWORDS_HEADER_INCLUDED
#include <opm/simulators/flow/KeywordValidation.hpp>
#include <string>
/*
Here keywords are defined that are fully supported by flow, but nevertheless
can benefit from a preliminary high-level non-contextual verification.
The keywords are specified in a mapping with the keyword names as keys, and
values that describe the set of supported items. These are described by a
mapping from the item name to a struct of properties, defined in KeywordValidation.hpp.
This struct has the following fields:
critical (bool) : if this is a critical error.
validator (function wrapper) : A function wrapper object that is used to test values.
message (itemal string): an optional message to add to the error reported by flow.
For convenience there is a small class KeywordValidation::allow_values which
can be initialized with a list of permitted values, and used as a validator.
*/
namespace Opm::FlowKeywordValidation
{
template <typename T>
const KeywordValidation::SupportedKeywords<T>& fullySupported();
} // namespace Opm::FlowKeywordValidation
#endif

View File

@ -28,10 +28,10 @@ namespace Opm::FlowKeywordValidation
{ {
template <> template <>
const PartiallySupportedKeywords<std::string>& const SupportedKeywords<std::string>&
partiallySupported() partiallySupported()
{ {
static const PartiallySupportedKeywords<std::string> partially_supported_keywords_strings = { static const SupportedKeywords<std::string> partially_supported_keywords_strings = {
{ {
"BRANPROP", "BRANPROP",
{ {
@ -273,13 +273,6 @@ partiallySupported()
{5,{true, allow_values<std::string> {"NO"}, "WAGHYSTR(WATER_MODEL): only the NO option is supported will STOP"}}, // WATER_MODEL {5,{true, allow_values<std::string> {"NO"}, "WAGHYSTR(WATER_MODEL): only the NO option is supported will STOP"}}, // WATER_MODEL
}, },
}, },
{
"WCONHIST",
{
{3,{true, allow_values<std::string> {"ORAT", "WRAT", "GRAT", "LRAT", "RESV", "BHP"}, "WCONHIST(TARGET): should be set to ORAT/WRAT/GRAT/LRAT/RESV or BHP"}}, // CMODE
},
},
{ {
"WEFAC", "WEFAC",
{ {
@ -351,10 +344,10 @@ partiallySupported()
} }
template <> template <>
const KeywordValidation::PartiallySupportedKeywords<int>& const KeywordValidation::SupportedKeywords<int>&
partiallySupported() partiallySupported()
{ {
static const KeywordValidation::PartiallySupportedKeywords<int>partially_supported_keywords_int = { static const KeywordValidation::SupportedKeywords<int>partially_supported_keywords_int = {
{ {
"EDITNNC", "EDITNNC",
{ {
@ -535,10 +528,10 @@ partiallySupported()
} }
template <> template <>
const KeywordValidation::PartiallySupportedKeywords<double>& const KeywordValidation::SupportedKeywords<double>&
partiallySupported() partiallySupported()
{ {
static const KeywordValidation::PartiallySupportedKeywords<double> partially_supported_keywords_double = { static const KeywordValidation::SupportedKeywords<double> partially_supported_keywords_double = {
{ {
"AQUCON", "AQUCON",
{ {

View File

@ -47,7 +47,7 @@ namespace Opm::FlowKeywordValidation
{ {
template <typename T> template <typename T>
const KeywordValidation::PartiallySupportedKeywords<T>& partiallySupported(); const KeywordValidation::SupportedKeywords<T>& partiallySupported();
} // namespace Opm::FlowKeywordValidation } // namespace Opm::FlowKeywordValidation

View File

@ -63,6 +63,7 @@
#include <opm/simulators/flow/KeywordValidation.hpp> #include <opm/simulators/flow/KeywordValidation.hpp>
#include <opm/simulators/flow/ValidationFunctions.hpp> #include <opm/simulators/flow/ValidationFunctions.hpp>
#include <opm/simulators/utils/FullySupportedFlowKeywords.hpp>
#include <opm/simulators/utils/ParallelEclipseState.hpp> #include <opm/simulators/utils/ParallelEclipseState.hpp>
#include <opm/simulators/utils/ParallelSerialization.hpp> #include <opm/simulators/utils/ParallelSerialization.hpp>
#include <opm/simulators/utils/PartiallySupportedFlowKeywords.hpp> #include <opm/simulators/utils/PartiallySupportedFlowKeywords.hpp>
@ -210,6 +211,9 @@ namespace {
Opm::FlowKeywordValidation::partiallySupported<std::string>(), Opm::FlowKeywordValidation::partiallySupported<std::string>(),
Opm::FlowKeywordValidation::partiallySupported<int>(), Opm::FlowKeywordValidation::partiallySupported<int>(),
Opm::FlowKeywordValidation::partiallySupported<double>(), Opm::FlowKeywordValidation::partiallySupported<double>(),
Opm::FlowKeywordValidation::fullySupported<std::string>(),
Opm::FlowKeywordValidation::fullySupported<int>(),
Opm::FlowKeywordValidation::fullySupported<double>(),
Opm::KeywordValidation::specialValidation() Opm::KeywordValidation::specialValidation()
}; };