Implement a new keyword validator

This commit is contained in:
Peter Verveer 2021-04-09 22:20:38 +02:00
parent bace3c4d19
commit 1640c4afcf
9 changed files with 1674 additions and 941 deletions

View File

@ -25,7 +25,7 @@
list (APPEND MAIN_SOURCE_FILES
opm/core/props/satfunc/RelpermDiagnostics.cpp
opm/simulators/timestepping/SimulatorReport.cpp
opm/simulators/flow/MissingFeatures.cpp
opm/simulators/flow/KeywordValidation.cpp
opm/simulators/linalg/ExtractParallelGridInformationToISTL.cpp
opm/simulators/linalg/FlexibleSolver1.cpp
opm/simulators/linalg/FlexibleSolver2.cpp
@ -95,6 +95,7 @@ list (APPEND TEST_SOURCE_FILES
tests/test_wellstatefullyimplicitblackoil.cpp
tests/test_parallelwellinfo.cpp
tests/test_glift1.cpp
tests/test_keyword_validator.cpp
)
if(MPI_FOUND)
@ -162,7 +163,7 @@ list (APPEND PUBLIC_HEADER_FILES
opm/simulators/flow/Main.hpp
opm/simulators/flow/NonlinearSolverEbos.hpp
opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp
opm/simulators/flow/MissingFeatures.hpp
opm/simulators/flow/KeywordValidation.hpp
opm/core/props/BlackoilPhases.hpp
opm/core/props/phaseUsageFromDeck.hpp
opm/core/props/satfunc/RelpermDiagnostics.hpp

View File

@ -0,0 +1,163 @@
/*
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/>.
*/
#include <map>
#include <string>
#include <type_traits>
#include <fmt/format.h>
#include <opm/common/utility/OpmInputError.hpp>
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include <opm/simulators/flow/KeywordValidation.hpp>
namespace Opm
{
namespace KeywordValidation
{
std::string get_error_report(const std::vector<ValidationError>& errors, const bool critical)
{
const std::string keyword_format = " {keyword}: keyword not supported\n";
const std::string item_format = " {{keyword}}: invalid value '{}' in record {} for item {}\n";
const std::string location_format = " In file: {file}, line {line}\n";
std::string report;
for (const ValidationError& err : errors) {
if (err.critical == critical) {
if (err.item_number && err.item_value) {
std::string message
= fmt::format(item_format, *(err.item_value), err.record_number, *(err.item_number));
report.append(OpmInputError::format(message, err.location));
} else {
report.append(OpmInputError::format(keyword_format, err.location));
}
report.append(OpmInputError::format(location_format, err.location));
if (err.user_message) {
report.append(" " + *(err.user_message) + "\n");
}
report.append("\n");
}
}
if (!report.empty()) {
// Remove the last two newlines.
report.erase(report.length() - 2);
// Prepend header and file name.
report.insert(0, "Unsupported keywords or keyword items:\n\n");
}
return report;
}
void
KeywordValidator::validateDeck(const Deck& deck, const ParseContext& parse_context, ErrorGuard& error_guard) const
{
// Make a vector with all problems encountered in the deck.
std::vector<ValidationError> errors;
for (const auto& keyword : deck)
validateDeckKeyword(keyword, errors);
// First report non-critical problems as a warning.
auto warning_report = get_error_report(errors, false);
if (!warning_report.empty()) {
parse_context.handleError(
ParseContext::SIMULATOR_KEYWORD_NOT_SUPPORTED, warning_report, std::nullopt, error_guard);
}
// Then report critical problems as an error.
auto error_report = get_error_report(errors, true);
if (!error_report.empty()) {
parse_context.handleError(
ParseContext::SIMULATOR_KEYWORD_NOT_SUPPORTED_CRITICAL, error_report, std::nullopt, error_guard);
}
}
void KeywordValidator::validateDeckKeyword(const DeckKeyword& keyword, std::vector<ValidationError>& errors) const
{
const auto& it = m_keywords.find(keyword.name());
if (it != m_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);
}
}
template <typename T>
void KeywordValidator::validateKeywordItems(const DeckKeyword& keyword,
const PartiallySupportedKeywords<T>& partially_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.
for (size_t record_index = 0; record_index < keyword.size(); record_index++) {
const auto& record = keyword.getRecord(record_index);
for (size_t item_index = 0; item_index < record.size(); item_index++) {
const auto& item = record.getItem(item_index);
// Find the index number, which starts counting at one, so item_index + 1
const auto& item_properties = keyword_properties->second.find(item_index + 1);
if (item_properties != keyword_properties->second.end()) {
// Validate the item, if it is partially supported.
validateKeywordItem<T>(
keyword, item_properties->second, record_index, item_index, item.get<T>(0), errors);
}
}
}
}
}
template <typename T>
void KeywordValidator::validateKeywordItem(const DeckKeyword& keyword,
const PartiallySupportedKeywordProperties<T>& properties,
const size_t record_index,
const size_t item_index,
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 the value is not permitted, format the value to report it.
std::string formatted_value;
if constexpr (std::is_arithmetic<T>::value)
formatted_value = std::to_string(item_value);
else
formatted_value = item_value;
// Add the relevant information to the vector of errors.
errors.push_back(ValidationError {properties.critical,
keyword.location(),
record_index + 1, // record numbers start at 1
item_index + 1, // item numbers start at 1
formatted_value,
properties.message});
}
}
} // namespace KeywordValidation
} // namespace Opm

View File

@ -0,0 +1,129 @@
/*
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/>.
*/
#ifndef OPM_KEYWORDVALIDATION_HEADER_INCLUDED
#define OPM_KEYWORDVALIDATION_HEADER_INCLUDED
#include <opm/common/OpmLog/KeywordLocation.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <optional>
#include <string>
#include <vector>
namespace Opm
{
class ErrorGuard;
class ParseContext;
namespace KeywordValidation
{
// Describe an unsupported keyword:
struct UnsupportedKeywordProperties {
bool critical; // Set to true if presence of the keyword should be an error
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:
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::optional<std::string> message; // An optional message to show if an illegal item is encountered
};
// This is used to list unsupported kewyords.
using UnsupportedKeywords = std::map<std::string, UnsupportedKeywordProperties>;
// This is used to list the partially supported items of a keyword:
template <typename T>
using PartiallySupportedKeywordItems = std::map<size_t, PartiallySupportedKeywordProperties<T>>;
// This is used to list the keywords that have partially supported items:
template <typename T>
using PartiallySupportedKeywords = std::map<std::string, PartiallySupportedKeywordItems<T>>;
// This contains the information needed to report a single error occurence.
// The validator will construct a vector of these, copying the relevant
// information from the properties of the offending keywords and items.
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.
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
};
// Get a formatted error report from a vector of validation errors. Set
// critical to true if the report should contain only critical errors. If
// critical is false, only non-critical errors are reported. If not
// critical/non-critical errors are present, but the critical flag to reset
// them, the result will be an empty string.
std::string get_error_report(const std::vector<ValidationError>& errors, const bool critical);
class KeywordValidator
{
public:
KeywordValidator(const UnsupportedKeywords& keywords,
const PartiallySupportedKeywords<std::string>& string_items,
const PartiallySupportedKeywords<int>& int_items)
: m_keywords(keywords)
, m_string_items(string_items)
, m_int_items(int_items)
{
}
// Validate a deck, reporting warnings and errors. If there are only
// warnings, these will be reported. If there are errors, these are
// reported, and execution of the program is halted.
void validateDeck(const Deck& deck, const ParseContext& parse_context, ErrorGuard& error_guard) const;
// Validate a single deck keyword. If a problem is encountered, add the
// relevant information to the errors vector.
void validateDeckKeyword(const DeckKeyword& keyword, std::vector<ValidationError>& errors) const;
private:
template <typename T>
void validateKeywordItem(const DeckKeyword& keyword,
const PartiallySupportedKeywordProperties<T>& properties,
const size_t record_number,
const size_t item_number,
const T& item_value,
std::vector<ValidationError>& errors) const;
template <typename T>
void validateKeywordItems(const DeckKeyword& keyword,
const PartiallySupportedKeywords<T>& partially_supported_options,
std::vector<ValidationError>& errors) const;
const UnsupportedKeywords m_keywords;
const PartiallySupportedKeywords<std::string> m_string_items;
const PartiallySupportedKeywords<int> m_int_items;
};
} // namespace KeywordValidation
} // namespace Opm
#endif

View File

