Better error handling for problems in conditions of ACTIONX.
When encountering these (e.g. a number instead of an expression on the left hand side) the simulator would immediately abort with an error message like: ``` Error: An error occurred while creating the reservoir schedule Internal error: Extra unhandled data starting with token[0] = 135 Error: Unrecoverable errors while loading input: Extra unhandled data starting with token[0] = 135 ``` (The message above is for the number 135 on the left hand side) With this change we now use the usual way of handling errors and warnings in the parser and continue parsing. The error message for the problem above is now ``` Error: condition of action EX1 has the following error: Left side of comparsion (135) has to be an expression! Error: Problem with keyword ACTIONX In model.schedule line 562 condition of action EX1 has the following error: Left side of comparsion (135) has to be an expression! Error: Unrecoverable errors while loading input: Problem with keyword ACTIONX In model.schedule line 562 condition of action EX1 has the following error: Left side of comparsion (135) has to be an expression!
This commit is contained in:
parent
722c3592a4
commit
f04ada2d44
@ -314,6 +314,14 @@ class KeywordLocation;
|
||||
*/
|
||||
const static std::string ACTIONX_ILLEGAL_KEYWORD;
|
||||
|
||||
/*
|
||||
Error flag marking parser errors ic ACTIONX conditions
|
||||
*/
|
||||
const static std::string ACTIONX_CONDITION_ERROR;
|
||||
/*
|
||||
Error flag marking that an ACTIONX has no condition
|
||||
*/
|
||||
const static std::string ACTIONX_NO_CONDITION;
|
||||
|
||||
/*
|
||||
The RPTSCH, RPTSOL and RPTSCHED keywords have two alternative forms,
|
||||
|
@ -75,7 +75,8 @@ class ActionX {
|
||||
public:
|
||||
ActionX();
|
||||
ActionX(const std::string& name, size_t max_run, double max_wait, std::time_t start_time);
|
||||
ActionX(const DeckKeyword& kw, const Actdims& actimds, std::time_t start_time);
|
||||
ActionX(const DeckKeyword& kw, const Actdims& actimds, std::time_t start_time,
|
||||
std::vector<std::pair<std::string, std::string>>& condition_errors);
|
||||
ActionX(const DeckRecord& record, std::time_t start_time);
|
||||
explicit ActionX(const RestartIO::RstAction& rst_action);
|
||||
|
||||
|
@ -114,6 +114,8 @@ namespace Opm {
|
||||
this->addKey(SUMMARY_REGION_TOO_LARGE, InputErrorAction::WARN);
|
||||
|
||||
addKey(ACTIONX_ILLEGAL_KEYWORD, InputErrorAction::THROW_EXCEPTION);
|
||||
addKey(ACTIONX_CONDITION_ERROR, InputErrorAction::THROW_EXCEPTION);
|
||||
addKey(ACTIONX_NO_CONDITION, InputErrorAction::WARN);
|
||||
|
||||
addKey(RPT_MIXED_STYLE, InputErrorAction::WARN);
|
||||
addKey(RPT_UNKNOWN_MNEMONIC, InputErrorAction::WARN);
|
||||
@ -369,6 +371,8 @@ namespace Opm {
|
||||
|
||||
const std::string ParseContext::SCHEDULE_INVALID_NAME = "SCHEDULE_INVALID_NAME";
|
||||
const std::string ParseContext::ACTIONX_ILLEGAL_KEYWORD = "ACTIONX_ILLEGAL_KEYWORD";
|
||||
const std::string ParseContext::ACTIONX_CONDITION_ERROR = "ACTIONX_CONDITION_ERROR";
|
||||
const std::string ParseContext::ACTIONX_NO_CONDITION = "ACTIONX_NO_CONDITION";
|
||||
|
||||
const std::string ParseContext::SIMULATOR_KEYWORD_NOT_SUPPORTED = "SIMULATOR_KEYWORD_NOT_SUPPORTED";
|
||||
const std::string ParseContext::SIMULATOR_KEYWORD_NOT_SUPPORTED_CRITICAL = "SIMULATOR_KEYWORD_NOT_SUPPORTED_CRITICAL";
|
||||
|
@ -128,7 +128,9 @@ ParseNode Parser::current() const {
|
||||
Action::ASTNode Parser::parse_left() {
|
||||
auto current = this->current();
|
||||
if (current.type != TokenType::ecl_expr)
|
||||
return TokenType::error;
|
||||
throw std::invalid_argument("Left side of comparison ("
|
||||
+ current.value + ") has to be "
|
||||
"an expression!");
|
||||
|
||||
std::string func = current.value;
|
||||
FuncType func_type = get_func(current.value);
|
||||
@ -270,15 +272,17 @@ Action::ASTNode Parser::parse(const std::vector<std::string>& tokens) {
|
||||
return ASTNode( start_node.type );
|
||||
|
||||
auto tree = parser.parse_or();
|
||||
|
||||
if (tree.type == TokenType::error)
|
||||
throw std::invalid_argument("Failed to parse ACTIONX condition.");
|
||||
|
||||
auto current = parser.current();
|
||||
if (current.type != TokenType::end) {
|
||||
size_t index = parser.current_pos;
|
||||
throw std::invalid_argument("Extra unhandled data starting with token[" + std::to_string(index) + "] = " + current.value);
|
||||
throw std::invalid_argument("Extra unhandled data starting with token[" + std::to_string(index) + "] = " + current.value+
|
||||
" in ACTIONX condition.");
|
||||
}
|
||||
|
||||
if (tree.type == TokenType::error)
|
||||
throw std::invalid_argument("Failed to parse");
|
||||
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <opm/input/eclipse/Schedule/Action/Actdims.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Action/State.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellMatcher.hpp>
|
||||
#include <opm/input/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
||||
#include <opm/io/eclipse/rst/action.hpp>
|
||||
#include <opm/common/utility/OpmInputError.hpp>
|
||||
@ -119,7 +120,7 @@ ActionX::ActionX(const DeckRecord& record, std::time_t start_time) :
|
||||
|
||||
|
||||
|
||||
ActionX::ActionX(const DeckKeyword& kw, const Actdims& actdims, std::time_t start_time) :
|
||||
ActionX::ActionX(const DeckKeyword& kw, const Actdims& actdims, std::time_t start_time, std::vector<std::pair<std::string, std::string>>& condition_errors) :
|
||||
ActionX(kw.getRecord(0), start_time)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
@ -132,10 +133,22 @@ ActionX::ActionX(const DeckKeyword& kw, const Actdims& actdims, std::time_t star
|
||||
|
||||
this->m_conditions.emplace_back(cond_tokens, kw.location());
|
||||
}
|
||||
if (this->m_conditions.size() > actdims.max_conditions())
|
||||
throw OpmInputError(fmt::format("Action {} has too many conditions - adjust item 4 of ACTDIMS to at least {}", this->name(), this->m_conditions.size()), kw.location());
|
||||
if (this->m_conditions.empty())
|
||||
condition_errors.push_back({ParseContext::ACTIONX_NO_CONDITION, fmt::format("Action {} is missing a condition.", this->name())});
|
||||
|
||||
this->condition = Action::AST(tokens);
|
||||
if (this->m_conditions.size() > actdims.max_conditions())
|
||||
condition_errors.push_back({ ParseContext::ACTIONX_CONDITION_ERROR,
|
||||
fmt::format("Action {} has too many conditions - adjust item 4 of ACTDIMS to at least {}", this->name(), this->m_conditions.size())});
|
||||
|
||||
try
|
||||
{
|
||||
this->condition = Action::AST(tokens);
|
||||
}
|
||||
catch(const std::invalid_argument& e)
|
||||
{
|
||||
condition_errors.push_back({ ParseContext::ACTIONX_CONDITION_ERROR,
|
||||
fmt::format("condition of action {} has the following error: {}", this->name(), e.what())});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -665,9 +665,16 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
|
||||
logger.location(location);
|
||||
|
||||
if (keyword.is<ParserKeywords::ACTIONX>()) {
|
||||
std::vector<std::pair<std::string, std::string>> condition_errors; //condition is parsed by ActionX constructor
|
||||
Action::ActionX action(keyword,
|
||||
this->m_static.m_runspec.actdims(),
|
||||
std::chrono::system_clock::to_time_t(this->snapshots[report_step].start_time()));
|
||||
std::chrono::system_clock::to_time_t(this->snapshots[report_step].start_time()),
|
||||
condition_errors);
|
||||
|
||||
for(const auto& [ marker, msg]: condition_errors) {
|
||||
parseContext.handleError(marker, msg, keyword.location(), errors);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
keyword_index++;
|
||||
if (keyword_index == block.size())
|
||||
|
@ -87,8 +87,25 @@ ACTIONX
|
||||
const auto deck = Parser{}.parseString( action_kw );
|
||||
const auto& kw = deck["ACTIONX"].back();
|
||||
|
||||
Action::ActionX action2(kw, {}, 0);
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> condition_errors;
|
||||
Action::ActionX action2(kw, {}, 0, condition_errors);
|
||||
BOOST_CHECK_EQUAL(action2.name(), "ACTION");
|
||||
|
||||
// left hand side has to be an expression.
|
||||
// Check whether we add an error to condition_errors
|
||||
// if that is not the case
|
||||
const auto action_kw_num_first = std::string{ R"(
|
||||
ACTIONX
|
||||
'ACTION' /
|
||||
0.75 < WWCT OPX /
|
||||
/
|
||||
)"};
|
||||
|
||||
condition_errors.clear();
|
||||
const auto deck1 = Parser{}.parseString( action_kw_num_first);
|
||||
const auto action3 = Action::ActionX(deck1["ACTIONX"].back(), {}, 0, condition_errors);
|
||||
BOOST_CHECK_EQUAL(condition_errors.size(), 1U);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user