Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate keyword validation for fully supported keywords #5866

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ list (APPEND MAIN_SOURCE_FILES
opm/simulators/utils/BlackoilPhases.cpp
opm/simulators/utils/ComponentName.cpp
opm/simulators/utils/DeferredLogger.cpp
opm/simulators/utils/FullySupportedFlowKeywords.cpp
opm/simulators/utils/ParallelFileMerger.cpp
opm/simulators/utils/ParallelRestart.cpp
opm/simulators/utils/PartiallySupportedFlowKeywords.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 @@ -123,29 +123,32 @@ namespace Opm::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 @@ -154,7 +157,7 @@ namespace Opm::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 @@ -172,7 +175,7 @@ namespace Opm::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 <opm/simulators/flow/ValidationFunctions.hpp>

Expand Down Expand Up @@ -49,10 +50,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 @@ -62,11 +63,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 All @@ -91,15 +92,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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imho this is getting out of hand. I'd introduce some struct, e.g.

struct Supported
{
  SupportedKeywords<std::string>& string;
  SupportedKeywords<int>& int;
  SupportedKeywords<double>& double;
};

and adjust constructor to

KeywordValidator(unsupported, partially_supported, fully_supported, special)

and adjust getters accordingly.

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, ValidationFunction>& 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 @@ -121,7 +128,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 @@ -131,13 +138,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, ValidationFunction> m_special_validation;
};

Expand All @@ -163,6 +173,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
80 changes: 80 additions & 0 deletions opm/simulators/utils/FullySupportedFlowKeywords.cpp
Original file line number Diff line number Diff line change
@@ -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
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
19 changes: 6 additions & 13 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 @@ -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
},
},

{
"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",
{
Expand Down Expand Up @@ -351,10 +344,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 @@ -535,10 +528,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
2 changes: 1 addition & 1 deletion opm/simulators/utils/PartiallySupportedFlowKeywords.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace Opm::FlowKeywordValidation
{

template <typename T>
const KeywordValidation::PartiallySupportedKeywords<T>& partiallySupported();
const KeywordValidation::SupportedKeywords<T>& partiallySupported();

} // namespace Opm::FlowKeywordValidation

Expand Down
Loading