Add KeywordLocation argument to ParseContext::handleError()
This commit is contained in:
parent
94b4c509b1
commit
e01400fa18
@ -420,8 +420,6 @@ list (APPEND TEST_DATA_FILES
|
||||
)
|
||||
if(ENABLE_ECL_OUTPUT)
|
||||
list (APPEND TEST_DATA_FILES
|
||||
tests/expect-wdims.chldg.err.out
|
||||
tests/expect-wdims.err.out
|
||||
tests/BASE_SIM.DATA
|
||||
tests/BASE_SIM_THPRES.DATA
|
||||
tests/RESTART_SIM.DATA
|
||||
|
@ -21,9 +21,10 @@
|
||||
#ifndef OPM_PARSE_CONTEXT_HPP
|
||||
#define OPM_PARSE_CONTEXT_HPP
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
@ -33,6 +34,9 @@
|
||||
namespace Opm {
|
||||
|
||||
|
||||
class KeywordLocation;
|
||||
|
||||
|
||||
/*
|
||||
The ParseContext class is meant to control the behavior of the
|
||||
parsing and EclipseState construction phase when
|
||||
@ -87,8 +91,8 @@ namespace Opm {
|
||||
explicit ParseContext(InputError::Action default_action);
|
||||
explicit ParseContext(const std::vector<std::pair<std::string , InputError::Action>>& initial);
|
||||
|
||||
void handleError( const std::string& errorKey, const std::string& msg, ErrorGuard& errors ) const;
|
||||
void handleUnknownKeyword(const std::string& keyword, ErrorGuard& errors) const;
|
||||
void handleError( const std::string& errorKey, const std::string& msg, const std::optional<KeywordLocation>& location, ErrorGuard& errors) const;
|
||||
void handleUnknownKeyword(const std::string& keyword, const std::optional<KeywordLocation>& location, ErrorGuard& errors) const;
|
||||
bool hasKey(const std::string& key) const;
|
||||
ParseContext withKey(const std::string& key, InputError::Action action = InputError::WARN) const;
|
||||
ParseContext& withKey(const std::string& key, InputError::Action action = InputError::WARN);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include <opm/common/utility/OpmInputError.hpp>
|
||||
#include <opm/parser/eclipse/Utility/Functional.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
|
||||
@ -332,17 +333,16 @@ inline std::map< std::string, int > RPT( const DeckKeyword& keyword,
|
||||
|
||||
if (ints && strs) {
|
||||
const auto& location = keyword.location();
|
||||
std::string msg = "Mixed style input is not allowed for keyword: " + keyword.name() + " at " + location.filename + "(" + std::to_string( location.lineno ) + ")";
|
||||
parseContext.handleError(ParseContext::RPT_MIXED_STYLE, msg, errors);
|
||||
std::string msg = "Error in keyword {keyword}, mixing mnemonics and integers is not allowed\n"
|
||||
"In {file} line {line}.";
|
||||
parseContext.handleError(ParseContext::RPT_MIXED_STYLE, msg, location, errors);
|
||||
|
||||
std::vector<std::string> stack;
|
||||
for (size_t index=0; index < deck_items.size(); index++) {
|
||||
if (is_int(deck_items[index])) {
|
||||
|
||||
if (stack.size() < 2) {
|
||||
std::string errmsg = "Can not interpret " + keyword.name() + " at " + location.filename + "(" + std::to_string( location.lineno ) + ")";
|
||||
throw std::invalid_argument(errmsg);
|
||||
}
|
||||
if (stack.size() < 2)
|
||||
throw OpmInputError("Problem processing {keyword}\nIn {file} line {line}.", location);
|
||||
|
||||
if (stack.back() == "=") {
|
||||
stack.pop_back();
|
||||
@ -352,10 +352,8 @@ inline std::map< std::string, int > RPT( const DeckKeyword& keyword,
|
||||
items.insert(items.begin(), stack.begin(), stack.end());
|
||||
stack.clear();
|
||||
items.push_back( mnemonic + "=" + deck_items[index]);
|
||||
} else {
|
||||
std::string errmsg = "Can not interpret " + keyword.name() + " at " + location.filename + "(" + std::to_string( location.lineno ) + ")";
|
||||
throw std::invalid_argument(errmsg);
|
||||
}
|
||||
} else
|
||||
throw OpmInputError("Problem processing {keyword}\nIn {file} line {line}.", location);
|
||||
|
||||
} else
|
||||
stack.push_back(deck_items[index]);
|
||||
@ -370,7 +368,8 @@ inline std::map< std::string, int > RPT( const DeckKeyword& keyword,
|
||||
|
||||
std::string base = mnemonic.substr( 0, sep_pos );
|
||||
if( !is_mnemonic( base ) ) {
|
||||
parseContext.handleError(ParseContext::RPT_UNKNOWN_MNEMONIC, "The mnemonic: " + base + " is not recognized.", errors);
|
||||
std::string msg_fmt = fmt::format("Error in keyword {{keyword}}, unrecognized mnemonic {}\nIn {{file}} line {{line}}.", base);
|
||||
parseContext.handleError(ParseContext::RPT_UNKNOWN_MNEMONIC, msg_fmt, keyword.location(), errors);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <opm/common/OpmLog/KeywordLocation.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
|
||||
@ -43,13 +46,20 @@ namespace {
|
||||
|
||||
if (nWells > std::size_t(wdims.maxWellsInField()))
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "Run uses " << nWells << " wells, but allocates at "
|
||||
<< "most " << wdims.maxWellsInField() << " in RUNSPEC "
|
||||
<< "section. Increase item 1 of WELLDIMS accordingly.";
|
||||
const auto& location = wdims.location();
|
||||
if (location) {
|
||||
std::string fmt_message = fmt::format("Problem with keyword {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"The case has {0} wells - but only {1} are specified in WELLDIMS.\n"
|
||||
"Please increase item 1 in WELLDIMS to at least {1}", nWells, wdims.maxWellsInField());
|
||||
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_NUMWELLS_TOO_LARGE,
|
||||
os.str(), guard);
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_NUMWELLS_TOO_LARGE,
|
||||
fmt_message, *location, guard);
|
||||
} else {
|
||||
std::string msg = fmt::format("The case does not have a WELLDIMS keyword.\n"
|
||||
"Please add a WELLDIMS keyword in the RUNSPEC section specifying at least {} wells in item 1.", nWells);
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_NUMWELLS_TOO_LARGE, msg, {}, guard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,14 +76,20 @@ namespace {
|
||||
|
||||
if (nconn > static_cast<decltype(nconn)>(wdims.maxConnPerWell()))
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "Run has well with " << nconn << " reservoir connections, "
|
||||
<< "but allocates at most " << wdims.maxConnPerWell()
|
||||
<< " connections per well in RUNSPEC section. Increase item "
|
||||
<< "2 of WELLDIMS accordingly.";
|
||||
const auto& location = wdims.location();
|
||||
if (location) {
|
||||
std::string fmt_message = fmt::format("Problem with keyword {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"The case has a well with {0} connections, but {1} is specified as maxmimum in WELLDIMS.\n"
|
||||
"Please increase item 2 in WELLDIMS to at least {0}", nconn, wdims.maxConnPerWell());
|
||||
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_CONNS_PER_WELL_TOO_LARGE,
|
||||
os.str(), guard);
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_CONNS_PER_WELL_TOO_LARGE,
|
||||
fmt_message, *location, guard);
|
||||
} else {
|
||||
std::string msg = fmt::format("The case does not have a WELLDIMS keyword.\n"
|
||||
"Please add a WELLDIMS keyword in the RUNSPEC section specifying at least {} connections in item 2.", nconn);
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_CONNS_PER_WELL_TOO_LARGE, msg, {}, guard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,14 +104,21 @@ namespace {
|
||||
// but excluded from WELLDIMS(3).
|
||||
if (nGroups > 1U + wdims.maxGroupsInField())
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "Run uses " << (nGroups - 1) << " non-FIELD groups, but "
|
||||
<< "allocates at most " << wdims.maxGroupsInField()
|
||||
<< " in RUNSPEC section. Increase item 3 of WELLDIMS "
|
||||
<< "accordingly.";
|
||||
const auto& location = wdims.location();
|
||||
if (location) {
|
||||
std::string fmt_message = fmt::format("Problem with keyword {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"The case has {0} non-FIELD groups, the WELLDIMS keyword specifies {1}\n."
|
||||
"Please increase item 3 in WELLDIMS to at least {0}", nGroups - 1, wdims.maxGroupsInField());
|
||||
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_NUMGROUPS_TOO_LARGE,
|
||||
os.str(), guard);
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_NUMGROUPS_TOO_LARGE,
|
||||
fmt_message, *location, guard);
|
||||
} else {
|
||||
std::string msg = fmt::format("The case does not have a WELLDIMS keyword.\n"
|
||||
"Please add a WELLDIMS keyword in the RUNSPEC section specifying at least {} groups in item 3.", nGroups - 1);
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_NUMGROUPS_TOO_LARGE,
|
||||
msg , {}, guard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,14 +138,21 @@ namespace {
|
||||
|
||||
if (size > static_cast<decltype(size)>(wdims.maxWellsPerGroup()))
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "Run uses maximum group size of " << size << ", but "
|
||||
<< "allocates at most " << wdims.maxWellsPerGroup()
|
||||
<< " in RUNSPEC section. Increase item 4 of WELLDIMS "
|
||||
<< "accordingly.";
|
||||
const auto& location = wdims.location();
|
||||
if (location) {
|
||||
std::string fmt_message = fmt::format("Problem with keyword {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"The case has a maximum group size of {0} wells, the WELLDIMS keyword specifies {1}\n."
|
||||
"Please increase item 4 in WELLDIMS to at least {0}", size, wdims.maxGroupsInField());
|
||||
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_GROUPSIZE_TOO_LARGE,
|
||||
os.str(), guard);
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_GROUPSIZE_TOO_LARGE,
|
||||
fmt_message, *location, guard);
|
||||
} else {
|
||||
std::string msg = fmt::format("The case does not have a WELLDIMS keyword.\n"
|
||||
"Please add a WELLDIMS keyword in the RUNSPEC section specifying at least {} as max groupsize in item 4.", size);
|
||||
ctxt.handleError(Opm::ParseContext::RUNSPEC_GROUPSIZE_TOO_LARGE,
|
||||
msg, Opm::KeywordLocation{}, guard);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // WellDims
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <opm/common/OpmLog/LogUtil.hpp>
|
||||
#include <opm/common/utility/OpmInputError.hpp>
|
||||
#include <opm/common/utility/numeric/cmp.hpp>
|
||||
@ -95,13 +97,14 @@ namespace {
|
||||
means that we do not inform the user about "our fix", but it is *not* possible
|
||||
to configure the parser to leave the spaces intact.
|
||||
*/
|
||||
|
||||
std::string trim_wgname(const DeckKeyword& keyword, const std::string& wgname_arg, const ParseContext& parseContext, ErrorGuard errors) {
|
||||
std::string wgname = trim_copy(wgname_arg);
|
||||
if (wgname != wgname_arg) {
|
||||
const auto& location = keyword.location();
|
||||
std::string msg = "Illegal space: \"" + wgname_arg + "\" found when defining WELL/GROUP in keyword: " + keyword.name() + " at " + location.filename + ":" + std::to_string(location.lineno);
|
||||
parseContext.handleError(ParseContext::PARSE_WGNAME_SPACE, msg, errors);
|
||||
std::string msg_fmt = fmt::format("Problem with keyword {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"Illegal space in {} when defining WELL/GROUP.", wgname_arg);
|
||||
parseContext.handleError(ParseContext::PARSE_WGNAME_SPACE, msg_fmt, location, errors);
|
||||
}
|
||||
return wgname;
|
||||
}
|
||||
@ -178,9 +181,10 @@ namespace {
|
||||
for (const auto& record : handlerContext.keyword) {
|
||||
const auto& methodItem = record.getItem<ParserKeywords::COMPORD::ORDER_TYPE>();
|
||||
if ((methodItem.get< std::string >(0) != "TRACK") && (methodItem.get< std::string >(0) != "INPUT")) {
|
||||
std::string msg = "The COMPORD keyword only handles 'TRACK' or 'INPUT' order.";
|
||||
OpmLog::error(msg);
|
||||
parseContext.handleError( ParseContext::UNSUPPORTED_COMPORD_TYPE , msg, errors );
|
||||
std::string msg_fmt = "Problem with {keyword}\n"
|
||||
"In {file} line {line}\n"
|
||||
"Only 'TRACK' and 'INPUT' order are supported";
|
||||
parseContext.handleError( ParseContext::UNSUPPORTED_COMPORD_TYPE ,msg_fmt , handlerContext.keyword.location(), errors );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -350,8 +354,10 @@ namespace {
|
||||
if ((guide_rate_def == Group::GuideRateTarget::INJV ||
|
||||
guide_rate_def == Group::GuideRateTarget::POTN ||
|
||||
guide_rate_def == Group::GuideRateTarget::FORM)) {
|
||||
std::string msg = "The supplied guide_rate value will be ignored";
|
||||
parseContext.handleError(ParseContext::SCHEDULE_IGNORED_GUIDE_RATE, msg, errors);
|
||||
std::string msg_fmt = "Problem with {keyword}\n"
|
||||
"In {file} line {line}\n"
|
||||
"The supplied guide rate will be ignored";
|
||||
parseContext.handleError(ParseContext::SCHEDULE_IGNORED_GUIDE_RATE, msg_fmt, handlerContext.keyword.location(), errors);
|
||||
} else {
|
||||
guide_rate = record.getItem("GUIDE_RATE").get<double>(0);
|
||||
if (guide_rate == 0)
|
||||
@ -628,8 +634,10 @@ namespace {
|
||||
}
|
||||
|
||||
void Schedule::handleMXUNSUPP(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
|
||||
std::string msg = "OPM does not support grid property modifier " + handlerContext.keyword.name() + " in the Schedule section. Error at report: " + std::to_string(handlerContext.currentStep);
|
||||
parseContext.handleError( ParseContext::UNSUPPORTED_SCHEDULE_GEO_MODIFIER , msg, errors );
|
||||
std::string msg_fmt = fmt::format("Problem with keyword {{keyword}} at report step {}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"OPM does not support grid property modifier {} in the Schedule section", handlerContext.currentStep, handlerContext.keyword.name());
|
||||
parseContext.handleError( ParseContext::UNSUPPORTED_SCHEDULE_GEO_MODIFIER , msg_fmt, handlerContext.keyword.location(), errors );
|
||||
}
|
||||
|
||||
void Schedule::handleNODEPROP(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) {
|
||||
@ -765,7 +773,7 @@ namespace {
|
||||
const auto& current = *this->udq_config.get(handlerContext.currentStep);
|
||||
std::shared_ptr<UDQConfig> new_udq = std::make_shared<UDQConfig>(current);
|
||||
for (const auto& record : handlerContext.keyword)
|
||||
new_udq->add_record(record, handlerContext.currentStep);
|
||||
new_udq->add_record(record, handlerContext.keyword.location(), handlerContext.currentStep);
|
||||
|
||||
this->udq_config.update(handlerContext.currentStep, new_udq);
|
||||
}
|
||||
@ -1267,9 +1275,10 @@ namespace {
|
||||
|
||||
const std::string bhp_terminate = record.getItem("BPH_TERMINATE").getTrimmedString(0);
|
||||
if (bhp_terminate == "YES") {
|
||||
std::string msg = "The WHISTCTL handlerContext.keyword does not handle 'YES'. i.e. to terminate the run";
|
||||
OpmLog::error(msg);
|
||||
parseContext.handleError( ParseContext::UNSUPPORTED_TERMINATE_IF_BHP , msg, errors );
|
||||
std::string msg_fmt = "Problem with {keyword}\n"
|
||||
"In {file} line {line}\n"
|
||||
"Setting item 2 in {keyword} to 'YES' to stop the run is not supported";
|
||||
parseContext.handleError( ParseContext::UNSUPPORTED_TERMINATE_IF_BHP , msg_fmt, handlerContext.keyword.location(), errors );
|
||||
}
|
||||
|
||||
for (auto& well_pair : this->wells_static) {
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/C.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
|
||||
@ -185,6 +187,7 @@ namespace {
|
||||
ErrorGuard& errors) {
|
||||
|
||||
std::vector< Record > compsegs;
|
||||
const auto& location = compsegsKeyword.location();
|
||||
|
||||
// The first record in the keyword only contains the well name
|
||||
// looping from the second record in the keyword
|
||||
@ -208,38 +211,38 @@ namespace {
|
||||
// TODO: the end of the previous connection or range
|
||||
// 'previous' should be in term of the input order
|
||||
// since basically no specific order for the connections
|
||||
const std::string msg = "This way to obtain DISTANCE_START in keyword COMPSEGS "
|
||||
"is not implemented yet for well " + well_name;
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_NOT_SUPPORTED, msg, errors);
|
||||
const std::string msg_fmt = "Must specify start of segment in item 5 in {keyword}\nIn {file} line {line}";
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_NOT_SUPPORTED, msg_fmt, location, errors);
|
||||
}
|
||||
if (record.getItem<ParserKeywords::COMPSEGS::DISTANCE_END>().hasValue(0)) {
|
||||
distance_end = record.getItem<ParserKeywords::COMPSEGS::DISTANCE_END>().getSIDouble(0);
|
||||
} else {
|
||||
// TODO: the distance_start plus the thickness of the grid block
|
||||
const std::string msg = "This way to obtain DISTANCE_END in keyword COMPSEGS "
|
||||
"is not implemented yet for well " + well_name;
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_NOT_SUPPORTED, msg, errors);
|
||||
const std::string msg_fmt = "Must specify end of segment in item 6 in {keyword}\nIn {file} line {line}";
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_NOT_SUPPORTED, msg_fmt, location, errors);
|
||||
}
|
||||
|
||||
if (distance_end <= distance_start) {
|
||||
std::ostringstream sstr;
|
||||
sstr << " The end of the perforations need be to further down than the start of the perforations\n "
|
||||
<< " well " << well_name << " " << I + 1 << " " << J + 1 << " " << K + 1 << " in keyword COMPSEGS\n";
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_INVALID, sstr.str(), errors);
|
||||
std::string msg_fmt = fmt::format("Problems with {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"The end of the perforation must be below the start for well {} connection({},{},{})", well_name, I+1, J+1, K+1);
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_INVALID, msg_fmt, location, errors);
|
||||
}
|
||||
|
||||
if( !record.getItem< ParserKeywords::COMPSEGS::DIRECTION >().hasValue( 0 ) &&
|
||||
!record.getItem< ParserKeywords::COMPSEGS::DISTANCE_END >().hasValue( 0 ) ) {
|
||||
const std::string msg = "The direction has to be specified when DISTANCE_END "
|
||||
"is not specified in keyword COMPSEGS for well " + well_name;
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_INVALID, msg, errors);
|
||||
std::string msg_fmt = fmt::format("Problems with {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"The direction must be specified when DISTANCE_END is defaulted. Well: {}", well_name);
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_INVALID, msg_fmt, location, errors);
|
||||
}
|
||||
|
||||
if( record.getItem< ParserKeywords::COMPSEGS::END_IJK >().hasValue( 0 ) &&
|
||||
!record.getItem< ParserKeywords::COMPSEGS::DIRECTION >().hasValue( 0 ) ) {
|
||||
const std::string msg = "The direction has to be specified when END_IJK "
|
||||
"is specified in keyword COMPSEGS for well " + well_name;
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_INVALID, msg, errors);
|
||||
std::string msg_fmt = fmt::format("Problems with {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"The direction must be specified when END_IJK is specified. Well: {}", well_name);
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_INVALID, msg_fmt, location, errors);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -262,9 +265,10 @@ namespace {
|
||||
|
||||
if (center_depth < 0.) {
|
||||
//TODO: get the depth from COMPDAT data.
|
||||
const std::string msg = "This way to obtain CENTER_DISTANCE in keyword COMPSEGS "
|
||||
"is not implemented yet for well " + well_name;
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_NOT_SUPPORTED, msg, errors);
|
||||
std::string msg_fmt = fmt::format("Problems with {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"The use of negative center depth in item 9 is not supported. Well: {}", well_name);
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_NOT_SUPPORTED, msg_fmt, location, errors);
|
||||
}
|
||||
|
||||
int segment_number;
|
||||
@ -287,10 +291,11 @@ namespace {
|
||||
seqIndex);
|
||||
}
|
||||
} else { // a range is defined. genrate a range of Record
|
||||
std::ostringstream sstr;
|
||||
sstr << "COMPSEGS entries can only be input for single connection, not supporting COMPSEGS entries specified with a range yet.\n"
|
||||
<< " well " << well_name << " " << I + 1 << " " << J + 1 << " " << K + 1 << " in keyword COMPSEGS\n";
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_NOT_SUPPORTED, sstr.str(), errors);
|
||||
std::string msg_fmt = fmt::format("Problems with {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"Entering COMPEGS with a range of connections is not yet supported\n"
|
||||
"Well: {} Connection: ({},{},{})", well_name, I+1, J+1 , K+1);
|
||||
parseContext.handleError(ParseContext::SCHEDULE_COMPSEGS_NOT_SUPPORTED, msg_fmt, location, errors);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,11 +331,13 @@ namespace {
|
||||
if (action_keyword.name() == "ENDACTIO")
|
||||
break;
|
||||
|
||||
if (Action::ActionX::valid_keyword(action_keyword.name())) {
|
||||
if (Action::ActionX::valid_keyword(action_keyword.name()))
|
||||
action.addKeyword(action_keyword);
|
||||
} else {
|
||||
std::string msg = "The keyword " + action_keyword.name() + " is not supported in a ACTIONX block.";
|
||||
parseContext.handleError( ParseContext::ACTIONX_ILLEGAL_KEYWORD, msg, errors);
|
||||
else {
|
||||
std::string msg = "The keyword {0} is not supported in a ACTIONX block. file: {1} line: {2}";
|
||||
std::string msg_fmt = "The keyword {keyword} is not supported in the ACTIONX block\n"
|
||||
"In {file} line {line}.";
|
||||
parseContext.handleError( ParseContext::ACTIONX_ILLEGAL_KEYWORD, msg, action_keyword.location(), errors);
|
||||
}
|
||||
}
|
||||
this->addACTIONX(action, currentStep);
|
||||
@ -599,8 +601,11 @@ namespace {
|
||||
}
|
||||
|
||||
void Schedule::invalidNamePattern( const std::string& namePattern, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors, const DeckKeyword& keyword ) const {
|
||||
std::string msg = "Error when handling " + keyword.name() + " at step: " + std::to_string(report_step) + ". No names match " + namePattern;
|
||||
parseContext.handleError( ParseContext::SCHEDULE_INVALID_NAME, msg, errors );
|
||||
std::string msg_fmt = fmt::format("Invalid wellname pattern in {{keyword}}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"No wells/groups match the pattern: '{}'", namePattern);
|
||||
|
||||
parseContext.handleError( ParseContext::SCHEDULE_INVALID_NAME, msg_fmt, keyword.location(), errors );
|
||||
}
|
||||
|
||||
const TimeMap& Schedule::getTimeMap() const {
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/common/OpmLog/KeywordLocation.hpp>
|
||||
|
||||
@ -250,16 +252,8 @@ UDQASTNode UDQParser::parse_set() {
|
||||
namespace {
|
||||
void dump_tokens(const std::string& target_var, const std::vector<UDQToken>& tokens) {
|
||||
std::cout << target_var << " = ";
|
||||
for (const auto& token : tokens) {
|
||||
const auto& value = token.value();
|
||||
if (std::holds_alternative<double>(value))
|
||||
std::cout << std::get<double>(token.value()) << " ";
|
||||
else {
|
||||
std::cout << std::get<std::string>(token.value()) << " ";
|
||||
for (const auto& s : token.selector())
|
||||
std::cout << s << " ";
|
||||
}
|
||||
}
|
||||
for (const auto& token : tokens)
|
||||
std::cout << token.str();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
@ -294,20 +288,32 @@ UDQASTNode UDQParser::parse(const UDQParams& udq_params, UDQVarType target_type,
|
||||
if (!parser.empty()) {
|
||||
size_t index = parser.current_pos;
|
||||
auto current = parser.current();
|
||||
std::string msg = "Extra unhandled data starting with token[" + std::to_string(index) + "] = '" + current.string() + "'";
|
||||
parseContext.handleError(ParseContext::UDQ_PARSE_ERROR, msg, errors);
|
||||
std::string msg_fmt = fmt::format("Problem parsing UDQ expression \n"
|
||||
"In {{file}} line {{line}}.\n"
|
||||
"Extra unhandled data starting with item {}.", current.string());
|
||||
parseContext.handleError(ParseContext::UDQ_PARSE_ERROR, msg_fmt, location, errors);
|
||||
return UDQASTNode( udq_params.undefinedValue() );
|
||||
}
|
||||
|
||||
if (!tree.valid()) {
|
||||
std::string msg = "ERROR: Failed to parse UDQ expression";
|
||||
parseContext.handleError(ParseContext::UDQ_PARSE_ERROR, msg, errors);
|
||||
std::string token_string;
|
||||
for (const auto& token : tokens)
|
||||
token_string += token.str() + " ";
|
||||
|
||||
std::string msg_fmt = fmt::format("Failed to parse UDQ expression\n"
|
||||
"In {{file}} line {{line}}.\n"
|
||||
"This can be a bug in flow or a bug in the UDQ input string.\n"
|
||||
"UDQ input: '{}'", token_string);
|
||||
parseContext.handleError(ParseContext::UDQ_PARSE_ERROR, msg_fmt, location, errors);
|
||||
return UDQASTNode( udq_params.undefinedValue() );
|
||||
}
|
||||
|
||||
if (!static_type_check(target_type, tree.var_type)) {
|
||||
std::string msg = "Invalid compile-time type conversion detected in UDQ expression target type: " + UDQ::typeName(target_type) + " expr type: " + UDQ::typeName(tree.var_type);
|
||||
parseContext.handleError(ParseContext::UDQ_TYPE_ERROR, msg, errors);
|
||||
std::string msg_fmt = fmt::format("Failed to parse UDQ expression\n"
|
||||
"In {{file}} line {{line}}.\n"
|
||||
"Invalid type conversion detected in UDQ expression expected: {} got: {}", UDQ::typeName(target_type), UDQ::typeName(tree.var_type));
|
||||
|
||||
parseContext.handleError(ParseContext::UDQ_TYPE_ERROR, msg_fmt, location, errors);
|
||||
if (parseContext.get(ParseContext::UDQ_TYPE_ERROR) != InputError::IGNORE)
|
||||
dump_tokens(target_var, tokens);
|
||||
|
||||
@ -315,8 +321,10 @@ UDQASTNode UDQParser::parse(const UDQParams& udq_params, UDQVarType target_type,
|
||||
}
|
||||
|
||||
if (tree.var_type == UDQVarType::NONE) {
|
||||
std::string msg = "Parse error when evaluating UDQ define expression - could not determine expression type";
|
||||
parseContext.handleError(ParseContext::UDQ_TYPE_ERROR, msg, errors);
|
||||
std::string msg_fmt = fmt::format("Failed to parse UDQ expression\n"
|
||||
"In {{file}} line {{line}}.\n"
|
||||
"Could not determine expression type.");
|
||||
parseContext.handleError(ParseContext::UDQ_TYPE_ERROR, msg_fmt, location, errors);
|
||||
if (parseContext.get(ParseContext::UDQ_TYPE_ERROR) != InputError::IGNORE)
|
||||
dump_tokens(target_var, tokens);
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include "UDQToken.hpp"
|
||||
|
||||
@ -51,4 +51,13 @@ UDQTokenType UDQToken::type() const {
|
||||
return this->token_type;
|
||||
}
|
||||
|
||||
std::string UDQToken::str() const {
|
||||
if (std::holds_alternative<std::string>(this->m_value))
|
||||
return std::get<std::string>(this->m_value) + std::string{" "} + std::accumulate(this->m_selector.begin(), this->m_selector.end(), std::string{},
|
||||
[](const std::string& s1, const std::string& s2) { return s1 + " " + s2; });
|
||||
else
|
||||
return std::to_string(std::get<double>(this->m_value));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
const std::vector<std::string>& selector() const;
|
||||
const std::variant<std::string, double>& value() const;
|
||||
UDQTokenType type() const;
|
||||
std::string str() const;
|
||||
private:
|
||||
UDQTokenType token_type;
|
||||
std::variant<std::string,double> m_value;
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/common/utility/OpmInputError.hpp>
|
||||
@ -326,30 +328,24 @@ namespace {
|
||||
return SummaryConfigNode::Type::Undefined;
|
||||
}
|
||||
|
||||
void handleMissingWell( const ParseContext& parseContext, ErrorGuard& errors, const std::string& keyword, const std::string& well) {
|
||||
std::string msg = std::string("Error in keyword:") + keyword + std::string(" No such well: ") + well;
|
||||
if (parseContext.get( ParseContext::SUMMARY_UNKNOWN_WELL) == InputError::WARN)
|
||||
std::cerr << "ERROR: " << msg << std::endl;
|
||||
|
||||
parseContext.handleError( ParseContext::SUMMARY_UNKNOWN_WELL , msg, errors );
|
||||
void handleMissingWell( const ParseContext& parseContext, ErrorGuard& errors, const KeywordLocation& location, const std::string& well) {
|
||||
std::string msg_fmt = fmt::format("Request for missing well {} in {{keyword}}\n"
|
||||
"In {{file}} line {{line}}", well);
|
||||
parseContext.handleError( ParseContext::SUMMARY_UNKNOWN_WELL , msg_fmt, location, errors );
|
||||
}
|
||||
|
||||
|
||||
void handleMissingGroup( const ParseContext& parseContext , ErrorGuard& errors, const std::string& keyword, const std::string& group) {
|
||||
std::string msg = std::string("Error in keyword:") + keyword + std::string(" No such group: ") + group;
|
||||
if (parseContext.get( ParseContext::SUMMARY_UNKNOWN_GROUP) == InputError::WARN)
|
||||
std::cerr << "ERROR: " << msg << std::endl;
|
||||
|
||||
parseContext.handleError( ParseContext::SUMMARY_UNKNOWN_GROUP , msg, errors );
|
||||
void handleMissingGroup( const ParseContext& parseContext , ErrorGuard& errors, const KeywordLocation& location, const std::string& group) {
|
||||
std::string msg_fmt = fmt::format("Request for missing group {} in {{keyword}}\n"
|
||||
"In {{file}} line {{line}}", group);
|
||||
parseContext.handleError( ParseContext::SUMMARY_UNKNOWN_GROUP , msg_fmt, location, errors );
|
||||
}
|
||||
|
||||
void handleMissingNode( const ParseContext& parseContext, ErrorGuard& errors, const std::string& keyword, const std::string& node_name )
|
||||
void handleMissingNode( const ParseContext& parseContext, ErrorGuard& errors, const KeywordLocation& location, const std::string& node_name )
|
||||
{
|
||||
const auto msg = std::string("Error in keyword \"") + keyword + std::string("\": No such network node: ") + node_name;
|
||||
if (parseContext.get( ParseContext::SUMMARY_UNKNOWN_NODE) == InputError::WARN)
|
||||
std::cerr << "ERROR: " << msg << std::endl;
|
||||
|
||||
parseContext.handleError( ParseContext::SUMMARY_UNKNOWN_NODE, msg, errors );
|
||||
std::string msg_fmt = fmt::format("Request for missing network node {} in {{keyword}}\n"
|
||||
"In {{file}} line {{line}}", node_name);
|
||||
parseContext.handleError( ParseContext::SUMMARY_UNKNOWN_NODE, msg_fmt, location, errors );
|
||||
}
|
||||
|
||||
inline void keywordW( SummaryConfig::keyword_list& list,
|
||||
@ -391,8 +387,9 @@ inline void keywordW( SummaryConfig::keyword_list& list,
|
||||
if (keyword.name().back() == 'L') {
|
||||
if (! (is_control_mode(keyword.name()) || is_udq(keyword.name()))) {
|
||||
const auto& location = keyword.location();
|
||||
std::string msg = std::string("The completion keywords like: " + keyword.name() + " are not supported at: " + location.filename + ", line " + std::to_string(location.lineno));
|
||||
parseContext.handleError( ParseContext::SUMMARY_UNHANDLED_KEYWORD, msg, errors);
|
||||
std::string msg = "Unsupported summary output keyword {}\n"
|
||||
"In {file} line {line}";
|
||||
parseContext.handleError( ParseContext::SUMMARY_UNHANDLED_KEYWORD, msg, location, errors);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -408,7 +405,7 @@ inline void keywordW( SummaryConfig::keyword_list& list,
|
||||
auto well_names = schedule.wellNames( pattern, schedule.size() - 1 );
|
||||
|
||||
if( well_names.empty() )
|
||||
handleMissingWell( parseContext, errors, keyword.name(), pattern );
|
||||
handleMissingWell( parseContext, errors, keyword.location(), pattern );
|
||||
|
||||
keywordW( list, well_names, param );
|
||||
}
|
||||
@ -463,7 +460,7 @@ inline void keywordG( SummaryConfig::keyword_list& list,
|
||||
if( schedule.hasGroup( group ) )
|
||||
list.push_back( param.namedEntity(group) );
|
||||
else
|
||||
handleMissingGroup( parseContext, errors, keyword.name(), group );
|
||||
handleMissingGroup( parseContext, errors, keyword.location(), group );
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,7 +504,7 @@ void keyword_node( SummaryConfig::keyword_list& list,
|
||||
if (pos != node_names.end())
|
||||
list.push_back( param.namedEntity(node_name) );
|
||||
else
|
||||
handleMissingNode( parseContext, errors, keyword.name(), node_name );
|
||||
handleMissingNode( parseContext, errors, keyword.location(), node_name );
|
||||
}
|
||||
}
|
||||
|
||||
@ -565,8 +562,9 @@ inline void keywordR2R( SummaryConfig::keyword_list& /* list */,
|
||||
const DeckKeyword& keyword)
|
||||
{
|
||||
const auto& location = keyword.location();
|
||||
std::string msg = "Region to region summary keyword: " + keyword.name() + " at " + location.filename + ", line " + std::to_string(location.lineno) + " is ignored";
|
||||
parseContext.handleError(ParseContext::SUMMARY_UNHANDLED_KEYWORD, msg, errors);
|
||||
std::string msg_fmt = "Region to region summary keyword {keyword} is ignored\n";
|
||||
"In {file} line {line}";
|
||||
parseContext.handleError(ParseContext::SUMMARY_UNHANDLED_KEYWORD, msg_fmt, location, errors);
|
||||
}
|
||||
|
||||
|
||||
@ -648,7 +646,7 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
|
||||
const auto ijk_defaulted = record.getItem( 1 ).defaultApplied( 0 );
|
||||
|
||||
if( well_names.empty() )
|
||||
handleMissingWell( parseContext, errors, keyword.name(), wellitem.getTrimmedString( 0 ) );
|
||||
handleMissingWell( parseContext, errors, keyword.location(), wellitem.getTrimmedString( 0 ) );
|
||||
|
||||
for(const auto& name : well_names) {
|
||||
param.namedEntity(name);
|
||||
@ -777,7 +775,7 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
|
||||
: schedule.wellNames(wellitem.getTrimmedString(0));
|
||||
|
||||
if (well_names.empty())
|
||||
handleMissingWell(parseContext, errors, keyword.name(),
|
||||
handleMissingWell(parseContext, errors, keyword.location(),
|
||||
wellitem.getTrimmedString(0));
|
||||
|
||||
// Negative 1 (< 0) if segment ID defaulted. Defaulted
|
||||
@ -852,25 +850,29 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
|
||||
};
|
||||
}
|
||||
|
||||
void check_udq( const std::string& name,
|
||||
void check_udq( const KeywordLocation& location,
|
||||
const Schedule& schedule,
|
||||
const ParseContext& parseContext,
|
||||
ErrorGuard& errors ) {
|
||||
if (! is_udq(name))
|
||||
if (! is_udq(location.keyword))
|
||||
// Nothing to do
|
||||
return;
|
||||
|
||||
const auto& udq = schedule.getUDQConfig(schedule.size() - 1);
|
||||
|
||||
if (!udq.has_keyword(name)) {
|
||||
std::string msg{"Summary output has been requested for UDQ keyword: " + name + " but it has not been configured"};
|
||||
parseContext.handleError(ParseContext::SUMMARY_UNDEFINED_UDQ, msg, errors);
|
||||
if (!udq.has_keyword(location.keyword)) {
|
||||
std::string msg = "Summary output requested for UDQ {keyword}\n"
|
||||
"In {file} line {line}\n"
|
||||
"No defintion for this UDQ found in the SCHEDULE section";
|
||||
parseContext.handleError(ParseContext::SUMMARY_UNDEFINED_UDQ, msg, location, errors);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!udq.has_unit(name)) {
|
||||
std::string msg{"Summary output has been requested for UDQ keyword: " + name + " but no unit has not been configured"};
|
||||
parseContext.handleError(ParseContext::SUMMARY_UDQ_MISSING_UNIT, msg, errors);
|
||||
if (!udq.has_unit(location.keyword)) {
|
||||
std::string msg = "Summary output requested for UDQ {keyword}\n"
|
||||
"In {file} line {line}\n"
|
||||
"No unit define in the SCHEDULE section";
|
||||
parseContext.handleError(ParseContext::SUMMARY_UDQ_MISSING_UNIT, msg, location, errors);
|
||||
}
|
||||
}
|
||||
|
||||
@ -885,7 +887,7 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
|
||||
using Cat = SummaryConfigNode::Category;
|
||||
|
||||
const auto& name = keyword.name();
|
||||
check_udq( name, schedule, parseContext, errors );
|
||||
check_udq( keyword.location(), schedule, parseContext, errors );
|
||||
|
||||
const auto cat = parseKeywordCategory( name );
|
||||
switch( cat ) {
|
||||
@ -900,8 +902,9 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
|
||||
case Cat::Miscellaneous: return keywordMISC( list, keyword );
|
||||
|
||||
default:
|
||||
std::string msg = "Summary keywords of type: " + to_string( cat ) + " is not supported. Keyword: " + name + " is ignored";
|
||||
parseContext.handleError(ParseContext::SUMMARY_UNHANDLED_KEYWORD, msg, errors);
|
||||
std::string msg_fmt = fmt::format("Summary output keyword {{keyword}} of type {} is not supported\n"
|
||||
"In {{file}} line {{line}}", to_string(cat));
|
||||
parseContext.handleError(ParseContext::SUMMARY_UNHANDLED_KEYWORD, msg_fmt, keyword.location(), errors);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -909,7 +912,7 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
|
||||
|
||||
inline void handleKW( SummaryConfig::keyword_list& list,
|
||||
const std::string& keyword,
|
||||
KeywordLocation loc,
|
||||
const KeywordLocation& location,
|
||||
const Schedule& schedule,
|
||||
const ParseContext& parseContext,
|
||||
ErrorGuard& errors) {
|
||||
@ -918,9 +921,10 @@ inline void handleKW( SummaryConfig::keyword_list& list,
|
||||
if (is_udq(keyword))
|
||||
throw std::logic_error("UDQ keywords not handleded when expanding alias list");
|
||||
|
||||
if (is_aquifer( keyword )) {
|
||||
std::string msg = "Summary keywords of type: Aquifer is not supported. Keyword: " + keyword + " is ignored";
|
||||
parseContext.handleError(ParseContext::SUMMARY_UNHANDLED_KEYWORD, msg, errors);
|
||||
if (is_aquifer(keyword)) {
|
||||
std::string msg = "Summary output keyword {keyword} of type AQUIFER is not supported\n"
|
||||
"In {{file}} line {{line}}";
|
||||
parseContext.handleError(ParseContext::SUMMARY_UNHANDLED_KEYWORD, msg, location, errors);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -928,10 +932,10 @@ inline void handleKW( SummaryConfig::keyword_list& list,
|
||||
const auto cat = parseKeywordCategory( keyword );
|
||||
|
||||
switch( cat ) {
|
||||
case Cat::Well: return keywordW( list, keyword, std::move(loc), schedule );
|
||||
case Cat::Group: return keywordG( list, keyword, std::move(loc), schedule );
|
||||
case Cat::Field: return keywordF( list, keyword, std::move(loc) );
|
||||
case Cat::Miscellaneous: return keywordMISC( list, keyword, std::move(loc));
|
||||
case Cat::Well: return keywordW( list, keyword, location, schedule );
|
||||
case Cat::Group: return keywordG( list, keyword, location, schedule );
|
||||
case Cat::Field: return keywordF( list, keyword, location );
|
||||
case Cat::Miscellaneous: return keywordMISC( list, keyword, location);
|
||||
|
||||
default:
|
||||
throw std::logic_error("Keyword type: " + to_string( cat ) + " is not supported in alias lists. Internal error handling: " + keyword);
|
||||
|
@ -57,12 +57,9 @@ bool checkDeck( const Deck& deck, const Parser& parser, const ParseContext& pars
|
||||
const std::string& fileUnitSystem = uppercase(keyword->getRecord(0).getItem("FILE_UNIT_SYSTEM").getTrimmedString(0));
|
||||
if (fileUnitSystem != deckUnitSystem) {
|
||||
const auto& location = keyword->location();
|
||||
std::string msg =
|
||||
"Unit system " + fileUnitSystem + " specified via the FILEUNIT keyword at "
|
||||
+ location.filename + ":" + std::to_string(location.lineno)
|
||||
+ " does not correspond to the unit system used by the deck ("
|
||||
+ deckUnitSystem + ")";
|
||||
parseContext.handleError(ParseContext::UNIT_SYSTEM_MISMATCH, msg, errorGuard);
|
||||
std::string msg_fmt = "Unit system mismatch\n"
|
||||
"In {file} line {line}";
|
||||
parseContext.handleError(ParseContext::UNIT_SYSTEM_MISMATCH, msg_fmt, location, errorGuard);
|
||||
deckValid = false;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/parser/eclipse/Parser/InputErrorAction.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/common/OpmLog/KeywordLocation.hpp>
|
||||
#include <opm/common/utility/String.hpp>
|
||||
|
||||
namespace Opm {
|
||||
@ -137,6 +138,7 @@ namespace Opm {
|
||||
void ParseContext::handleError(
|
||||
const std::string& errorKey,
|
||||
const std::string& msg,
|
||||
const std::optional<KeywordLocation>& location,
|
||||
ErrorGuard& errors) const {
|
||||
|
||||
InputError::Action action = get( errorKey );
|
||||
@ -175,10 +177,10 @@ namespace Opm {
|
||||
}
|
||||
}
|
||||
|
||||
void ParseContext::handleUnknownKeyword(const std::string& keyword, ErrorGuard& errors) const {
|
||||
void ParseContext::handleUnknownKeyword(const std::string& keyword, const std::optional<KeywordLocation>& location, ErrorGuard& errors) const {
|
||||
if (this->ignore_keywords.find(keyword) == this->ignore_keywords.end()) {
|
||||
std::string msg = "Unknown keyword: " + keyword;
|
||||
this->handleError(ParseContext::PARSE_UNKNOWN_KEYWORD, msg, errors);
|
||||
this->handleError(ParseContext::PARSE_UNKNOWN_KEYWORD, msg, location, errors);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <opm/common/utility/FileSystem.hpp>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
@ -470,7 +472,7 @@ void ParserState::loadFile(const Opm::filesystem::path& inputFile) {
|
||||
inputFileCanonical = Opm::filesystem::canonical(inputFile);
|
||||
} catch (const Opm::filesystem::filesystem_error& fs_error) {
|
||||
std::string msg = "Could not open file: " + inputFile.string();
|
||||
parseContext.handleError( ParseContext::PARSE_MISSING_INCLUDE , msg, errors);
|
||||
parseContext.handleError( ParseContext::PARSE_MISSING_INCLUDE , msg, {}, errors);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -483,8 +485,7 @@ void ParserState::loadFile(const Opm::filesystem::path& inputFile) {
|
||||
// make sure the file we'd like to parse is readable
|
||||
if( !ufp ) {
|
||||
std::string msg = "Could not read from file: " + inputFile.string();
|
||||
|
||||
parseContext.handleError( ParseContext::PARSE_MISSING_INCLUDE , msg, errors);
|
||||
parseContext.handleError( ParseContext::PARSE_MISSING_INCLUDE , msg, {}, errors);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -516,37 +517,28 @@ void ParserState::loadFile(const Opm::filesystem::path& inputFile) {
|
||||
|
||||
void ParserState::handleRandomText(const std::string_view& keywordString ) const {
|
||||
std::string errorKey;
|
||||
std::stringstream msg;
|
||||
std::string trimmedCopy = std::string( keywordString );
|
||||
|
||||
std::string msg;
|
||||
KeywordLocation location{lastKeyWord, this->current_path(), this->line()};
|
||||
|
||||
if (trimmedCopy == "/") {
|
||||
errorKey = ParseContext::PARSE_RANDOM_SLASH;
|
||||
msg << "Extra '/' detected at: "
|
||||
<< this->current_path()
|
||||
<< ":" << this->line();
|
||||
msg = "Extra '/' detected in {file} line {line}";
|
||||
}
|
||||
else if (lastSizeType == OTHER_KEYWORD_IN_DECK) {
|
||||
errorKey = ParseContext::PARSE_EXTRA_RECORDS;
|
||||
msg << "String: \'"
|
||||
<< keywordString
|
||||
<< "\' invalid."
|
||||
<< "Too many records in keyword: "
|
||||
<< lastKeyWord
|
||||
<< " at: "
|
||||
<< this->line()
|
||||
<< ".\n";
|
||||
msg = "Too many records in keyword {keyword}\n"
|
||||
"In {} line {}";
|
||||
}
|
||||
else {
|
||||
errorKey = ParseContext::PARSE_RANDOM_TEXT;
|
||||
msg << "String \'" << keywordString
|
||||
<< "\' not formatted/recognized as valid keyword at: "
|
||||
<< this->current_path()
|
||||
<< ":" << this->line();
|
||||
msg = fmt::format("String {} not formatted as valid keyword\n"
|
||||
"In {{file}} line {{line}}.", keywordString);
|
||||
}
|
||||
parseContext.handleError( errorKey , msg.str(), errors );
|
||||
parseContext.handleError( errorKey , msg, location, errors );
|
||||
}
|
||||
|
||||
|
||||
void ParserState::openRootFile( const Opm::filesystem::path& inputFile) {
|
||||
this->loadFile( inputFile );
|
||||
this->deck.setDataFile( inputFile.string() );
|
||||
@ -643,9 +635,13 @@ RawKeyword * newRawKeyword(const ParserKeyword& parserKeyword, const std::string
|
||||
targetSize);
|
||||
}
|
||||
|
||||
std::string msg = "Expected the kewyord: " +keyword_size.keyword
|
||||
+ " to infer the number of records in: " + keywordString;
|
||||
parserState.parseContext.handleError(ParseContext::PARSE_MISSING_DIMS_KEYWORD , msg, parserState.errors );
|
||||
std::string msg_fmt = fmt::format("Problem with {{keyword}} - missing {0}\n"
|
||||
"In {{file}} line {{line}}\n"
|
||||
"For the keyword {{keyword}} we expect to read the number of records from keyword {0}, {0} was not found", keyword_size.keyword);
|
||||
parserState.parseContext.handleError(ParseContext::PARSE_MISSING_DIMS_KEYWORD ,
|
||||
msg_fmt,
|
||||
KeywordLocation{keywordString, parserState.current_path().string(), parserState.line()},
|
||||
parserState.errors );
|
||||
|
||||
const auto& keyword = parser.getKeyword( keyword_size.keyword );
|
||||
const auto& record = keyword.getRecord(0);
|
||||
@ -665,14 +661,18 @@ RawKeyword * newRawKeyword( const std::string& deck_name, ParserState& parserSta
|
||||
if (deck_name.size() > RawConsts::maxKeywordLength) {
|
||||
const std::string keyword8 = deck_name.substr(0, RawConsts::maxKeywordLength);
|
||||
if (parser.isRecognizedKeyword(keyword8)) {
|
||||
std::string msg = "Keyword: " + deck_name + " too long - only first eight characters recognized";
|
||||
parserState.parseContext.handleError(ParseContext::PARSE_LONG_KEYWORD, msg, parserState.errors);
|
||||
std::string msg = "Keyword {keyword} to long - only eight first characters recognized\n"
|
||||
"In {file} line {line}\n";
|
||||
parserState.parseContext.handleError(ParseContext::PARSE_LONG_KEYWORD,
|
||||
msg,
|
||||
KeywordLocation{deck_name, parserState.current_path().string(), parserState.line()},
|
||||
parserState.errors);
|
||||
|
||||
parserState.unknown_keyword = false;
|
||||
const auto& parserKeyword = parser.getParserKeywordFromDeckName( keyword8 );
|
||||
return newRawKeyword(parserKeyword, keyword8, parserState, parser);
|
||||
} else {
|
||||
parserState.parseContext.handleUnknownKeyword( deck_name, parserState.errors );
|
||||
parserState.parseContext.handleUnknownKeyword( deck_name, KeywordLocation{}, parserState.errors );
|
||||
parserState.unknown_keyword = true;
|
||||
return nullptr;
|
||||
}
|
||||
@ -685,7 +685,7 @@ RawKeyword * newRawKeyword( const std::string& deck_name, ParserState& parserSta
|
||||
}
|
||||
|
||||
if( ParserKeyword::validDeckName(deck_name) ) {
|
||||
parserState.parseContext.handleUnknownKeyword( deck_name, parserState.errors );
|
||||
parserState.parseContext.handleUnknownKeyword( deck_name, KeywordLocation{}, parserState.errors );
|
||||
parserState.unknown_keyword = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
@ -119,7 +121,6 @@ namespace {
|
||||
return *itr;
|
||||
}
|
||||
|
||||
|
||||
DeckRecord ParserRecord::parse(const ParseContext& parseContext , ErrorGuard& errors , RawRecord& rawRecord, UnitSystem& active_unitsystem, UnitSystem& default_unitsystem, const KeywordLocation& location) const {
|
||||
std::vector< DeckItem > items;
|
||||
items.reserve( this->size() + 20 );
|
||||
@ -127,10 +128,10 @@ namespace {
|
||||
items.emplace_back( parserItem.scan( rawRecord, active_unitsystem, default_unitsystem ) );
|
||||
|
||||
if (rawRecord.size() > 0) {
|
||||
std::string msg = "The RawRecord for keyword \"" + location.keyword + "\" in file\"" + location.filename + "\" contained " +
|
||||
std::to_string(rawRecord.size()) +
|
||||
" too many items according to the spec. RawRecord was: " + rawRecord.getRecordString();
|
||||
parseContext.handleError(ParseContext::PARSE_EXTRA_DATA , msg, errors);
|
||||
std::string msg_format = fmt::format("Record contains too many items in keyword {{0}}. Expected {} items, found {}.\n", this->size(), rawRecord.max_size()) +
|
||||
"In file {1} at line {2}.\n" +
|
||||
fmt::format("Record is \"{}\".", rawRecord.getRecordString());
|
||||
parseContext.handleError(ParseContext::PARSE_EXTRA_DATA , msg_format, location, errors);
|
||||
}
|
||||
|
||||
return { std::move( items ) };
|
||||
|
@ -1,6 +0,0 @@
|
||||
|
||||
|
||||
Errors:
|
||||
RUNSPEC_GROUPSIZE_TOO_LARGE: Run uses maximum group size of 6, but allocates at most 4 in RUNSPEC section. Increase item 4 of WELLDIMS accordingly.
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
|
||||
|
||||
Errors:
|
||||
RUNSPEC_NUMWELLS_TOO_LARGE : Run uses 12 wells, but allocates at most 0 in RUNSPEC section. Increase item 1 of WELLDIMS accordingly.
|
||||
RUNSPEC_CONNS_PER_WELL_TOO_LARGE: Run has well with 15 reservoir connections, but allocates at most 0 connections per well in RUNSPEC section. Increase item 2 of WELLDIMS accordingly.
|
||||
RUNSPEC_NUMGROUPS_TOO_LARGE : Run uses 11 non-FIELD groups, but allocates at most 0 in RUNSPEC section. Increase item 3 of WELLDIMS accordingly.
|
||||
RUNSPEC_GROUPSIZE_TOO_LARGE : Run uses maximum group size of 10, but allocates at most 0 in RUNSPEC section. Increase item 4 of WELLDIMS accordingly.
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/IOConfig/RestartConfig.hpp>
|
||||
#include <opm/parser/eclipse/Utility/Functional.hpp>
|
||||
#include <opm/common/utility/OpmInputError.hpp>
|
||||
|
||||
inline std::string fst( const std::pair< std::string, int >& p ) {
|
||||
return p.first;
|
||||
@ -620,7 +621,7 @@ BOOST_AUTO_TEST_CASE(RPTRST_FORMAT_ERROR) {
|
||||
|
||||
// The case "BASIC 1" - i.e. without '=' can not be salvaged; this should
|
||||
// give an exception whatever is the value of ParseContext::RPT_MIXED_STYLE:
|
||||
BOOST_CHECK_THROW(RestartConfig(TimeMap(deck0), deck0, ctx, errors), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(RestartConfig(TimeMap(deck0), deck0, ctx, errors), OpmInputError);
|
||||
|
||||
|
||||
// Observe that this is true due to some undocumented guessing that
|
||||
|
@ -74,9 +74,10 @@ BOOST_AUTO_TEST_CASE(TYPE_COERCION) {
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GROUP_VARIABLES)
|
||||
{
|
||||
KeywordLocation location;
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft;
|
||||
UDQDefine def_group(udqp, "GUOPRL",{"(", "5000", "-", "GOPR", "LOWER", "*", "0.13", "-", "GOPR", "UPPER", "*", "0.15", ")" , "*", "0.89"});
|
||||
UDQDefine def_group(udqp, "GUOPRL", location, {"(", "5000", "-", "GOPR", "LOWER", "*", "0.13", "-", "GOPR", "UPPER", "*", "0.15", ")" , "*", "0.89"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -95,10 +96,11 @@ BOOST_AUTO_TEST_CASE(GROUP_VARIABLES)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SUBTRACT)
|
||||
{
|
||||
KeywordLocation location;
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft;
|
||||
UDQDefine def(udqp, "WU", {"16", "-", "8", "-", "4", "-", "2", "-", "1"});
|
||||
UDQDefine scalar(udqp, "WU", {"16"});
|
||||
UDQDefine def(udqp, "WU", location, {"16", "-", "8", "-", "4", "-", "2", "-", "1"});
|
||||
UDQDefine scalar(udqp, "WU", location, {"16"});
|
||||
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
@ -114,12 +116,13 @@ BOOST_AUTO_TEST_CASE(SUBTRACT)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TEST)
|
||||
{
|
||||
KeywordLocation location;
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft;
|
||||
UDQDefine def1(udqp, "WUWI3", {"GOPR" , "MAU", "*", "2.0", "*", "0.25", "*", "10"});
|
||||
UDQDefine def2(udqp, "WUWI3", {"2.0", "*", "0.25", "*", "3"});
|
||||
UDQDefine def3(udqp, "WUWI3", {"GOPR" , "FIELD", "-", "2.0", "*", "3"});
|
||||
UDQDefine def4(udqp, "WUWI3", {"FOPR" , "/", "2"});
|
||||
UDQDefine def1(udqp, "WUWI3", location, {"GOPR" , "MAU", "*", "2.0", "*", "0.25", "*", "10"});
|
||||
UDQDefine def2(udqp, "WUWI3", location, {"2.0", "*", "0.25", "*", "3"});
|
||||
UDQDefine def3(udqp, "WUWI3", location, {"GOPR" , "FIELD", "-", "2.0", "*", "3"});
|
||||
UDQDefine def4(udqp, "WUWI3", location, {"FOPR" , "/", "2"});
|
||||
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
@ -152,19 +155,20 @@ BOOST_AUTO_TEST_CASE(TEST)
|
||||
This expression has a well set as target type, and involves group with
|
||||
wildcard that is not supported by flow.
|
||||
*/
|
||||
BOOST_CHECK_THROW( UDQDefine(udqp, "WUWI2", {"GOPR", "G*", "*", "2.0"}), std::logic_error);
|
||||
BOOST_CHECK_THROW( UDQDefine(udqp, "WUWI2", location, {"GOPR", "G*", "*", "2.0"}), std::logic_error);
|
||||
|
||||
/*
|
||||
UDQVarType == BLOCK is not yet supported.
|
||||
*/
|
||||
BOOST_CHECK_THROW( UDQDefine(udqp, "WUWI2", {"BPR", "1","1", "1", "*", "2.0"}), std::logic_error);
|
||||
BOOST_CHECK_THROW( UDQDefine(udqp, "WUWI2", location, {"BPR", "1","1", "1", "*", "2.0"}), std::logic_error);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(MIX_SCALAR) {
|
||||
UDQFunctionTable udqft;
|
||||
UDQParams udqp;
|
||||
UDQDefine def_add(udqp, "WU", {"WOPR", "+", "1"});
|
||||
KeywordLocation location;
|
||||
UDQDefine def_add(udqp, "WU", location, {"WOPR", "+", "1"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -178,13 +182,15 @@ BOOST_AUTO_TEST_CASE(MIX_SCALAR) {
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQ_TABLE_EXCEPTION) {
|
||||
UDQParams udqp;
|
||||
BOOST_CHECK_THROW(UDQDefine(udqp, "WU", {"TUPRICE[WOPR]"}), std::invalid_argument);
|
||||
KeywordLocation location;
|
||||
BOOST_CHECK_THROW(UDQDefine(udqp, "WU", location, {"TUPRICE[WOPR]"}), std::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQFieldSetTest) {
|
||||
std::vector<std::string> wells = {"P1", "P2", "P3", "P4"};
|
||||
KeywordLocation location;
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft(udqp);
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
@ -205,7 +211,7 @@ BOOST_AUTO_TEST_CASE(UDQFieldSetTest) {
|
||||
*/
|
||||
|
||||
{
|
||||
UDQDefine def_fopr(udqp, "FUOPR", {"SUM", "(", "WOPR", ")"});
|
||||
UDQDefine def_fopr(udqp, "FUOPR", location, {"SUM", "(", "WOPR", ")"});
|
||||
auto fopr_res = def_fopr.eval(context);
|
||||
BOOST_CHECK_EQUAL( fopr_res[0].get(), 10.0 );
|
||||
}
|
||||
@ -286,9 +292,10 @@ BOOST_AUTO_TEST_CASE(UDQ_GROUP_TEST) {
|
||||
const auto& value = gs["G1"];
|
||||
BOOST_CHECK_EQUAL(value.get(), 1.0);
|
||||
{
|
||||
KeywordLocation location;
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft(udqp);
|
||||
UDQDefine def_fopr(udqp, "FUOPR", {"SUM", "(", "GOPR", ")"});
|
||||
UDQDefine def_fopr(udqp, "FUOPR", location, {"SUM", "(", "GOPR", ")"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -309,8 +316,9 @@ BOOST_AUTO_TEST_CASE(UDQ_GROUP_TEST) {
|
||||
BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft(udqp);
|
||||
KeywordLocation location;
|
||||
{
|
||||
UDQDefine def(udqp, "WUBHP", {"WBHP"});
|
||||
UDQDefine def(udqp, "WUBHP", location, {"WBHP"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -325,7 +333,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
|
||||
BOOST_CHECK_EQUAL( res["W3"].get(), 3 );
|
||||
}
|
||||
{
|
||||
UDQDefine def(udqp, "WUBHP", {"WBHP" , "'P*'"});
|
||||
UDQDefine def(udqp, "WUBHP", location, {"WBHP" , "'P*'"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -343,7 +351,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
|
||||
BOOST_CHECK_EQUAL( res["I1"].defined(), false);
|
||||
}
|
||||
{
|
||||
UDQDefine def(udqp, "WUBHP", {"NINT" , "(", "WBHP", ")"});
|
||||
UDQDefine def(udqp, "WUBHP", location, {"NINT" , "(", "WBHP", ")"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -966,10 +974,11 @@ BOOST_AUTO_TEST_CASE(UDQASSIGN_TEST) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQ_POW_TEST) {
|
||||
KeywordLocation location;
|
||||
UDQFunctionTable udqft;
|
||||
UDQParams udqp;
|
||||
UDQDefine def_pow1(udqp, "WU", {"WOPR", "+", "WWPR", "*", "WGOR", "^", "WWIR"});
|
||||
UDQDefine def_pow2(udqp, "WU", {"(", "WOPR", "+", "WWPR", ")", "^", "(", "WOPR", "+" , "WGOR", "*", "WWIR", "-", "WOPT", ")"});
|
||||
UDQDefine def_pow1(udqp, "WU", location, {"WOPR", "+", "WWPR", "*", "WGOR", "^", "WWIR"});
|
||||
UDQDefine def_pow2(udqp, "WU", location, {"(", "WOPR", "+", "WWPR", ")", "^", "(", "WOPR", "+" , "WGOR", "*", "WWIR", "-", "WOPT", ")"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -987,9 +996,10 @@ BOOST_AUTO_TEST_CASE(UDQ_POW_TEST) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQ_CMP_TEST) {
|
||||
KeywordLocation location;
|
||||
UDQFunctionTable udqft;
|
||||
UDQParams udqp;
|
||||
UDQDefine def_cmp(udqp, "WU", {"WOPR", ">", "WWPR", "+", "WGOR", "*", "WWIR"});
|
||||
UDQDefine def_cmp(udqp, "WU", location, {"WOPR", ">", "WWPR", "+", "WGOR", "*", "WWIR"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -1016,6 +1026,7 @@ BOOST_AUTO_TEST_CASE(UDQ_CMP_TEST) {
|
||||
*/
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
|
||||
KeywordLocation location;
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft;
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
@ -1033,7 +1044,7 @@ BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
|
||||
st.update_well_var("P4", "WWPR", 4);
|
||||
|
||||
{
|
||||
UDQDefine def(udqp, "WUOPR", {"WOPR", "'*1'"});
|
||||
UDQDefine def(udqp, "WUOPR", location, {"WOPR", "'*1'"});
|
||||
auto res = def.eval(context);
|
||||
BOOST_CHECK_EQUAL(4, res.size());
|
||||
auto well1 = res["P1"];
|
||||
@ -1047,7 +1058,7 @@ BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
|
||||
BOOST_CHECK( !well4.defined() );
|
||||
}
|
||||
{
|
||||
UDQDefine def(udqp, "WUOPR", {"1"});
|
||||
UDQDefine def(udqp, "WUOPR", location, {"1"});
|
||||
auto res = def.eval(context);
|
||||
BOOST_CHECK_EQUAL(4, res.size());
|
||||
auto well1 = res["P1"];
|
||||
@ -1063,7 +1074,7 @@ BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
|
||||
BOOST_CHECK_EQUAL(well4.get() , 1);
|
||||
}
|
||||
{
|
||||
UDQDefine def(udqp, "WUOPR", {"WOPR", "'P1'"});
|
||||
UDQDefine def(udqp, "WUOPR", location, {"WOPR", "'P1'"});
|
||||
auto res = def.eval(context);
|
||||
BOOST_CHECK_EQUAL(4, res.size());
|
||||
auto well1 = res["P1"];
|
||||
@ -1085,8 +1096,9 @@ BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
|
||||
BOOST_AUTO_TEST_CASE(UDQ_SORTD_NAN) {
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft;
|
||||
UDQDefine def(udqp, "WUPR1" , {"1", "/", "(", "WWIR", "'OP*'" , ")"});
|
||||
UDQDefine def_sort(udqp , "WUPR3", {"SORTD", "(", "WUPR1", ")" });
|
||||
KeywordLocation location;
|
||||
UDQDefine def(udqp, "WUPR1" , location, {"1", "/", "(", "WWIR", "'OP*'" , ")"});
|
||||
UDQDefine def_sort(udqp , "WUPR3", location, {"SORTD", "(", "WUPR1", ")" });
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -1126,10 +1138,11 @@ BOOST_AUTO_TEST_CASE(UDQ_SORTD_NAN) {
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQ_SORTA) {
|
||||
KeywordLocation location;
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft;
|
||||
UDQDefine def1(udqp, "WUPR1" , {"1", "/", "(", "WWCT", "'OP*'", "+", "0.00001", ")"});
|
||||
UDQDefine def_sort(udqp , "WUPR3", {"SORTA", "(", "WUPR1", ")" });
|
||||
UDQDefine def1(udqp, "WUPR1" , location, {"1", "/", "(", "WWCT", "'OP*'", "+", "0.00001", ")"});
|
||||
UDQDefine def_sort(udqp , "WUPR3", location, {"SORTA", "(", "WUPR1", ")" });
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -1156,12 +1169,13 @@ BOOST_AUTO_TEST_CASE(UDQ_SORTA) {
|
||||
BOOST_AUTO_TEST_CASE(UDQ_BASIC_MATH_TEST) {
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft;
|
||||
UDQDefine def_add(udqp, "WU2OPR", {"WOPR", "+", "WOPR"});
|
||||
UDQDefine def_sub(udqp, "WU2OPR", {"WOPR", "-", "WOPR"});
|
||||
UDQDefine def_mul(udqp, "WU2OPR", {"WOPR", "*", "WOPR"});
|
||||
UDQDefine def_div(udqp, "WU2OPR", {"WOPR", "/", "WOPR"});
|
||||
UDQDefine def_muladd(udqp , "WUX", {"WOPR", "+", "WOPR", "*", "WOPR"});
|
||||
UDQDefine def_wuwct(udqp , "WUWCT", {"WWPR", "/", "(", "WOPR", "+", "WWPR", ")"});
|
||||
KeywordLocation location;
|
||||
UDQDefine def_add(udqp, "WU2OPR", location, {"WOPR", "+", "WOPR"});
|
||||
UDQDefine def_sub(udqp, "WU2OPR", location, {"WOPR", "-", "WOPR"});
|
||||
UDQDefine def_mul(udqp, "WU2OPR", location, {"WOPR", "*", "WOPR"});
|
||||
UDQDefine def_div(udqp, "WU2OPR", location, {"WOPR", "/", "WOPR"});
|
||||
UDQDefine def_muladd(udqp, "WUX", location, {"WOPR", "+", "WOPR", "*", "WOPR"});
|
||||
UDQDefine def_wuwct(udqp , "WUWCT", location, {"WWPR", "/", "(", "WOPR", "+", "WWPR", ")"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -1220,9 +1234,10 @@ BOOST_AUTO_TEST_CASE(UDQ_BASIC_MATH_TEST) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DECK_TEST) {
|
||||
KeywordLocation location;
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft(udqp);
|
||||
UDQDefine def(udqp, "WUOPRL", {"(", "WOPR", "OP1", "-", "150", ")", "*", "0.90"});
|
||||
UDQDefine def(udqp, "WUOPRL", location, {"(", "WOPR", "OP1", "-", "150", ")", "*", "0.90"});
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
UDQContext context(udqft, st, udq_state);
|
||||
@ -1239,11 +1254,12 @@ BOOST_AUTO_TEST_CASE(DECK_TEST) {
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQPARSE_TEST1) {
|
||||
KeywordLocation location;
|
||||
UDQParams udqp;
|
||||
UDQDefine def1(udqp, "WUBHP", {"1/(WWCT", "'W1*')"});
|
||||
UDQDefine def1(udqp, "WUBHP", location, {"1/(WWCT", "'W1*')"});
|
||||
BOOST_CHECK_EQUAL( def1.input_string() , "1/(WWCT 'W1*')");
|
||||
|
||||
UDQDefine def2(udqp, "WUBHP", {"2*(1", "+" , "WBHP)"});
|
||||
UDQDefine def2(udqp, "WUBHP", location, {"2*(1", "+" , "WBHP)"});
|
||||
BOOST_CHECK_EQUAL( def2.input_string() , "2*(1 + WBHP)");
|
||||
}
|
||||
|
||||
@ -1253,9 +1269,10 @@ BOOST_AUTO_TEST_CASE(UDQ_PARSE_ERROR) {
|
||||
ParseContext parseContext;
|
||||
ErrorGuard errors;
|
||||
std::vector<std::string> tokens = {"WBHP", "+"};
|
||||
KeywordLocation location;
|
||||
parseContext.update(ParseContext::UDQ_PARSE_ERROR, InputError::IGNORE);
|
||||
{
|
||||
UDQDefine def1(udqp, "WUBHP", tokens, parseContext, errors);
|
||||
UDQDefine def1(udqp, "WUBHP", location, tokens, parseContext, errors);
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQFunctionTable udqft(udqp);
|
||||
UDQState udq_state(udqp.undefinedValue());
|
||||
@ -1267,7 +1284,7 @@ BOOST_AUTO_TEST_CASE(UDQ_PARSE_ERROR) {
|
||||
}
|
||||
|
||||
parseContext.update(ParseContext::UDQ_PARSE_ERROR, InputError::THROW_EXCEPTION);
|
||||
BOOST_CHECK_THROW( UDQDefine(udqp, "WUBHP", tokens, parseContext, errors), std::invalid_argument);
|
||||
BOOST_CHECK_THROW( UDQDefine(udqp, "WUBHP", location, tokens, parseContext, errors), std::invalid_argument);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
|
||||
@ -1276,10 +1293,11 @@ BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
|
||||
ErrorGuard errors;
|
||||
std::vector<std::string> tokens1 = {"WBHP", "+", "1"};
|
||||
std::vector<std::string> tokens2 = {"SUM", "(", "WBHP", ")"};
|
||||
KeywordLocation location;
|
||||
parseContext.update(ParseContext::UDQ_TYPE_ERROR, InputError::IGNORE);
|
||||
{
|
||||
UDQDefine def1(udqp, "FUBHP", tokens1, parseContext, errors);
|
||||
UDQDefine def2(udqp, "WUBHP", tokens2, parseContext, errors);
|
||||
UDQDefine def1(udqp, "FUBHP", location, tokens1, parseContext, errors);
|
||||
UDQDefine def2(udqp, "WUBHP", location, tokens2, parseContext, errors);
|
||||
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
UDQFunctionTable udqft(udqp);
|
||||
@ -1300,7 +1318,7 @@ BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
|
||||
parseContext.update(ParseContext::UDQ_TYPE_ERROR, InputError::THROW_EXCEPTION);
|
||||
|
||||
// This fails because the well expression (WBHP + 1) is assigned to the field variable FUBHP
|
||||
BOOST_CHECK_THROW( UDQDefine(udqp, "FUBHP", tokens1, parseContext, errors), std::invalid_argument);
|
||||
BOOST_CHECK_THROW( UDQDefine(udqp, "FUBHP", location, tokens1, parseContext, errors), std::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,12 +21,6 @@
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/version.hpp>
|
||||
#if BOOST_VERSION / 100000 == 1 && BOOST_VERSION / 100 % 1000 < 71
|
||||
#include <boost/test/output_test_stream.hpp>
|
||||
#else
|
||||
#include <boost/test/tools/output_test_stream.hpp>
|
||||
#endif
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ArrayDimChecker.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Python/Python.hpp>
|
||||
@ -445,14 +439,18 @@ BOOST_AUTO_TEST_CASE(WellDims)
|
||||
// There *should* be errors from dimension checking
|
||||
BOOST_CHECK(cse.guard);
|
||||
|
||||
// Verify that we get expected output from ErrorGuard::dump()
|
||||
boost::test_tools::output_test_stream output{"expect-wdims.err.out", true};
|
||||
{
|
||||
RedirectCERR stream(output.rdbuf());
|
||||
std::stringstream estream;
|
||||
RedirectCERR stream(estream.rdbuf());
|
||||
|
||||
cse.guard.dump();
|
||||
const auto error_msg = estream.str();
|
||||
|
||||
BOOST_CHECK(output.match_pattern());
|
||||
for (const auto& s : {"RUNSPEC_NUMWELLS_TOO_LARGE", "item 1",
|
||||
"RUNSPEC_CONNS_PER_WELL_TOO_LARGE", "item 2",
|
||||
"RUNSPEC_NUMGROUPS_TOO_LARGE", "item 3",
|
||||
"RUNSPEC_GROUPSIZE_TOO_LARGE", "item 4"})
|
||||
BOOST_CHECK( error_msg.find(s) != std::string::npos );
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,13 +477,15 @@ BOOST_AUTO_TEST_CASE(WellDims_ManyChildGroups)
|
||||
BOOST_CHECK(cse.guard);
|
||||
|
||||
// Verify that we get expected output from ErrorGuard::dump()
|
||||
boost::test_tools::output_test_stream output{"expect-wdims.chldg.err.out", true};
|
||||
{
|
||||
RedirectCERR stream(output.rdbuf());
|
||||
std::stringstream estream;
|
||||
RedirectCERR stream(estream.rdbuf());
|
||||
|
||||
cse.guard.dump();
|
||||
const auto error_msg = estream.str();
|
||||
|
||||
BOOST_CHECK(output.match_pattern());
|
||||
for (const auto& s : {"RUNSPEC_GROUPSIZE_TOO_LARGE", "item 4"})
|
||||
BOOST_CHECK( error_msg.find(s) != std::string::npos );
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user