@ -1,879 +0,0 @@
/*
Copyright 2016 Statoil ASA.
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/>.
*/
#include <fmt/format.h>
#include <opm/simulators/flow/MissingFeatures.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/C.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/E.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/P.hpp>
#include <unordered_set>
#include <string>
#include <map>
#include <type_traits>
namespace Opm {
namespace MissingFeatures {
template <typename Keyword, typename Item, typename T>
void addSupported(std::multimap<std::string, PartiallySupported<T> >& map, T itemValue)
{
std::pair<std::string,PartiallySupported<T> > pair({Keyword::keywordName, PartiallySupported<T>{Item::itemName , itemValue}});
map.insert(pair);
}
template <typename T>
void checkOptions(const DeckKeyword& keyword, std::multimap<std::string , PartiallySupported<T> >& map, const ParseContext& parseContext, ErrorGuard& errorGuard)
{
// check for partially supported keywords.
typename std::multimap<std::string, PartiallySupported<T> >::iterator it, itlow, itup;
itlow = map.lower_bound(keyword.name());
itup = map.upper_bound(keyword.name());
for (it = itlow; it != itup; ++it) {
const auto& record = keyword.getRecord(0);
if (record.getItem(it->second.item).template get<T>(0) != it->second.item_value) {
std::string val;
if constexpr (std::is_arithmetic<T>::value)
val = std::to_string(it->second.item_value);
else
val = it->second.item_value;
std::string msg_fmt = fmt::format("Unsupported value for {{keyword}}\n"
"In {{file}} line {{line}}\n"
"Only the value {} in item {} of {{keyword}} is supported by flow", val, it->second.item);
parseContext.handleError(ParseContext::SIMULATOR_KEYWORD_ITEM_NOT_SUPPORTED, msg_fmt, keyword.location(), errorGuard);
}
}
}
template <typename T>
void checkKeywords(const Deck& deck, const ParseContext& parseContext, T&& errorGuard) {
checkKeywords(deck, parseContext, errorGuard);
}
void checkKeywords(const Deck& deck) {
checkKeywords(deck, ParseContext(), ErrorGuard());
}
void checkKeywords(const Deck& deck, const ParseContext& parseContext, ErrorGuard& errorGuard)
{
// These keywords are supported by opm-parser, but are not supported
// by flow. For some of them, only part of the options are supported.
// The list is used to output messages only.
std::unordered_set<std::string> unsupported_keywords = {
"ACTION",
"ACTIONG",
"ACTIONR",
"ACTIONS",
"ACTIONW",
"ACTPARAM",
"ADSALNOD",
"ADDZCORN",
"ADSORP",
"AITS",
"AITSOFF",
"ALKADS",
"ALKALINE",
"ALKROCK",
"API",
"ALPOLADS",
"ALSURFAD",
"ALSURFST",
"AMALGAM",
"APIGROUP",
"APILIM",
"APIVD",
"AQANCONL",
"AQANNC",
"AQANTRC",
"AQUALIST",
"AQUCHGAS",
"AQUCHWAT",
"AQUCON",
"AQUCWFAC",
"AQUFET",
"AQUFLUX",
"AQUNNC",
"AQUNUM",
"AUTOCOAR",
"AUTOREF",
"BIGMODEL",
"BDENSITY",
"BGGI",
"BOGI",
"BOUNDARY",
"BPARA",
"BPIDIMS",
"BRANPROP",
"BTOBALFA",
"BTOBALFV",
"CALTRAC",
"CARFIN",
"CART",
"CBMOPTS",
"CECON",
"CECONT",
"COAL",
"COALADS",
"COALNUM",
"COALPP",
"COARSEN",
"COLLAPSE",
"COLUMNS",
"CBMOPTS",
"COMPDATX",
"COMPDATL",
"COMPDATM",
"COMPDATL",
"COMPIMB",
"COMPFLSH",
"COMPINJK",
"COMPLMPL",
"COMPOFF",
"COMPRIV",
"COMPRP",
"COMPRPL",
"COMPSEGL",
"COMPVE",
"COMPVEL",
"CPIFACT",
"CPIFACTL",
"CPR",
"CSKIN",
"CONNECTION",
"CONNECTION_PROBE",
"COORDSYS",
"COPYBOX",
"COPYREG",
"CRITPERM",
"DATUMR",
"DATUMRX",
"DCQDEFN",
"DEBUG",
"DELAYACT",
"DEPTHTAB",
"DIAGDISP",
"DIFF",
"DIFFC",
"DIFFCOAL",
"DIFFDP",
"DIFFMMF",
"DIFFMR",
"DIFFMR-",
"DIFFMTHT",
"DIFFMTH-",
"DIFFMX",
"DIFFMX-",
"DIFFMY",
"DIFFMY-",
"DIFFMZ",
"DIFFMZ-",
"DIFFR",
"DIFFTHT",
"DIFFUSE"
"DIFFX",
"DIFFY",
"DIFFZ",
"DIMPES",
"DIMPLICT",
"DISPDIMS",
"DISPERSE",
"DOMAINS",
"DPGRID",
"DPKRMOD",
"DPNUM",
"DRILPRI",
"DSPDEINT",
"DUALPERM",
"DUALPORO",
"DUMPCUPL",
"DUMPFLUX",
"DYNAMICR",
"DYNRDIMS",
"DYNAMICR",
"DZMATRIX",
"DZMTRX",
"DZMTRXV",
"DZNET",
"ECHO",
"ECLMC",
"EDITNNCR",
"EHYSTRR",
"ENDDYN",
"ENDFIN",
"ENDNUM",
"ENDSKIP",
"ENKRVD",
"ENKSRVD",
"ENPCVD",
"ENPTVD",
"ENSPCVD",
"EPSDBGS",
"EPSDEBUG",
"EQLZCORN",
"EQUALREG",
"ESSNODE",
"EXCAVATE",
"EXCEL",
"EXTFIN",
"EXTHOST",
"EXTRAPMS",
"EXTREPGL",
"FBHPDEF",
"FHERCHBL",
"FRICTION",
"FIPSEP",
"FLUXREG",
"FLUXTYPE",
"FMTHMD",
"FOAMDCYO",
"FOAMDCYW",
"FOAMFCN",
"FOAMFRM",
"FOAMFSO"
"FOAMFST",
"FOAMFSW",
"FOAMMOBP",
"FOAMMOBS",
"FORMFEED",
"FULLIMP",
"GEGONT",
"GETDATA",
"GASBEGIN",
"GASCONC",
"GASEND",
"GASFCOMP",
"GASFDECR",
"GASFDELC",
"GASFIELD",
"GASFTARG",
"GASMONTH",
"GASPERIO",
"GASSATC",
"GASYEAR",
"GCALECON",
"GCONCAL",
"GCONENG",
"GCONPRI",
"GCONTOL",
"GCUTBACK",
"GCUTBACT",
"GCVD",
"GDCQ",
"GDCQECON",
"GDIMS",
"GDORIENT",
"GDRILPOT",
"GECON",
"GECONT",
"GETGLOB",
"GI",
"GIALL",
"GIMODEL",
"GINODE",
"GLIFTLIM",
"GLIFTOPT",
"GNETDP",
"GNETINJE",
"GNETPUMP",
"GPMAINT",
"GRADGRUP",
"GRADRESV",
"GRADRFT",
"GRADWELL",
"GRAVCONS",
"GRAVDR",
"GRAVDRB",
"GRAVDRM",
"GRDREACH",
"GRIDUNIT",
"GRUPMAST",
"GRUPNET",
"GRUPRIG",
"GRUPSLAV",
"GRUPTARG",
"GSATINJE",
"GSEPCOND",
"GSSCPTST",
"GSWINGF",
"GTADD",
"GTMULT",
"GUIDECAL",
"GSATPROD",
"GUPFREQ",
"GWRTWCV",
"HALFTRAN",
"HAxxxxxx",
"HBNUM",
"HDISP",
"HMAQUCT",
"HMAQUFET",
"HMAQUNUM",
"HMDIMS",
"HMFAULTS",
"HMMLAQUN",
"HMMLCTAQ",
"HMMLFTAQ",
"HMMLTWCN",
"HMMULTxx",
"HMMULTFT",
"HMMULTSG",
"HMPROPS",
"HMROCK",
"HMROCKT",
"HMRREF",
"HMWELCON",
"HMWPIMLT",
"HMxxxxxx",
"HRFIN",
"HWKRO",
"HWKRORG",
"HWKRORW",
"HWKRW",
"HWKRWR",
"HWPCW",
"HWSNUM",
"HWSOGCR",
"HWSOWCR",
"HWSWCR",
"HWSWL",
"HWSWLPC",
"HWSWU",
"HXFIN",
"HYDRHEAD",
"HYFIN",
"HYMOBGDR",
"HYST",
"HYSTCHCK",
"HZFIN",
"IHOST",
"IMBNUMMF",
"IMKRVD",
"IMPCVD",
"IMPES",
"IMPLICIT",
"IMPORT",
"IMPTVD",
"IMSPCVD",
"INSPEC",
"INTPC",
"IONROCK",
"IONXROCK",
"IONXSURF",
"ISOLNUM",
"JFUNCR",
"KRNUM",
"KRNUMMF",
"LANGMPL",
"LANGMUIR",
"LANGSOLV",
"LCUNIT",
"LGR",
"LGRCOPY",
"LGRFREE",
"LGRLOCK",
"LGROFF",
"LGRON",
"LICENSES",
"LINCOM",
"LINKPERM",
"LKRO",
"LKRORG",
"LKRORW",
"LKRW",
"LKRWR",
"LOAD",
"LOWSALT",
"LPCW",
"LSALTFNC",
"LSLTWNUM",
"LSNUM",
"LSOGCR",
"LSOWCR",
"LSWCR",
"LSWL",
"LSWLPC",
"LSWU",
"LTOSIGMA",
"LWKRO",
"LWKRORG",
"LWKRORW",
"LWKRW",
"LWKRWR",
"LWPCW",
"LWSLTNUM",
"LWSNUM",
"LWSOGCR",
"LWSOWCR",
"LWSWCR",
"LWSWL",
"LWSWLPC",
"LWSWU",
"LX",
"LXFIN",
"LY",
"LYFIN",
"LZ",
"LZFIN",
"MAPUNITS",
"MASSFLOW",
"MATCORR",
"MEMORY",
"MESSAGE",
"MESSOPTS",
"MESSSRVC",
"MINNNCT",
"MINPORV",
"MLANG",
"MLANGSLV",
"MONITOR",
"MPFANUM",
"MPFNNC",
"MSGFILE",
"MULSGGD",
"MULSGGDV",
"MULTOUTS",
"MULTREAL",
"MULTREGD",
"MULTREGH",
"MULTSIG",
"MULTSIGV",
"MULT_XYZ",
"NARROW",
"NCONSUMP",
"NEFAC",
"NETBALAN",
"NETCOMPA",
"NETWORK",
"NEXT",
"NEXTSTEP",
"NEXTSTPL",
"NINENUM",
"NINEPOIN",
"NMATOPTS",
"NMATRIX",
"NODPPM",
"NOECHO",
"NOHMD",
"NOHMO",
"NOHYST",
"NOWARNEP",
"NRSOUT",
"NNEWTF",
"NOCASC",
"NODEPROP",
"NOGGF",
"NOINSPEC",
"NLINEARS",
"NOMONITO",
"NONNC",
"NORSSPEC",
"NOWARN",
"NSTACK",
"NUMRES",
"NWATREM",
"NXFIN",
"NYFIN",
"NZFIN",
"OFM",
"OILAPI",
"OLDTRAN",
"OLDTRANR",
"OPTIONS",
"OUTSOL",
"PARAOPTS",
"PCG32D",
"PCW32D",
"PERMJFUN",
"PETOPTS",
"PLYESAL",
"PLYKRRF",
"PLYOPTS",
"PLYRMDEN",
"PLYROCKM",
"PLYTRRF",
"PLYTRRFA",
"PLYVISCS",
"PLYVISCT",
"PLYVSCST",
"PVZG",
"PMAX",
"PRIORITY",
"PSTEADY",
"PSWRG",
"PSWRO",
"PVCO",
"PVZG",
"QDRILL",
"QDRILL",
"QHRATING",
"QMOBIL",
"PARALLEL",
"PARTTRAC",
"PBUB",
"PCG",
"PCW",
"PDEW",
"PEBI",
"PECOEFS",
"PEDIMS",
"PEGTABX",
"PEKTABX",
"PENUM",
"PERMAVE",
"PERMFACT",
"PERMXY",
"PERMYZ",
"PERMZX",
"PETGRID",
"PICOND",
"PIMULTAB",
"PINCHNUM",
"PINCHOUT",
"PINCHREG",
"PINCHXY",
"PLYADSS",
"PLYATEMP",
"PLYCAMAX",
"PLYDHFLF",
"PPCWMAX",
"PRECSALT",
"PRORDER",
"PRVD",
"PVTGW",
"PVTGWO",
"RAINFALL",
"RBEDCONT",
"RADFIN",
"RADFIN4",
"RADIAL",
"RCMASTS",
"REACACT",
"REACHES",
"READDATA",
"RESIDNUM",
"RESVNUMS",
"RIVDEBUG",
"RIVRXSEC",
"RIVERSYS",
"RIVRDIMS",
"RIVRPROP",
"RIVRXSE",
"RIVSALT",
"RIVTRACE",
"ROCKFRAC",
"ROCKPAMA",
"ROCKTAB",
"ROCKTABH",
"ROCKTABW",
"ROCKTHSG",
"ROCKTSIG",
"ROCKV",
"RPTCPL",
"RPTGRIDL",
"RPTHM",
"RPTHMG",
"RPTHMD",
"RPTHMW",
"RPTINIT",
"RPTISOL",
"RPTPROPS",
"RPTREGS",
"RSGI",
"RSSPE",
"RSSSPEC",
"RVCONS",
"RVCONSTT",
"RVGI",
"REFINE",
"RADFIN4",
"RHO",
"RKTRMDIR",
"ROCKOPTS",
"ROCKTAB",
"RPTGRID",
"RPTONLY",
"RPTONLYO",
"RPTPROS",
"PRTRST",
"RPTRUNSP",
"RPTSMRY",
"RPTSOL",
"RSCONST",
"RSCONSTT",
"RSSPEC",
"RTEMPA",
"RWGSALT",
"SALTPVD",
"SALTSOL",
"SAMG",
"SAVE",
"SKIP",
"SKIP100",
"SKIP300",
"SUMTHIN",
"SALT",
"SALTNODE",
"SALTREST",
"SCALELIM",
"SCDATAB",
"SCDETAB",
"SCDPTAB",
"SCDPTRAC",
"SCDPDIMS",
"SCVD",
"SEPVALS",
"SFOAM",
"SGF32D",
"SIGMA",
"SIGMAGD",
"SIGMAGDV",
"SIGMATH",
"SIGMAV",
"SIMULATE",
"SKRO",
"SKRORG",
"SKRORW",
"SKRW",
"SKRWR",
"SLAVES",
"SMULTX",
"SMULTY",
"SMULTZ",
"SOCRS",
"SOF32D",
"SOLVCONC",
"SOLVDIMS",
"SOLVDIRS",
"SOLVFRAC",
"SOLVNUM",
"SOLWNUM",
"SOMGAS",
"SOMWAT",
"SSGCR",
"SSGL",
"SSOGCR",
"SSOWCR",
"SSWCR",
"SSWL",
"SSWU",
"STOG",
"STOW",
"STWG",
"SURF",
"SURFACT",
"SURFACTW",
"SURFADDW",
"SURFADS",
"SURFCAPD",
"SURFESAL",
"SURFNUM",
"SURFOPTS",
"SURFROCK",
"SURFST",
"SURFSTES",
"SURFVISC",
"SURFWNUM",
"SWF32D",
"SWINGFAC"
"TEMP",
"TEMPNODE",
"TEMPTVD",
"TEMPVD",
"TIGHTEN",
"TIGHTENP",
"TIME",
"TNUM",
"TPAMEPS",
"TPAMEPSS",
"TRACERKM",
"TRACERKP",
"TRACITVD",
"TRACTVD",
"TRACER",
"TRACERS",
"TRACITVD",
"TRADS",
"TRANGL",
"TRANR",
"TRANTHT",
"TRDCY",
"TRDIF",
"TRDIS",
"TRKPF",
"TRNHD",
"TRPLPORO",
"TRROCK",
"TUNINGDP",
"TUNINGH",
"TUNINGL",
"TUNINGS",
"TVDP",
"TZONE",
"UDT",
"UDTDIMS",
"UNCODHMD",
"UNIFOUTS",
"UNIFSAVE",
"USECUPL",
"USEFLUX",
"USENOFLO",
"VAPWAT",
"VDFLOW",
"VDFLOWR",
"VE",
"VEDEBUG",
"VEFIN",
"VEFRAC",
"VEFRACP",
"VEFRACPV",
"VEFRACV",
"VFPCHK",
"VFPTABL",
"VISAGE",
"VISCD",
"VISDATES",
"VISOPTS",
"WAGHYSTR",
"WAITBAL",
"WALKALIN",
"WALQCALC",
"WAPI",
"WARN",
"WBHGLR",
"WBOREVOL",
"WCALCVAL",
"WBP",
"WBP4",
"WBP5",
"WBP9",
"WCONINJ",
"WCONINJP",
"WCUTBACK",
"WCUTBACT",
"WCYCLE",
"WDFACCOR",
"WDFAC",
"WDRILTIM",
"WDRILPRI",
"WDRILRES",
"WECONINJ",
"WECONT",
"WELCNTL",
"WELDEBUG",
"WELDRAW",
"WELEVNT",
"WELMOVEL"
"WELOPENL"
"WELPRI",
"WELSOMIN",
"WELSPECL",
"WFRICSEG",
"WFRICSGL",
"WFRICTN",
"WFRICTNL",
"WGASPROD",
"WGORPEN",
"WH2NUM",
"WH3NUM",
"WHEDREFD",
"WHTEMP",
"WINJMULT",
"WLIMTOL",
"WLIFT",
"WLISTARG",
"WLISTNAM",
"WLISTOPT",
"WNETCTRL",
"WNETDP",
"WORKLIM",
"WORKTHP",
"WPAVE",
"WPIMULTL",
"WPITAB",
"WPLUG",
"WPOLYRED",
"WPOTCALC",
"WREGROUP",
"WSCCLEAN",
"WSCCLENL",
"WSCTAB",
"WSEGDFIN",
"WSEGDFMD",
"WSEGDFPA",
"WSEGEXSS",
"WSEGFLIM",
"WSEGFMOD",
"WSEGINIT",
"WSEGITER",
"WSEGLABY",
"WSEGLINK",
"WSEGMULT",
"WSEGPROP",
"WSEGPULL",
"WSEGSEP",
"WSEGSOLV",
"WSEGTABL",
"WSURFACT",
"WTADD",
"WTEMPQ",
"WTHPMAX",
"WTMULT",
"WVFPDP",
"WVFPEXP",
"WWPAVE",
"ZIPPY2",
"ZIPP2OFF"};
std::multimap<std::string, PartiallySupported<std::string> > string_options;
std::multimap<std::string, PartiallySupported<int> > int_options;
addSupported<ParserKeywords::COMPORD, ParserKeywords::COMPORD::ORDER_TYPE, std::string>(string_options , "INPUT");
addSupported<ParserKeywords::ENDSCALE, ParserKeywords::ENDSCALE::DIRECT, std::string>(string_options, "NODIR");
addSupported<ParserKeywords::ENDSCALE, ParserKeywords::ENDSCALE::IRREVERS, std::string>(string_options, "REVER");
addSupported<ParserKeywords::PINCH, ParserKeywords::PINCH::CONTROL_OPTION, std::string>(string_options, "GAP");
addSupported<ParserKeywords::PINCH, ParserKeywords::PINCH::PINCHOUT_OPTION, std::string>(string_options, "TOPBOT");
addSupported<ParserKeywords::EHYSTR, ParserKeywords::EHYSTR::relative_perm_hyst, int>(int_options , 0);
// check deck and keyword for flow and parser.
for (size_t idx = 0; idx < deck.size(); ++idx) {
const auto& keyword = deck.getKeyword(idx);
std::unordered_set<std::string>::const_iterator it;
it = unsupported_keywords.find(keyword.name());
if (it != unsupported_keywords.end()) {
std::string msg_fmt = "Keyword {keyword} is not supported by flow.\n"
"In {file} line {line}.";
parseContext.handleError(ParseContext::SIMULATOR_KEYWORD_NOT_SUPPORTED, msg_fmt, keyword.location(), errorGuard);
}
checkOptions<std::string>(keyword, string_options, parseContext, errorGuard);
checkOptions<int>(keyword, int_options, parseContext, errorGuard);
}
}
} // namespace MissingFeatures
} // namespace Opm

