Skip to content

Commit

Permalink
Adding 'FullySupportedKeywords' to find easy errors early also in ful…
Browse files Browse the repository at this point in the history
…ly supported keywords.
  • Loading branch information
vkip committed Jun 24, 2024
1 parent 6515c63 commit db6e623
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 50 deletions.
1 change: 1 addition & 0 deletions CMakeLists_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ list (APPEND MAIN_SOURCE_FILES
opm/simulators/utils/ComponentName.cpp
opm/simulators/utils/compressPartition.cpp
opm/simulators/utils/DeferredLogger.cpp
opm/simulators/utils/FullySupportedFlowKeywords.cpp
opm/simulators/utils/gatherDeferredLogger.cpp
opm/simulators/utils/ParallelFileMerger.cpp
opm/simulators/utils/ParallelRestart.cpp
Expand Down
25 changes: 14 additions & 11 deletions opm/simulators/flow/KeywordValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,29 +131,32 @@ namespace KeywordValidation

void KeywordValidator::validateDeckKeyword(const DeckKeyword& keyword, std::vector<ValidationError>& errors) const
{
const auto& it = m_keywords.find(keyword.name());
if (it != m_keywords.end()) {
const auto& it = m_unsupported_keywords.find(keyword.name());
if (it != m_unsupported_keywords.end()) {
// If the keyword is not supported, add an error for that.
const auto& properties = it->second;
errors.push_back(ValidationError {
properties.critical, keyword.location(), 1, std::nullopt, std::nullopt, properties.message});
} else {
// Otherwise, check all its items.
validateKeywordItems(keyword, m_string_items, errors);
validateKeywordItems(keyword, m_int_items, errors);
validateKeywordItems(keyword, m_double_items, errors);
validateKeywordItems(keyword, m_partially_supported_string_items, errors);
validateKeywordItems(keyword, m_partially_supported_int_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>
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
{
const auto& keyword_properties = partially_supported_items.find(keyword.name());
if (keyword_properties != partially_supported_items.end()) {
// If this keyworcs has partially supported items, iterate over all of them.
const auto& keyword_properties = partially_or_fully_supported_items.find(keyword.name());
if (keyword_properties != partially_or_fully_supported_items.end()) {
// 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++) {
const auto& record = keyword.getRecord(record_index);
for (std::size_t item_index = 0; item_index < record.size(); item_index++) {
Expand All @@ -162,7 +165,7 @@ namespace KeywordValidation
const auto& item_properties = keyword_properties->second.find(item_index + 1);
if (item_properties != keyword_properties->second.end()) {
if (item.hasValue(0)) {
// Validate the item, if it is partially supported.
// Validate the item
validateKeywordItem<T>(keyword,
item_properties->second,
keyword.size() > 1,
Expand All @@ -180,7 +183,7 @@ namespace KeywordValidation

template <typename T>
void KeywordValidator::validateKeywordItem(const DeckKeyword& keyword,
const PartiallySupportedKeywordProperties<T>& properties,
const SupportedKeywordProperties<T>& properties,
const bool multiple_records,
const std::size_t record_index,
const std::size_t item_index,
Expand Down
61 changes: 41 additions & 20 deletions opm/simulators/flow/KeywordValidation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#ifndef OPM_KEYWORDVALIDATION_HEADER_INCLUDED
#define OPM_KEYWORDVALIDATION_HEADER_INCLUDED

#include <opm/input/eclipse/Deck/DeckItem.hpp>
#include <opm/common/OpmLog/KeywordLocation.hpp>

#include <algorithm>
Expand Down Expand Up @@ -48,10 +49,10 @@ namespace KeywordValidation
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>
struct PartiallySupportedKeywordProperties {
bool critical; // Set to true if the unsupported item value should be an error
struct SupportedKeywordProperties {
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::optional<std::string> message; // An optional message to show if an illegal item is encountered
};
Expand All @@ -61,11 +62,11 @@ namespace KeywordValidation

// This is used to list the partially supported items of a keyword:
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>
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.
// The validator will construct a vector of these, copying the relevant
Expand Down Expand Up @@ -97,15 +98,21 @@ namespace KeywordValidation
class KeywordValidator
{
public:
KeywordValidator(const UnsupportedKeywords& keywords,
const PartiallySupportedKeywords<std::string>& string_items,
const PartiallySupportedKeywords<int>& int_items,
const PartiallySupportedKeywords<double>& double_items,
KeywordValidator(const UnsupportedKeywords& unsupported_keywords,
const SupportedKeywords<std::string>& partially_supported_string_items,
const SupportedKeywords<int>& partially_supported_int_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, std::function<void(const DeckKeyword& keyword, std::vector<ValidationError>& errors)>>& special_validation)
: m_keywords(keywords)
, m_string_items(string_items)
, m_int_items(int_items)
, m_double_items(double_items)
: m_unsupported_keywords(unsupported_keywords)
, m_partially_supported_string_items(partially_supported_string_items)
, m_partially_supported_int_items(partially_supported_int_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)
{
}
Expand All @@ -127,7 +134,7 @@ namespace KeywordValidation
private:
template <typename T>
void validateKeywordItem(const DeckKeyword& keyword,
const PartiallySupportedKeywordProperties<T>& properties,
const SupportedKeywordProperties<T>& properties,
const bool multiple_records,
const std::size_t record_number,
const std::size_t item_number,
Expand All @@ -137,13 +144,16 @@ namespace KeywordValidation

template <typename T>
void validateKeywordItems(const DeckKeyword& keyword,
const PartiallySupportedKeywords<T>& partially_supported_options,
const SupportedKeywords<T>& supported_options,
std::vector<ValidationError>& errors) const;

const UnsupportedKeywords m_keywords;
const PartiallySupportedKeywords<std::string> m_string_items;
const PartiallySupportedKeywords<int> m_int_items;
const PartiallySupportedKeywords<double> m_double_items;
const UnsupportedKeywords m_unsupported_keywords;
const SupportedKeywords<std::string> m_partially_supported_string_items;
const SupportedKeywords<int> m_partially_supported_int_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, std::function<void(const DeckKeyword& keyword, std::vector<ValidationError>& errors)>> m_special_validation;
};

Expand All @@ -169,6 +179,17 @@ namespace KeywordValidation
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

Expand Down
86 changes: 86 additions & 0 deletions opm/simulators/utils/FullySupportedFlowKeywords.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
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 = {
{
"WEFAC",
{
{3,{true, is_bool_convertible {}, "WEFAC(WELNETWK): String value must be convertible to bool."}}, // USE_WEFAC_IN_NETWORK
},
},
{
"GEFAC",
{
{3,{true, is_bool_convertible {}, "GEFAC(GRPNETWK): String value must be convertible to bool."}}, // USE_GEFAC_IN_NETWORK
},
},
};

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 = {
{
"WEFAC",
{
{2,{true, [](double x) { return x > 0; }, "WEFAC(FACTOR): Well efficiency must be a positive number."}}, // WELL_EFFICIENCY
},
},
{
"GEFAC",
{
{2,{true, [](double x) { return x > 0; }, "GEFAC(FACTOR): Well efficiency must be a positive number."}}, // WELL_EFFICIENCY
},
},
};

return fully_supported_keywords_double;
}

} // namespace Opm::FlowKeywordValidation
55 changes: 55 additions & 0 deletions opm/simulators/utils/FullySupportedFlowKeywords.hpp
Original file line number Diff line number Diff line change
@@ -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
24 changes: 6 additions & 18 deletions opm/simulators/utils/PartiallySupportedFlowKeywords.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ namespace Opm::FlowKeywordValidation
{

template <>
const PartiallySupportedKeywords<std::string>&
const SupportedKeywords<std::string>&
partiallySupported()
{
static const PartiallySupportedKeywords<std::string> partially_supported_keywords_strings = {
static const SupportedKeywords<std::string> partially_supported_keywords_strings = {
{
"BRANPROP",
{
Expand Down Expand Up @@ -111,12 +111,6 @@ partiallySupported()
{8,{true, allow_values<std::string> {"NO"}, "GECON(ENDRUN): End run not implemented"}},
},
},
{
"GEFAC",
{
{3,{true, allow_values<std::string> {"YES", "NO"}, "GEFAC(GRPNETWK): should be set to either YES or NO"}}, // USE_GEFAC_IN_NETWORK
},
},
{
"GRIDOPTS",
{
Expand Down Expand Up @@ -281,12 +275,6 @@ partiallySupported()
{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",
{
{3,{true, allow_values<std::string> {"YES","NO"}, "WEFAC(WELNETWK): value must be YES or NO"}}, // USE_WEFAC_IN_NETWORK
},
},
{
"WELSPECS",
{
Expand Down Expand Up @@ -352,10 +340,10 @@ partiallySupported()
}

template <>
const KeywordValidation::PartiallySupportedKeywords<int>&
const KeywordValidation::SupportedKeywords<int>&
partiallySupported()
{
static const KeywordValidation::PartiallySupportedKeywords<int>partially_supported_keywords_int = {
static const KeywordValidation::SupportedKeywords<int>partially_supported_keywords_int = {
{
"EDITNNC",
{
Expand Down Expand Up @@ -536,10 +524,10 @@ partiallySupported()
}

template <>
const KeywordValidation::PartiallySupportedKeywords<double>&
const KeywordValidation::SupportedKeywords<double>&
partiallySupported()
{
static const KeywordValidation::PartiallySupportedKeywords<double> partially_supported_keywords_double = {
static const KeywordValidation::SupportedKeywords<double> partially_supported_keywords_double = {
{
"AQUCON",
{
Expand Down
Loading

0 comments on commit db6e623

Please sign in to comment.