Add keyword validation using a predicate function

This commit is contained in:
Peter Verveer
2021-06-11 18:22:29 +02:00
parent f9618faceb
commit fd753e20c4
6 changed files with 145 additions and 49 deletions

View File

@@ -109,6 +109,7 @@ namespace KeywordValidation
// Otherwise, check all its items.
validateKeywordItems(keyword, m_string_items, errors);
validateKeywordItems(keyword, m_int_items, errors);
validateKeywordItems(keyword, m_double_items, errors);
}
}
@@ -152,8 +153,7 @@ namespace KeywordValidation
const T& item_value,
std::vector<ValidationError>& errors) const
{
const auto& permitted = properties.permitted_values;
if (std::find(permitted.begin(), permitted.end(), item_value) == permitted.end()) {
if (!properties.validator(item_value)) {
// If the value is not permitted, format the value to report it.
std::string formatted_value;
if constexpr (std::is_arithmetic<T>::value)

View File

@@ -22,6 +22,8 @@
#include <opm/common/OpmLog/KeywordLocation.hpp>
#include <functional>
#include <initializer_list>
#include <map>
#include <optional>
#include <string>
@@ -47,7 +49,7 @@ namespace KeywordValidation
template <typename T>
struct PartiallySupportedKeywordProperties {
bool critical; // Set to true if the unsupported item value should be an error
std::vector<T> permitted_values; // The list of permitted 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
};
@@ -68,8 +70,8 @@ namespace KeywordValidation
struct ValidationError {
bool critical; // Determines if the encountered problem should be an error or a warning
KeywordLocation location; // Location information (keyword name, file and line number)
size_t record_number; // Number of the offending record.
std::optional<size_t> item_number; // Number of the offending item, -1 if the kewyord is not supported at all.
size_t record_number; // Number of the offending record
std::optional<size_t> item_number; // Number of the offending item
std::optional<std::string> item_value; // The offending value of a problematic item
std::optional<std::string> user_message; // An optional message to show if a problem is encountered
};
@@ -86,10 +88,12 @@ namespace KeywordValidation
public:
KeywordValidator(const UnsupportedKeywords& keywords,
const PartiallySupportedKeywords<std::string>& string_items,
const PartiallySupportedKeywords<int>& int_items)
const PartiallySupportedKeywords<int>& int_items,
const PartiallySupportedKeywords<double>& double_items)
: m_keywords(keywords)
, m_string_items(string_items)
, m_int_items(int_items)
, m_double_items(double_items)
{
}
@@ -121,6 +125,29 @@ namespace KeywordValidation
const UnsupportedKeywords m_keywords;
const PartiallySupportedKeywords<std::string> m_string_items;
const PartiallySupportedKeywords<int> m_int_items;
const PartiallySupportedKeywords<double> m_double_items;
};
// Helper class to test if a given value is with a list of allowed values.
template <typename T>
class allow_values
{
public:
allow_values(const std::initializer_list<T>& allowed_values)
{
for (auto item : allowed_values) {
m_allowed_values.push_back(item);
}
}
bool operator()(const T& value) const
{
return std::find(m_allowed_values.begin(), m_allowed_values.end(), value) != m_allowed_values.end();
}
private:
std::vector<T> m_allowed_values;
};

View File

@@ -19,32 +19,33 @@
#include <opm/simulators/utils/PartiallySupportedFlowKeywords.hpp>
using namespace Opm::KeywordValidation;
namespace Opm::FlowKeywordValidation
{
template<>
const KeywordValidation::PartiallySupportedKeywords<std::string>&
template <>
const PartiallySupportedKeywords<std::string>&
partiallySupported()
{
static const KeywordValidation::PartiallySupportedKeywords<std::string> partially_supported_keywords_strings = {
static const PartiallySupportedKeywords<std::string> partially_supported_keywords_strings = {
{
"COMPORD",
{
{2, {false, {"INPUT"}, std::nullopt}}, // ORDER_TYPE
{2, {false, allow_values<std::string>{"INPUT"}, std::nullopt}}, // ORDER_TYPE
},
},
{
"ENDSCALE",
{
{1, {false, {"NODIR"}, std::nullopt}}, // DIRECT
{2, {false, {"REVERS"}, std::nullopt}}, // IRREVERS
{1, {false, allow_values<std::string>{"NODIR"}, std::nullopt}}, // DIRECT
{2, {false, allow_values<std::string>{"REVERS"}, std::nullopt}}, // IRREVERS
},
},
{
"PINCH",
{
{2, {false, {"GAP"}, std::nullopt}}, // GAP
{4, {false, {"TOPBOT"}, std::nullopt}}, // PINCHOUT_OPTION
{2, {false, allow_values<std::string>{"GAP"}, std::nullopt}}, // GAP
{4, {false, allow_values<std::string>{"TOPBOT"}, std::nullopt}}, // PINCHOUT_OPTION
},
},
};
@@ -52,15 +53,15 @@ partiallySupported()
return partially_supported_keywords_strings;
}
template<>
const KeywordValidation::PartiallySupportedKeywords<int>&
template <>
const PartiallySupportedKeywords<int>&
partiallySupported()
{
static const KeywordValidation::PartiallySupportedKeywords<int> partially_supported_keywords_int = {
static const PartiallySupportedKeywords<int> partially_supported_keywords_int = {
{
"EHYSTR",
{
{2, {false, {0}, std::nullopt}}, //relative_perm_hyst
{2, {false, allow_values<int>{0}, std::nullopt}}, // relative_perm_hyst
},
},
};
@@ -68,4 +69,13 @@ partiallySupported()
return partially_supported_keywords_int;
}
template <>
const PartiallySupportedKeywords<double>&
partiallySupported()
{
static const PartiallySupportedKeywords<double> partially_supported_keywords_double = {};
return partially_supported_keywords_double;
}
} // namespace Opm::FlowKeywordValidation

View File

@@ -36,16 +36,17 @@
This struct has the following fields:
critical (bool) : if this is a critical error.
permitted_values (vector of strings) : the list of values that is allowed.
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.
Below is the set of partiall supported keywords, currently used 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>
template <typename T>
const KeywordValidation::PartiallySupportedKeywords<T>& partiallySupported();
} // namespace Opm::FlowKeywordValidation

View File

@@ -210,7 +210,8 @@ void readDeck(int rank, std::string& deckFilename, std::unique_ptr<Opm::Deck>& d
Opm::KeywordValidation::KeywordValidator keyword_validator(
Opm::FlowKeywordValidation::unsupportedKeywords(),
Opm::FlowKeywordValidation::partiallySupported<std::string>(),
Opm::FlowKeywordValidation::partiallySupported<int>());
Opm::FlowKeywordValidation::partiallySupported<int>(),
Opm::FlowKeywordValidation::partiallySupported<double>());
keyword_validator.validateDeck(*deck, *parseContext, *errorGuard);
if ( checkDeck )