View File

@ -1,58 +0,0 @@
/*
Copyright 2016 Statoil ASA.
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_MISSINGFEATURES_HEADER_INCLUDED
#define OPM_MISSINGFEATURES_HEADER_INCLUDED
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <string>
#include <map>
namespace Opm {
class ErrorGuard;
class ParseContext;
namespace MissingFeatures {
template <typename T>
struct PartiallySupported {
std::string item;
T item_value;
};
template <typename Keyword, typename Item, typename T>
void addSupported(std::multimap<std::string, PartiallySupported<T> >& map, T itemValue);
template <typename T>
void checkOptions(const DeckKeyword& keyword, std::multimap<std::string , PartiallySupported<T> >& map, const ParseContext& parseContext, ErrorGuard& errorGuard);
void checkKeywords(const Deck& deck, const ParseContext& parseContext, ErrorGuard& errorGuard);
template<typename T>
void checkKeywords(const Deck& deck, const ParseContext& parseContext, T&& errorGuard);
void checkKeywords(const Deck& deck);
}
}
#endif // OPM_MISSINGFEATURES_HEADER_INCLUDED

View File

@ -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/>.
*/
#ifndef OPM_PARTIALLYSUPPORTEDFLOWKEYWORDS_HEADER_INCLUDED
#define OPM_PARTIALLYSUPPORTEDFLOWKEYWORDS_HEADER_INCLUDED
#include <map>
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include <opm/simulators/flow/KeywordValidation.hpp>
/*
Here keywords are defined that are supported by flow, but have items that
are only partially supported.
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.
permitted_values (vector of strings) : the list of values that is allowed.
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.
*/
namespace Opm::FlowKeywordValidation
{
const Opm::KeywordValidation::PartiallySupportedKeywords<std::string> partially_supported_keywords_strings = {
{
"COMPORD",
{
{2, {false, {"INPUT"}, std::nullopt}}, // ORDER_TYPE
},
},
{
"ENDSCALE",
{
{1, {false, {"NODIR"}, std::nullopt}}, // DIRECT
{2, {false, {"REVERS"}, std::nullopt}}, // IRREVERS
},
},
{
"PINCH",
{
{2, {false, {"GAP"}, std::nullopt}}, // GAP
{4, {false, {"TOPBOT"}, std::nullopt}}, // PINCHOUT_OPTION
},
},
};
const Opm::KeywordValidation::PartiallySupportedKeywords<int> partially_supported_keywords_int = {
{
"EHYSTR",
{
{2, {false, {0}, std::nullopt}}, //relative_perm_hyst
},
},
};
} // namespace Opm::FlowKeywordValidation
#endif

View File

@ -0,0 +1,825 @@
/*
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/>.
*/
#ifndef OPM_UNSUPPORTEDFLOWKEYWORDS_HEADER_INCLUDED
#define OPM_UNSUPPORTEDFLOWKEYWORDS_HEADER_INCLUDED
#include <map>
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include <opm/simulators/flow/KeywordValidation.hpp>
/*
Here the keywords are defined that are not suppored by flow. When parsing
the deck, unsupported keywords will be flagged and reported. It is possible
to mark a keyword as 'critical'. In this case an error will be raised and
flow will not proceed when it encounters this keyword.
The unsupported keywords are specified by a mapping from the keyword name to
a struct with properties of that keyword. The struct is defined in
KeywordValidation.hpp and contains the following fields:
critical (bool) : set to true if the keywords is considered critical.
message (optional string): set to an optional message string that is added
to the error.
Below is the std::map with the keywords that are not supported by flow.
Most entries in the map below are not critical ('false') and do not have an
additional message. Set the first entry to 'true' to make a keyword
critical. A message can be added by replacing std::nullopt by a string
literal.
*/
namespace Opm::FlowKeywordValidation
{
const Opm::KeywordValidation::UnsupportedKeywords unsupported_keywords = {
{"ACTION", {false, std::nullopt}},
{"ACTIONG", {false, std::nullopt}},
{"ACTIONR", {false, std::nullopt}},
{"ACTIONS", {false, std::nullopt}},
{"ACTIONW", {false, std::nullopt}},
{"ACTPARAM", {false, std::nullopt}},
{"ADSALNOD", {false, std::nullopt}},
{"ADDZCORN", {false, std::nullopt}},
{"ADSORP", {false, std::nullopt}},
{"AITS", {false, std::nullopt}},
{"AITSOFF", {false, std::nullopt}},
{"ALKADS", {false, std::nullopt}},
{"ALKALINE", {false, std::nullopt}},
{"ALKROCK", {false, std::nullopt}},
{"API", {false, std::nullopt}},
{"ALPOLADS", {false, std::nullopt}},
{"ALSURFAD", {false, std::nullopt}},
{"ALSURFST", {false, std::nullopt}},
{"AMALGAM", {false, std::nullopt}},
{"APIGROUP", {false, std::nullopt}},
{"APILIM", {false, std::nullopt}},
{"APIVD", {false, std::nullopt}},
{"AQANCONL", {false, std::nullopt}},
{"AQANNC", {false, std::nullopt}},
{"AQANTRC", {false, std::nullopt}},
{"AQUALIST", {false, std::nullopt}},
{"AQUCHGAS", {false, std::nullopt}},
{"AQUCHWAT", {false, std::nullopt}},
{"AQUCON", {false, std::nullopt}},
{"AQUCWFAC", {false, std::nullopt}},
{"AQUFET", {false, std::nullopt}},
{"AQUFLUX", {false, std::nullopt}},
{"AQUNNC", {false, std::nullopt}},
{"AQUNUM", {false, std::nullopt}},
{"AUTOCOAR", {false, std::nullopt}},
{"AUTOREF", {false, std::nullopt}},
{"BIGMODEL", {false, std::nullopt}},
{"BDENSITY", {false, std::nullopt}},
{"BGGI", {false, std::nullopt}},
{"BOGI", {false, std::nullopt}},
{"BOUNDARY", {false, std::nullopt}},
{"BPARA", {false, std::nullopt}},
{"BPIDIMS", {false, std::nullopt}},
{"BRANPROP", {false, std::nullopt}},
{"BTOBALFA", {false, std::nullopt}},
{"BTOBALFV", {false, std::nullopt}},
{"CALTRAC", {false, std::nullopt}},
{"CARFIN", {false, std::nullopt}},
{"CART", {false, std::nullopt}},
{"CBMOPTS", {false, std::nullopt}},
{"CECON", {false, std::nullopt}},
{"CECONT", {false, std::nullopt}},
{"COAL", {false, std::nullopt}},
{"COALADS", {false, std::nullopt}},
{"COALNUM", {false, std::nullopt}},
{"COALPP", {false, std::nullopt}},
{"COARSEN", {false, std::nullopt}},
{"COLLAPSE", {false, std::nullopt}},
{"COLUMNS", {false, std::nullopt}},
{"CBMOPTS", {false, std::nullopt}},
{"COMPDATX", {false, std::nullopt}},
{"COMPDATL", {false, std::nullopt}},
{"COMPDATM", {false, std::nullopt}},
{"COMPDATL", {false, std::nullopt}},
{"COMPIMB", {false, std::nullopt}},
{"COMPFLSH", {false, std::nullopt}},
{"COMPINJK", {false, std::nullopt}},
{"COMPLMPL", {false, std::nullopt}},
{"COMPOFF", {false, std::nullopt}},
{"COMPRIV", {false, std::nullopt}},
{"COMPRP", {false, std::nullopt}},
{"COMPRPL", {false, std::nullopt}},
{"COMPSEGL", {false, std::nullopt}},
{"COMPVE", {false, std::nullopt}},
{"COMPVEL", {false, std::nullopt}},
{"CPIFACT", {false, std::nullopt}},
{"CPIFACTL", {false, std::nullopt}},
{"CPR", {false, std::nullopt}},
{"CSKIN", {false, std::nullopt}},
{"CONNECTION", {false, std::nullopt}},
{"CONNECTION_PROBE", {false, std::nullopt}},
{"COORDSYS", {false, std::nullopt}},
{"COPYBOX", {false, std::nullopt}},
{"COPYREG", {false, std::nullopt}},
{"CRITPERM", {false, std::nullopt}},
{"DATUMR", {false, std::nullopt}},
{"DATUMRX", {false, std::nullopt}},
{"DCQDEFN", {false, std::nullopt}},
{"DEBUG", {false, std::nullopt}},
{"DELAYACT", {false, std::nullopt}},
{"DEPTHTAB", {false, std::nullopt}},
{"DIAGDISP", {false, std::nullopt}},
{"DIFF", {false, std::nullopt}},
{"DIFFC", {false, std::nullopt}},
{"DIFFCOAL", {false, std::nullopt}},
{"DIFFDP", {false, std::nullopt}},
{"DIFFMMF", {false, std::nullopt}},
{"DIFFMR", {false, std::nullopt}},
{"DIFFMR-", {false, std::nullopt}},
{"DIFFMTHT", {false, std::nullopt}},
{"DIFFMTH-", {false, std::nullopt}},
{"DIFFMX", {false, std::nullopt}},
{"DIFFMX-", {false, std::nullopt}},
{"DIFFMY", {false, std::nullopt}},
{"DIFFMY-", {false, std::nullopt}},
{"DIFFMZ", {false, std::nullopt}},
{"DIFFMZ-", {false, std::nullopt}},
{"DIFFR", {false, std::nullopt}},
{"DIFFTHT", {false, std::nullopt}},
{"DIFFUSE", {false, std::nullopt}},
{"DIFFX", {false, std::nullopt}},
{"DIFFY", {false, std::nullopt}},
{"DIFFZ", {false, std::nullopt}},
{"DIMPES", {false, std::nullopt}},
{"DIMPLICT", {false, std::nullopt}},
{"DISPDIMS", {false, std::nullopt}},
{"DISPERSE", {false, std::nullopt}},
{"DOMAINS", {false, std::nullopt}},
{"DPGRID", {false, std::nullopt}},
{"DPKRMOD", {false, std::nullopt}},
{"DPNUM", {false, std::nullopt}},
{"DRILPRI", {false, std::nullopt}},
{"DSPDEINT", {false, std::nullopt}},
{"DUALPERM", {false, std::nullopt}},
{"DUALPORO", {false, std::nullopt}},
{"DUMPCUPL", {false, std::nullopt}},
{"DUMPFLUX", {false, std::nullopt}},
{"DYNAMICR", {false, std::nullopt}},
{"DYNRDIMS", {false, std::nullopt}},
{"DYNAMICR", {false, std::nullopt}},
{"DZMATRIX", {false, std::nullopt}},
{"DZMTRX", {false, std::nullopt}},
{"DZMTRXV", {false, std::nullopt}},
{"DZNET", {false, std::nullopt}},
{"ECHO", {false, std::nullopt}},
{"ECLMC", {false, std::nullopt}},
{"EDITNNCR", {false, std::nullopt}},
{"EHYSTRR", {false, std::nullopt}},
{"ENDDYN", {false, std::nullopt}},
{"ENDFIN", {false, std::nullopt}},
{"ENDNUM", {false, std::nullopt}},
{"ENDSKIP", {false, std::nullopt}},
{"ENKRVD", {false, std::nullopt}},
{"ENKSRVD", {false, std::nullopt}},
{"ENPCVD", {false, std::nullopt}},
{"ENPTVD", {false, std::nullopt}},
{"ENSPCVD", {false, std::nullopt}},
{"EPSDBGS", {false, std::nullopt}},
{"EPSDEBUG", {false, std::nullopt}},
{"EQLZCORN", {false, std::nullopt}},
{"EQUALREG", {false, std::nullopt}},
{"ESSNODE", {false, std::nullopt}},
{"EXCAVATE", {false, std::nullopt}},
{"EXCEL", {false, std::nullopt}},
{"EXTFIN", {false, std::nullopt}},
{"EXTHOST", {false, std::nullopt}},
{"EXTRAPMS", {false, std::nullopt}},
{"EXTREPGL", {false, std::nullopt}},
{"FBHPDEF", {false, std::nullopt}},
{"FHERCHBL", {false, std::nullopt}},
{"FRICTION", {false, std::nullopt}},
{"FIPSEP", {false, std::nullopt}},
{"FLUXREG", {false, std::nullopt}},
{"FLUXTYPE", {false, std::nullopt}},
{"FMTHMD", {false, std::nullopt}},
{"FOAMDCYO", {false, std::nullopt}},
{"FOAMDCYW", {false, std::nullopt}},
{"FOAMFCN", {false, std::nullopt}},
{"FOAMFRM", {false, std::nullopt}},
{"FOAMFSO", {false, std::nullopt}},
{"FOAMFST", {false, std::nullopt}},
{"FOAMFSW", {false, std::nullopt}},
{"FOAMMOBP", {false, std::nullopt}},
{"FOAMMOBS", {false, std::nullopt}},
{"FORMFEED", {false, std::nullopt}},
{"FULLIMP", {false, std::nullopt}},
{"GEGONT", {false, std::nullopt}},
{"GETDATA", {false, std::nullopt}},
{"GASBEGIN", {false, std::nullopt}},
{"GASCONC", {false, std::nullopt}},
{"GASEND", {false, std::nullopt}},
{"GASFCOMP", {false, std::nullopt}},
{"GASFDECR", {false, std::nullopt}},
{"GASFDELC", {false, std::nullopt}},
{"GASFIELD", {false, std::nullopt}},
{"GASFTARG", {false, std::nullopt}},
{"GASMONTH", {false, std::nullopt}},
{"GASPERIO", {false, std::nullopt}},
{"GASSATC", {false, std::nullopt}},
{"GASYEAR", {false, std::nullopt}},
{"GCALECON", {false, std::nullopt}},
{"GCONCAL", {false, std::nullopt}},
{"GCONENG", {false, std::nullopt}},
{"GCONPRI", {false, std::nullopt}},
{"GCONTOL", {false, std::nullopt}},
{"GCUTBACK", {false, std::nullopt}},
{"GCUTBACT", {false, std::nullopt}},
{"GCVD", {false, std::nullopt}},
{"GDCQ", {false, std::nullopt}},
{"GDCQECON", {false, std::nullopt}},
{"GDIMS", {false, std::nullopt}},
{"GDORIENT", {false, std::nullopt}},
{"GDRILPOT", {false, std::nullopt}},
{"GECON", {false, std::nullopt}},
{"GECONT", {false, std::nullopt}},
{"GETGLOB", {false, std::nullopt}},
{"GI", {false, std::nullopt}},
{"GIALL", {false, std::nullopt}},
{"GIMODEL", {false, std::nullopt}},
{"GINODE", {false, std::nullopt}},
{"GLIFTLIM", {false, std::nullopt}},
{"GLIFTOPT", {false, std::nullopt}},
{"GNETDP", {false, std::nullopt}},
{"GNETINJE", {false, std::nullopt}},
{"GNETPUMP", {false, std::nullopt}},
{"GPMAINT", {false, std::nullopt}},
{"GRADGRUP", {false, std::nullopt}},
{"GRADRESV", {false, std::nullopt}},
{"GRADRFT", {false, std::nullopt}},
{"GRADWELL", {false, std::nullopt}},
{"GRAVCONS", {false, std::nullopt}},
{"GRAVDR", {false, std::nullopt}},
{"GRAVDRB", {false, std::nullopt}},
{"GRAVDRM", {false, std::nullopt}},
{"GRDREACH", {false, std::nullopt}},
{"GRIDUNIT", {false, std::nullopt}},
{"GRUPMAST", {false, std::nullopt}},
{"GRUPNET", {false, std::nullopt}},
{"GRUPRIG", {false, std::nullopt}},
{"GRUPSLAV", {false, std::nullopt}},
{"GRUPTARG", {false, std::nullopt}},
{"GSATINJE", {false, std::nullopt}},
{"GSEPCOND", {false, std::nullopt}},
{"GSSCPTST", {false, std::nullopt}},
{"GSWINGF", {false, std::nullopt}},
{"GTADD", {false, std::nullopt}},
{"GTMULT", {false, std::nullopt}},
{"GUIDECAL", {false, std::nullopt}},
{"GSATPROD", {false, std::nullopt}},
{"GUPFREQ", {false, std::nullopt}},
{"GWRTWCV", {false, std::nullopt}},
{"HALFTRAN", {false, std::nullopt}},
{"HAxxxxxx", {false, std::nullopt}},
{"HBNUM", {false, std::nullopt}},
{"HDISP", {false, std::nullopt}},
{"HMAQUCT", {false, std::nullopt}},
{"HMAQUFET", {false, std::nullopt}},
{"HMAQUNUM", {false, std::nullopt}},
{"HMDIMS", {false, std::nullopt}},
{"HMFAULTS", {false, std::nullopt}},
{"HMMLAQUN", {false, std::nullopt}},
{"HMMLCTAQ", {false, std::nullopt}},
{"HMMLFTAQ", {false, std::nullopt}},
{"HMMLTWCN", {false, std::nullopt}},
{"HMMULTxx", {false, std::nullopt}},
{"HMMULTFT", {false, std::nullopt}},
{"HMMULTSG", {false, std::nullopt}},
{"HMPROPS", {false, std::nullopt}},
{"HMROCK", {false, std::nullopt}},
{"HMROCKT", {false, std::nullopt}},
{"HMRREF", {false, std::nullopt}},
{"HMWELCON", {false, std::nullopt}},
{"HMWPIMLT", {false, std::nullopt}},
{"HMxxxxxx", {false, std::nullopt}},
{"HRFIN", {false, std::nullopt}},
{"HWKRO", {false, std::nullopt}},
{"HWKRORG", {false, std::nullopt}},
{"HWKRORW", {false, std::nullopt}},
{"HWKRW", {false, std::nullopt}},
{"HWKRWR", {false, std::nullopt}},
{"HWPCW", {false, std::nullopt}},
{"HWSNUM", {false, std::nullopt}},
{"HWSOGCR", {false, std::nullopt}},
{"HWSOWCR", {false, std::nullopt}},
{"HWSWCR", {false, std::nullopt}},
{"HWSWL", {false, std::nullopt}},
{"HWSWLPC", {false, std::nullopt}},
{"HWSWU", {false, std::nullopt}},
{"HXFIN", {false, std::nullopt}},
{"HYDRHEAD", {false, std::nullopt}},
{"HYFIN", {false, std::nullopt}},
{"HYMOBGDR", {false, std::nullopt}},
{"HYST", {false, std::nullopt}},
{"HYSTCHCK", {false, std::nullopt}},
{"HZFIN", {false, std::nullopt}},
{"IHOST", {false, std::nullopt}},
{"IMBNUMMF", {false, std::nullopt}},
{"IMKRVD", {false, std::nullopt}},
{"IMPCVD", {false, std::nullopt}},
{"IMPES", {false, std::nullopt}},
{"IMPLICIT", {false, std::nullopt}},
{"IMPORT", {false, std::nullopt}},
{"IMPTVD", {false, std::nullopt}},
{"IMSPCVD", {false, std::nullopt}},
{"INSPEC", {false, std::nullopt}},
{"INTPC", {false, std::nullopt}},
{"IONROCK", {false, std::nullopt}},
{"IONXROCK", {false, std::nullopt}},
{"IONXSURF", {false, std::nullopt}},
{"ISOLNUM", {false, std::nullopt}},
{"JFUNCR", {false, std::nullopt}},
{"KRNUM", {false, std::nullopt}},
{"KRNUMMF", {false, std::nullopt}},
{"LANGMPL", {false, std::nullopt}},
{"LANGMUIR", {false, std::nullopt}},
{"LANGSOLV", {false, std::nullopt}},
{"LCUNIT", {false, std::nullopt}},
{"LGR", {false, std::nullopt}},
{"LGRCOPY", {false, std::nullopt}},
{"LGRFREE", {false, std::nullopt}},
{"LGRLOCK", {false, std::nullopt}},
{"LGROFF", {false, std::nullopt}},
{"LGRON", {false, std::nullopt}},
{"LICENSES", {false, std::nullopt}},
{"LINCOM", {false, std::nullopt}},
{"LINKPERM", {false, std::nullopt}},
{"LKRO", {false, std::nullopt}},
{"LKRORG", {false, std::nullopt}},
{"LKRORW", {false, std::nullopt}},
{"LKRW", {false, std::nullopt}},
{"LKRWR", {false, std::nullopt}},
{"LOAD", {false, std::nullopt}},
{"LOWSALT", {false, std::nullopt}},
{"LPCW", {false, std::nullopt}},
{"LSALTFNC", {false, std::nullopt}},
{"LSLTWNUM", {false, std::nullopt}},
{"LSNUM", {false, std::nullopt}},
{"LSOGCR", {false, std::nullopt}},
{"LSOWCR", {false, std::nullopt}},
{"LSWCR", {false, std::nullopt}},
{"LSWL", {false, std::nullopt}},
{"LSWLPC", {false, std::nullopt}},
{"LSWU", {false, std::nullopt}},
{"LTOSIGMA", {false, std::nullopt}},
{"LWKRO", {false, std::nullopt}},
{"LWKRORG", {false, std::nullopt}},
{"LWKRORW", {false, std::nullopt}},
{"LWKRW", {false, std::nullopt}},
{"LWKRWR", {false, std::nullopt}},
{"LWPCW", {false, std::nullopt}},
{"LWSLTNUM", {false, std::nullopt}},
{"LWSNUM", {false, std::nullopt}},
{"LWSOGCR", {false, std::nullopt}},
{"LWSOWCR", {false, std::nullopt}},
{"LWSWCR", {false, std::nullopt}},
{"LWSWL", {false, std::nullopt}},
{"LWSWLPC", {false, std::nullopt}},
{"LWSWU", {false, std::nullopt}},
{"LX", {false, std::nullopt}},
{"LXFIN", {false, std::nullopt}},
{"LY", {false, std::nullopt}},
{"LYFIN", {false, std::nullopt}},
{"LZ", {false, std::nullopt}},
{"LZFIN", {false, std::nullopt}},
{"MAPUNITS", {false, std::nullopt}},
{"MASSFLOW", {false, std::nullopt}},
{"MATCORR", {false, std::nullopt}},
{"MEMORY", {false, std::nullopt}},
{"MESSAGE", {false, std::nullopt}},
{"MESSOPTS", {false, std::nullopt}},
{"MESSSRVC", {false, std::nullopt}},
{"MINNNCT", {false, std::nullopt}},
{"MINPORV", {false, std::nullopt}},
{"MLANG", {false, std::nullopt}},
{"MLANGSLV", {false, std::nullopt}},
{"MONITOR", {false, std::nullopt}},
{"MPFANUM", {false, std::nullopt}},
{"MPFNNC", {false, std::nullopt}},
{"MSGFILE", {false, std::nullopt}},
{"MULSGGD", {false, std::nullopt}},
{"MULSGGDV", {false, std::nullopt}},
{"MULTOUTS", {false, std::nullopt}},
{"MULTREAL", {false, std::nullopt}},
{"MULTREGD", {false, std::nullopt}},
{"MULTREGH", {false, std::nullopt}},
{"MULTSIG", {false, std::nullopt}},
{"MULTSIGV", {false, std::nullopt}},
{"MULT_XYZ", {false, std::nullopt}},
{"NARROW", {false, std::nullopt}},
{"NCONSUMP", {false, std::nullopt}},
{"NEFAC", {false, std::nullopt}},
{"NETBALAN", {false, std::nullopt}},
{"NETCOMPA", {false, std::nullopt}},
{"NETWORK", {false, std::nullopt}},
{"NEXT", {false, std::nullopt}},
{"NEXTSTEP", {false, std::nullopt}},
{"NEXTSTPL", {false, std::nullopt}},
{"NINENUM", {false, std::nullopt}},
{"NINEPOIN", {false, std::nullopt}},
{"NMATOPTS", {false, std::nullopt}},
{"NMATRIX", {false, std::nullopt}},
{"NODPPM", {false, std::nullopt}},
{"NOECHO", {false, std::nullopt}},
{"NOHMD", {false, std::nullopt}},
{"NOHMO", {false, std::nullopt}},
{"NOHYST", {false, std::nullopt}},
{"NOWARNEP", {false, std::nullopt}},
{"NRSOUT", {false, std::nullopt}},
{"NNEWTF", {false, std::nullopt}},
{"NOCASC", {false, std::nullopt}},
{"NODEPROP", {false, std::nullopt}},
{"NOGGF", {false, std::nullopt}},
{"NOINSPEC", {false, std::nullopt}},
{"NLINEARS", {false, std::nullopt}},
{"NOMONITO", {false, std::nullopt}},
{"NONNC", {false, std::nullopt}},
{"NORSSPEC", {false, std::nullopt}},
{"NOWARN", {false, std::nullopt}},
{"NSTACK", {false, std::nullopt}},
{"NUMRES", {false, std::nullopt}},
{"NWATREM", {false, std::nullopt}},
{"NXFIN", {false, std::nullopt}},
{"NYFIN", {false, std::nullopt}},
{"NZFIN", {false, std::nullopt}},
{"OFM", {false, std::nullopt}},
{"OILAPI", {false, std::nullopt}},
{"OLDTRAN", {false, std::nullopt}},
{"OLDTRANR", {false, std::nullopt}},
{"OPTIONS", {false, std::nullopt}},
{"OUTSOL", {false, std::nullopt}},
{"PARAOPTS", {false, std::nullopt}},
{"PCG32D", {false, std::nullopt}},
{"PCW32D", {false, std::nullopt}},
{"PERMJFUN", {false, std::nullopt}},
{"PETOPTS", {false, std::nullopt}},
{"PLYESAL", {false, std::nullopt}},
{"PLYKRRF", {false, std::nullopt}},
{"PLYOPTS", {false, std::nullopt}},
{"PLYRMDEN", {false, std::nullopt}},
{"PLYROCKM", {false, std::nullopt}},
{"PLYTRRF", {false, std::nullopt}},
{"PLYTRRFA", {false, std::nullopt}},
{"PLYVISCS", {false, std::nullopt}},
{"PLYVISCT", {false, std::nullopt}},
{"PLYVSCST", {false, std::nullopt}},
{"PVZG", {false, std::nullopt}},
{"PMAX", {false, std::nullopt}},
{"PRIORITY", {false, std::nullopt}},
{"PSTEADY", {false, std::nullopt}},
{"PSWRG", {false, std::nullopt}},
{"PSWRO", {false, std::nullopt}},
{"PVCO", {false, std::nullopt}},
{"PVZG", {false, std::nullopt}},
{"QDRILL", {false, std::nullopt}},
{"QDRILL", {false, std::nullopt}},
{"QHRATING", {false, std::nullopt}},
{"QMOBIL", {false, std::nullopt}},
{"PARALLEL", {false, std::nullopt}},
{"PARTTRAC", {false, std::nullopt}},
{"PBUB", {false, std::nullopt}},
{"PCG", {false, std::nullopt}},
{"PCW", {false, std::nullopt}},
{"PDEW", {false, std::nullopt}},
{"PEBI", {false, std::nullopt}},
{"PECOEFS", {false, std::nullopt}},
{"PEDIMS", {false, std::nullopt}},
{"PEGTABX", {false, std::nullopt}},
{"PEKTABX", {false, std::nullopt}},
{"PENUM", {false, std::nullopt}},
{"PERMAVE", {false, std::nullopt}},
{"PERMFACT", {false, std::nullopt}},
{"PERMXY", {false, std::nullopt}},
{"PERMYZ", {false, std::nullopt}},
{"PERMZX", {false, std::nullopt}},
{"PETGRID", {false, std::nullopt}},
{"PICOND", {false, std::nullopt}},
{"PIMULTAB", {false, std::nullopt}},
{"PINCHNUM", {false, std::nullopt}},
{"PINCHOUT", {false, std::nullopt}},
{"PINCHREG", {false, std::nullopt}},
{"PINCHXY", {false, std::nullopt}},
{"PLYADSS", {false, std::nullopt}},
{"PLYATEMP", {false, std::nullopt}},
{"PLYCAMAX", {false, std::nullopt}},
{"PLYDHFLF", {false, std::nullopt}},
{"PPCWMAX", {false, std::nullopt}},
{"PRECSALT", {false, std::nullopt}},
{"PRORDER", {false, std::nullopt}},
{"PRVD", {false, std::nullopt}},
{"PVTGW", {false, std::nullopt}},
{"PVTGWO", {false, std::nullopt}},
{"RAINFALL", {false, std::nullopt}},
{"RBEDCONT", {false, std::nullopt}},
{"RADFIN", {false, std::nullopt}},
{"RADFIN4", {false, std::nullopt}},
{"RADIAL", {false, std::nullopt}},
{"RCMASTS", {false, std::nullopt}},
{"REACACT", {false, std::nullopt}},
{"REACHES", {false, std::nullopt}},
{"READDATA", {false, std::nullopt}},
{"RESIDNUM", {false, std::nullopt}},
{"RESVNUMS", {false, std::nullopt}},
{"RIVDEBUG", {false, std::nullopt}},
{"RIVRXSEC", {false, std::nullopt}},
{"RIVERSYS", {false, std::nullopt}},
{"RIVRDIMS", {false, std::nullopt}},
{"RIVRPROP", {false, std::nullopt}},
{"RIVRXSE", {false, std::nullopt}},
{"RIVSALT", {false, std::nullopt}},
{"RIVTRACE", {false, std::nullopt}},
{"ROCKFRAC", {false, std::nullopt}},
{"ROCKPAMA", {false, std::nullopt}},
{"ROCKTAB", {false, std::nullopt}},
{"ROCKTABH", {false, std::nullopt}},
{"ROCKTABW", {false, std::nullopt}},
{"ROCKTHSG", {false, std::nullopt}},
{"ROCKTSIG", {false, std::nullopt}},
{"ROCKV", {false, std::nullopt}},
{"RPTCPL", {false, std::nullopt}},
{"RPTGRIDL", {false, std::nullopt}},
{"RPTHM", {false, std::nullopt}},
{"RPTHMG", {false, std::nullopt}},
{"RPTHMD", {false, std::nullopt}},
{"RPTHMW", {false, std::nullopt}},
{"RPTINIT", {false, std::nullopt}},
{"RPTISOL", {false, std::nullopt}},
{"RPTPROPS", {false, std::nullopt}},
{"RPTREGS", {false, std::nullopt}},
{"RSGI", {false, std::nullopt}},
{"RSSPE", {false, std::nullopt}},
{"RSSSPEC", {false, std::nullopt}},
{"RVCONS", {false, std::nullopt}},
{"RVCONSTT", {false, std::nullopt}},
{"RVGI", {false, std::nullopt}},
{"REFINE", {false, std::nullopt}},
{"RADFIN4", {false, std::nullopt}},
{"RHO", {false, std::nullopt}},
{"RKTRMDIR", {false, std::nullopt}},
{"ROCKOPTS", {false, std::nullopt}},
{"ROCKTAB", {false, std::nullopt}},
{"RPTGRID", {false, std::nullopt}},
{"RPTONLY", {false, std::nullopt}},
{"RPTONLYO", {false, std::nullopt}},
{"RPTPROS", {false, std::nullopt}},
{"PRTRST", {false, std::nullopt}},
{"RPTRUNSP", {false, std::nullopt}},
{"RPTSMRY", {false, std::nullopt}},
{"RPTSOL", {false, std::nullopt}},
{"RSCONST", {false, std::nullopt}},
{"RSCONSTT", {false, std::nullopt}},
{"RSSPEC", {false, std::nullopt}},
{"RTEMPA", {false, std::nullopt}},
{"RWGSALT", {false, std::nullopt}},
{"SALTPVD", {false, std::nullopt}},
{"SALTSOL", {false, std::nullopt}},
{"SAMG", {false, std::nullopt}},
{"SAVE", {false, std::nullopt}},
{"SKIP", {false, std::nullopt}},
{"SKIP100", {false, std::nullopt}},
{"SKIP300", {false, std::nullopt}},
{"SUMTHIN", {false, std::nullopt}},
{"SALT", {false, std::nullopt}},
{"SALTNODE", {false, std::nullopt}},
{"SALTREST", {false, std::nullopt}},
{"SCALELIM", {false, std::nullopt}},
{"SCDATAB", {false, std::nullopt}},
{"SCDETAB", {false, std::nullopt}},
{"SCDPTAB", {false, std::nullopt}},
{"SCDPTRAC", {false, std::nullopt}},
{"SCDPDIMS", {false, std::nullopt}},
{"SCVD", {false, std::nullopt}},
{"SEPVALS", {false, std::nullopt}},
{"SFOAM", {false, std::nullopt}},
{"SGF32D", {false, std::nullopt}},
{"SIGMA", {false, std::nullopt}},
{"SIGMAGD", {false, std::nullopt}},
{"SIGMAGDV", {false, std::nullopt}},
{"SIGMATH", {false, std::nullopt}},
{"SIGMAV", {false, std::nullopt}},
{"SIMULATE", {false, std::nullopt}},
{"SKRO", {false, std::nullopt}},
{"SKRORG", {false, std::nullopt}},
{"SKRORW", {false, std::nullopt}},
{"SKRW", {false, std::nullopt}},
{"SKRWR", {false, std::nullopt}},
{"SLAVES", {false, std::nullopt}},
{"SMULTX", {false, std::nullopt}},
{"SMULTY", {false, std::nullopt}},
{"SMULTZ", {false, std::nullopt}},
{"SOCRS", {false, std::nullopt}},
{"SOF32D", {false, std::nullopt}},
{"SOLVCONC", {false, std::nullopt}},
{"SOLVDIMS", {false, std::nullopt}},
{"SOLVDIRS", {false, std::nullopt}},
{"SOLVFRAC", {false, std::nullopt}},
{"SOLVNUM", {false, std::nullopt}},
{"SOLWNUM", {false, std::nullopt}},
{"SOMGAS", {false, std::nullopt}},
{"SOMWAT", {false, std::nullopt}},
{"SSGCR", {false, std::nullopt}},
{"SSGL", {false, std::nullopt}},
{"SSOGCR", {false, std::nullopt}},
{"SSOWCR", {false, std::nullopt}},
{"SSWCR", {false, std::nullopt}},
{"SSWL", {false, std::nullopt}},
{"SSWU", {false, std::nullopt}},
{"STOG", {false, std::nullopt}},
{"STOW", {false, std::nullopt}},
{"STWG", {false, std::nullopt}},
{"SURF", {false, std::nullopt}},
{"SURFACT", {false, std::nullopt}},
{"SURFACTW", {false, std::nullopt}},
{"SURFADDW", {false, std::nullopt}},
{"SURFADS", {false, std::nullopt}},
{"SURFCAPD", {false, std::nullopt}},
{"SURFESAL", {false, std::nullopt}},
{"SURFNUM", {false, std::nullopt}},
{"SURFOPTS", {false, std::nullopt}},
{"SURFROCK", {false, std::nullopt}},
{"SURFST", {false, std::nullopt}},
{"SURFSTES", {false, std::nullopt}},
{"SURFVISC", {false, std::nullopt}},
{"SURFWNUM", {false, std::nullopt}},
{"SWF32D", {false, std::nullopt}},
{"SWINGFAC", {false, std::nullopt}},
{"TEMP", {false, std::nullopt}},
{"TEMPNODE", {false, std::nullopt}},
{"TEMPTVD", {false, std::nullopt}},
{"TEMPVD", {false, std::nullopt}},
{"TIGHTEN", {false, std::nullopt}},
{"TIGHTENP", {false, std::nullopt}},
{"TIME", {false, std::nullopt}},
{"TNUM", {false, std::nullopt}},
{"TPAMEPS", {false, std::nullopt}},
{"TPAMEPSS", {false, std::nullopt}},
{"TRACERKM", {false, std::nullopt}},
{"TRACERKP", {false, std::nullopt}},
{"TRACITVD", {false, std::nullopt}},
{"TRACTVD", {false, std::nullopt}},
{"TRACER", {false, std::nullopt}},
{"TRACERS", {false, std::nullopt}},
{"TRACITVD", {false, std::nullopt}},
{"TRADS", {false, std::nullopt}},
{"TRANGL", {false, std::nullopt}},
{"TRANR", {false, std::nullopt}},
{"TRANTHT", {false, std::nullopt}},
{"TRDCY", {false, std::nullopt}},
{"TRDIF", {false, std::nullopt}},
{"TRDIS", {false, std::nullopt}},
{"TRKPF", {false, std::nullopt}},
{"TRNHD", {false, std::nullopt}},
{"TRPLPORO", {false, std::nullopt}},
{"TRROCK", {false, std::nullopt}},
{"TUNINGDP", {false, std::nullopt}},
{"TUNINGH", {false, std::nullopt}},
{"TUNINGL", {false, std::nullopt}},
{"TUNINGS", {false, std::nullopt}},
{"TVDP", {false, std::nullopt}},
{"TZONE", {false, std::nullopt}},
{"UDT", {false, std::nullopt}},
{"UDTDIMS", {false, std::nullopt}},
{"UNCODHMD", {false, std::nullopt}},
{"UNIFOUTS", {false, std::nullopt}},
{"UNIFSAVE", {false, std::nullopt}},
{"USECUPL", {false, std::nullopt}},
{"USEFLUX", {false, std::nullopt}},
{"USENOFLO", {false, std::nullopt}},
{"VAPWAT", {false, std::nullopt}},
{"VDFLOW", {false, std::nullopt}},
{"VDFLOWR", {false, std::nullopt}},
{"VE", {false, std::nullopt}},
{"VEDEBUG", {false, std::nullopt}},
{"VEFIN", {false, std::nullopt}},
{"VEFRAC", {false, std::nullopt}},
{"VEFRACP", {false, std::nullopt}},
{"VEFRACPV", {false, std::nullopt}},
{"VEFRACV", {false, std::nullopt}},
{"VFPCHK", {false, std::nullopt}},
{"VFPTABL", {false, std::nullopt}},
{"VISAGE", {false, std::nullopt}},
{"VISCD", {false, std::nullopt}},
{"VISDATES", {false, std::nullopt}},
{"VISOPTS", {false, std::nullopt}},
{"WAGHYSTR", {false, std::nullopt}},
{"WAITBAL", {false, std::nullopt}},
{"WALKALIN", {false, std::nullopt}},
{"WALQCALC", {false, std::nullopt}},
{"WAPI", {false, std::nullopt}},
{"WARN", {false, std::nullopt}},
{"WBHGLR", {false, std::nullopt}},
{"WBOREVOL", {false, std::nullopt}},
{"WCALCVAL", {false, std::nullopt}},
{"WBP", {false, std::nullopt}},
{"WBP4", {false, std::nullopt}},
{"WBP5", {false, std::nullopt}},
{"WBP9", {false, std::nullopt}},
{"WCONINJ", {false, std::nullopt}},
{"WCONINJP", {false, std::nullopt}},
{"WCUTBACK", {false, std::nullopt}},
{"WCUTBACT", {false, std::nullopt}},
{"WCYCLE", {false, std::nullopt}},
{"WDFACCOR", {false, std::nullopt}},
{"WDFAC", {false, std::nullopt}},
{"WDRILTIM", {false, std::nullopt}},
{"WDRILPRI", {false, std::nullopt}},
{"WDRILRES", {false, std::nullopt}},
{"WECONINJ", {false, std::nullopt}},
{"WECONT", {false, std::nullopt}},
{"WELCNTL", {false, std::nullopt}},
{"WELDEBUG", {false, std::nullopt}},
{"WELDRAW", {false, std::nullopt}},
{"WELEVNT", {false, std::nullopt}},
{"WELMOVEL", {false, std::nullopt}},
{"WELOPENL", {false, std::nullopt}},
{"WELPRI", {false, std::nullopt}},
{"WELSOMIN", {false, std::nullopt}},
{"WELSPECL", {false, std::nullopt}},
{"WFRICSEG", {false, std::nullopt}},
{"WFRICSGL", {false, std::nullopt}},
{"WFRICTN", {false, std::nullopt}},
{"WFRICTNL", {false, std::nullopt}},
{"WGASPROD", {false, std::nullopt}},
{"WGORPEN", {false, std::nullopt}},
{"WH2NUM", {false, std::nullopt}},
{"WH3NUM", {false, std::nullopt}},
{"WHEDREFD", {false, std::nullopt}},
{"WHTEMP", {false, std::nullopt}},
{"WINJMULT", {false, std::nullopt}},
{"WLIMTOL", {false, std::nullopt}},
{"WLIFT", {false, std::nullopt}},
{"WLISTARG", {false, std::nullopt}},
{"WLISTNAM", {false, std::nullopt}},
{"WLISTOPT", {false, std::nullopt}},
{"WNETCTRL", {false, std::nullopt}},
{"WNETDP", {false, std::nullopt}},
{"WORKLIM", {false, std::nullopt}},
{"WORKTHP", {false, std::nullopt}},
{"WPAVE", {false, std::nullopt}},
{"WPIMULTL", {false, std::nullopt}},
{"WPITAB", {false, std::nullopt}},
{"WPLUG", {false, std::nullopt}},
{"WPOLYRED", {false, std::nullopt}},
{"WPOTCALC", {false, std::nullopt}},
{"WREGROUP", {false, std::nullopt}},
{"WSCCLEAN", {false, std::nullopt}},
{"WSCCLENL", {false, std::nullopt}},
{"WSCTAB", {false, std::nullopt}},
{"WSEGDFIN", {false, std::nullopt}},
{"WSEGDFMD", {false, std::nullopt}},
{"WSEGDFPA", {false, std::nullopt}},
{"WSEGEXSS", {false, std::nullopt}},
{"WSEGFLIM", {false, std::nullopt}},
{"WSEGFMOD", {false, std::nullopt}},
{"WSEGINIT", {false, std::nullopt}},
{"WSEGITER", {false, std::nullopt}},
{"WSEGLABY", {false, std::nullopt}},
{"WSEGLINK", {false, std::nullopt}},
{"WSEGMULT", {false, std::nullopt}},
{"WSEGPROP", {false, std::nullopt}},
{"WSEGPULL", {false, std::nullopt}},
{"WSEGSEP", {false, std::nullopt}},
{"WSEGSOLV", {false, std::nullopt}},
{"WSEGTABL", {false, std::nullopt}},
{"WSURFACT", {false, std::nullopt}},
{"WTADD", {false, std::nullopt}},
{"WTEMPQ", {false, std::nullopt}},
{"WTHPMAX", {false, std::nullopt}},
{"WTMULT", {false, std::nullopt}},
{"WVFPDP", {false, std::nullopt}},
{"WVFPEXP", {false, std::nullopt}},
{"WWPAVE", {false, std::nullopt}},
{"ZIPPY2", {false, std::nullopt}},
{"ZIPP2OFF", {false, std::nullopt}},
};
} // namespace Opm::FlowKeywordValidation
#endif

View File

@ -39,7 +39,10 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
#include <opm/simulators/flow/MissingFeatures.hpp>
#include "UnsupportedFlowKeywords.hpp"
#include "PartiallySupportedFlowKeywords.hpp"
#include <opm/simulators/flow/KeywordValidation.hpp>
#include <opm/simulators/utils/ParallelEclipseState.hpp>
#include <opm/simulators/utils/ParallelSerialization.hpp>
@ -192,7 +195,13 @@ void readDeck(int rank, std::string& deckFilename, std::unique_ptr<Opm::Deck>& d
{
Opm::Parser parser;
deck = std::make_unique<Opm::Deck>( parser.parseFile(deckFilename , *parseContext, *errorGuard));
Opm::MissingFeatures::checkKeywords(*deck, *parseContext, *errorGuard);
Opm::KeywordValidation::KeywordValidator keyword_validator(
Opm::FlowKeywordValidation::unsupported_keywords,
Opm::FlowKeywordValidation::partially_supported_keywords_strings,
Opm::FlowKeywordValidation::partially_supported_keywords_int);
keyword_validator.validateDeck(*deck, *parseContext, *errorGuard);
if ( checkDeck )
Opm::checkDeck(*deck, parser, *parseContext, *errorGuard);
}

View File

@ -0,0 +1,457 @@
/*
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/>.
*/
#include <string>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/simulators/flow/KeywordValidation.hpp>
#define BOOST_TEST_MODULE KeywordValidatorTest
#include <boost/test/unit_test.hpp>
using namespace Opm;
using namespace Opm::KeywordValidation;
const UnsupportedKeywords test_unsupported_keywords = {
{"ECHO", {false, "This is not a critical error"}},
{"NOECHO", {true, std::nullopt}},
};
const PartiallySupportedKeywords<std::string> test_string_items = {
{
"PINCH",
{
{2, {false, {"GAP"}, std::nullopt}}, // GAP
{4, {true, {"TOPBOT"}, "This is a critical error"}}, // PINCHOUT_OPTION
},
},
};
const PartiallySupportedKeywords<int> test_int_items = {
{
"ENDSCALE",
{
{3, {false, {1}, std::nullopt}}, // NTENDP
{4, {true, {20}, std::nullopt}}, // NSENDP
},
},
{
"COMPDAT",
{
{2, {false, {1}, std::nullopt}}, // I
{3, {false, {1}, std::nullopt}}, // J
},
},
};
BOOST_AUTO_TEST_CASE(non_critical_keyword)
{
const auto keywords_string = std::string {R"(
ECHO
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("ECHO");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
BOOST_CHECK(!errors[0].critical);
BOOST_CHECK(!errors[0].item_number);
BOOST_CHECK(!errors[0].item_value);
BOOST_CHECK(*(errors[0].user_message) == "This is not a critical error");
}
BOOST_AUTO_TEST_CASE(critical_keyword)
{
const auto keywords_string = std::string {R"(
NOECHO
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("NOECHO");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
BOOST_CHECK(errors[0].critical);
BOOST_CHECK(!errors[0].item_number);
BOOST_CHECK(!errors[0].item_value);
BOOST_CHECK(!errors[0].user_message);
}
BOOST_AUTO_TEST_CASE(non_critical_keyword_item_string)
{
const auto keywords_string = std::string {R"(
PINCH
0.41 FOO 1* 1* /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("PINCH");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
BOOST_CHECK(!errors[0].critical);
BOOST_CHECK(errors[0].item_number == 2);
BOOST_CHECK(errors[0].item_value == "FOO");
BOOST_CHECK(!errors[0].user_message);
}
BOOST_AUTO_TEST_CASE(critical_keyword_item_string)
{
const auto keywords_string = std::string {R"(
PINCH
0.41 GAP 1* FOO /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("PINCH");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
BOOST_CHECK(errors[0].critical);
BOOST_CHECK(errors[0].item_number == 4);
BOOST_CHECK(errors[0].item_value == "FOO");
BOOST_CHECK(*(errors[0].user_message) == "This is a critical error");
}
BOOST_AUTO_TEST_CASE(non_critical_keyword_item_int)
{
const auto keywords_string = std::string {R"(
ENDSCALE
NODIR REVERS 0 20 /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("ENDSCALE");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
BOOST_CHECK(!errors[0].critical);
BOOST_CHECK(errors[0].item_number == 3);
BOOST_CHECK(errors[0].item_value == "0");
BOOST_CHECK(!errors[0].user_message);
}
BOOST_AUTO_TEST_CASE(critical_keyword_item_int)
{
const auto keywords_string = std::string {R"(
ENDSCALE
NODIR REVERS 1 0 /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("ENDSCALE");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
BOOST_CHECK(errors[0].critical);
BOOST_CHECK(errors[0].item_number == 4);
BOOST_CHECK(errors[0].item_value == "0");
BOOST_CHECK(!errors[0].user_message);
}
BOOST_AUTO_TEST_CASE(two_keyword_errors)
{
const auto keywords_string = std::string {R"(
PINCH
0.41 GAP 1* FOO /
ENDSCALE
NODIR REVERS 1 0 /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword1 = deck.getKeyword("PINCH");
const auto& test_keyword2 = deck.getKeyword("ENDSCALE");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword1, errors);
validator.validateDeckKeyword(test_keyword2, errors);
BOOST_CHECK(errors[0].critical);
BOOST_CHECK(errors[0].item_number == 4);
BOOST_CHECK(errors[0].item_value == "FOO");
BOOST_CHECK(*(errors[0].user_message) == "This is a critical error");
BOOST_CHECK(errors[1].critical);
BOOST_CHECK(errors[1].item_number == 4);
BOOST_CHECK(errors[1].item_value == "0");
BOOST_CHECK(!errors[1].user_message);
}
BOOST_AUTO_TEST_CASE(report_not_critical)
{
const auto keywords_string = std::string {R"(
ECHO
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("ECHO");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, false);
BOOST_CHECK(report
== "Unsupported keywords or keyword items:\n\n"
" ECHO: keyword not supported\n"
" In file: <memory string>, line 2\n"
" This is not a critical error");
}
BOOST_AUTO_TEST_CASE(report_critical_missing)
{
const auto keywords_string = std::string {R"(
ECHO
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("ECHO");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, true);
BOOST_CHECK(report.empty());
}
BOOST_AUTO_TEST_CASE(report_critical)
{
const auto keywords_string = std::string {R"(
NOECHO
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("NOECHO");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, true);
BOOST_CHECK(report
== "Unsupported keywords or keyword items:\n\n"
" NOECHO: keyword not supported\n"
" In file: <memory string>, line 2");
}
BOOST_AUTO_TEST_CASE(report_not_critical_missing)
{
const auto keywords_string = std::string {R"(
NOECHO
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("NOECHO");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, false);
BOOST_CHECK(report.empty());
}
BOOST_AUTO_TEST_CASE(error_report_non_critical_keyword_item_string)
{
const auto keywords_string = std::string {R"(
PINCH
0.41 FOO 1* 1* /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("PINCH");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, false);
BOOST_CHECK(report
== "Unsupported keywords or keyword items:\n\n"
" PINCH: invalid value 'FOO' in record 1 for item 2\n"
" In file: <memory string>, line 2");
}
BOOST_AUTO_TEST_CASE(error_report_non_critical_keyword_item_string_two_records)
{
const auto keywords_string = std::string {R"(
PINCH
0.41 GAP 1* 1* /
COMPDAT
C-4H 0 1 1 1 OPEN 1* 4.088536E+1 0.21600 1* 0.00000 1* 'Z' /
C-4H 1 0 2 2 OPEN 1* 7.072475E+1 0.21600 1* 0.00000 1* 'Z' /
/
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("COMPDAT");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, false);
BOOST_CHECK(report
== "Unsupported keywords or keyword items:\n\n"
" COMPDAT: invalid value '0' in record 1 for item 2\n"
" In file: <memory string>, line 4\n\n"
" COMPDAT: invalid value '0' in record 2 for item 3\n"
" In file: <memory string>, line 4");
}
BOOST_AUTO_TEST_CASE(error_report_non_critical_keyword_item_string_missing)
{
const auto keywords_string = std::string {R"(
PINCH
0.41 FOO 1* 1* /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("PINCH");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, true);
BOOST_CHECK(report.empty());
}
BOOST_AUTO_TEST_CASE(error_report_non_critical_keyword_item_int)
{
const auto keywords_string = std::string {R"(
ENDSCALE
NODIR REVERS 0 20 /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("ENDSCALE");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, false);
BOOST_CHECK(report
== "Unsupported keywords or keyword items:\n\n"
" ENDSCALE: invalid value '0' in record 1 for item 3\n"
" In file: <memory string>, line 2");
}
BOOST_AUTO_TEST_CASE(error_report_non_critical_keyword_item_int_missing)
{
const auto keywords_string = std::string {R"(
ENDSCALE
NODIR REVERS 0 20 /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("ENDSCALE");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, true);
BOOST_CHECK(report.empty());
}
BOOST_AUTO_TEST_CASE(error_report_critical_keyword_item_int)
{
const auto keywords_string = std::string {R"(
ENDSCALE
NODIR REVERS 1 0 /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("ENDSCALE");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, true);
BOOST_CHECK(report
== "Unsupported keywords or keyword items:\n\n"
" ENDSCALE: invalid value '0' in record 1 for item 4\n"
" In file: <memory string>, line 2");
}
BOOST_AUTO_TEST_CASE(error_report_critical_keyword_item_int_missing)
{
const auto keywords_string = std::string {R"(
ENDSCALE
NODIR REVERS 1 0 /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword = deck.getKeyword("ENDSCALE");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword, errors);
const auto report = get_error_report(errors, false);
BOOST_CHECK(report.empty());
}
BOOST_AUTO_TEST_CASE(error_report_all_not_critical)
{
const auto keywords_string = std::string {R"(
ECHO
NOECHO
PINCH
0.41 GAP 1* FOO /
ENDSCALE
NODIR REVERS 0 20 /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword1 = deck.getKeyword("ECHO");
const auto& test_keyword2 = deck.getKeyword("NOECHO");
const auto& test_keyword3 = deck.getKeyword("PINCH");
const auto& test_keyword4 = deck.getKeyword("ENDSCALE");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword1, errors);
validator.validateDeckKeyword(test_keyword2, errors);
validator.validateDeckKeyword(test_keyword3, errors);
validator.validateDeckKeyword(test_keyword4, errors);
const auto report = get_error_report(errors, false);
BOOST_CHECK(report
== "Unsupported keywords or keyword items:\n\n"
" ECHO: keyword not supported\n"
" In file: <memory string>, line 2\n"
" This is not a critical error\n\n"
" ENDSCALE: invalid value '0' in record 1 for item 3\n"
" In file: <memory string>, line 6");
}
BOOST_AUTO_TEST_CASE(error_report_not_critical)
{
const auto keywords_string = std::string {R"(
ECHO
NOECHO
PINCH
0.41 GAP 1* FOO /
ENDSCALE
NODIR REVERS 0 20 /
)"};
const auto deck = Parser {}.parseString(keywords_string);
const auto& test_keyword1 = deck.getKeyword("ECHO");
const auto& test_keyword2 = deck.getKeyword("NOECHO");
const auto& test_keyword3 = deck.getKeyword("PINCH");
const auto& test_keyword4 = deck.getKeyword("ENDSCALE");
KeywordValidator validator(test_unsupported_keywords, test_string_items, test_int_items);
std::vector<ValidationError> errors;
validator.validateDeckKeyword(test_keyword1, errors);
validator.validateDeckKeyword(test_keyword2, errors);
validator.validateDeckKeyword(test_keyword3, errors);
validator.validateDeckKeyword(test_keyword4, errors);
const auto report = get_error_report(errors, true);
BOOST_CHECK(report
== "Unsupported keywords or keyword items:\n\n"
" NOECHO: keyword not supported\n"
" In file: <memory string>, line 3\n\n"
" PINCH: invalid value 'FOO' in record 1 for item 4\n"
" In file: <memory string>, line 4\n"
" This is a critical error");
}