Changed UDQDefine to take UDQParams argument

This commit is contained in:
Joakim Hove
2019-03-11 11:43:23 +01:00
parent ef5f90c12b
commit c9821faddc
10 changed files with 118 additions and 51 deletions

View File

@@ -37,16 +37,18 @@ class ErrorGuard;
class UDQDefine{
public:
UDQDefine(const UDQFunctionTable& udqft, const std::string& keyword, const std::vector<std::string>& deck_data);
UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
const std::vector<std::string>& deck_data);
UDQDefine(const UDQFunctionTable& udqft,
UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
const std::vector<std::string>& deck_data,
const ParseContext& parseContext,
ErrorGuard& errors);
template <typename T>
UDQDefine(const UDQFunctionTable& udqft,
UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
const std::vector<std::string>& deck_data,
const ParseContext& parseContext,
@@ -62,10 +64,10 @@ public:
std::vector<std::string> tokens;
UDQVarType var_type() const;
private:
const UDQParams& udq_params; // Beacuse of the shared RNG stream this must be a reference.
std::string m_keyword;
std::shared_ptr<UDQASTNode> ast;
UDQVarType m_var_type;
UDQFunctionTable udqft;
};
}

View File

@@ -247,6 +247,7 @@ namespace Opm {
*/
const static std::string UNSUPPORTED_TERMINATE_IF_BHP;
const static std::string UDQ_PARSE_ERROR;
/*
If the third item in the THPRES keyword is defaulted the

View File

@@ -43,6 +43,12 @@ UDQASTNode::UDQASTNode(UDQTokenType type) :
throw std::invalid_argument("The one argument constructor is only available for error and end");
}
UDQASTNode::UDQASTNode(double scalar_value) :
type(UDQTokenType::number),
scalar_value(scalar_value)
{}
UDQASTNode::UDQASTNode(UDQTokenType type_arg,

View File

@@ -36,6 +36,7 @@ public:
UDQASTNode();
UDQASTNode(UDQTokenType type_arg);
UDQASTNode(double scalar_value);
UDQASTNode(UDQTokenType type_arg, const std::string& string_value, const std::vector<std::string>& selector);
UDQASTNode(UDQTokenType type_arg, const std::string& func_name, const UDQASTNode& arg);
UDQASTNode(UDQTokenType type_arg, const std::string& func_name, const UDQASTNode& left, const UDQASTNode& right);

View File

@@ -62,30 +62,30 @@ std::vector<std::string> quote_split(const std::string& item) {
}
template <typename T>
UDQDefine::UDQDefine(const UDQFunctionTable& udqft,
UDQDefine::UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
const std::vector<std::string>& deck_data,
const ParseContext& parseContext,
T&& errors) :
UDQDefine(udqft, keyword, deck_data, parseContext, errors)
UDQDefine(udq_params, keyword, deck_data, parseContext, errors)
{}
UDQDefine::UDQDefine(const UDQFunctionTable& udqft,
UDQDefine::UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
const std::vector<std::string>& deck_data) :
UDQDefine(udqft, keyword, deck_data, ParseContext(), ErrorGuard())
UDQDefine(udq_params, keyword, deck_data, ParseContext(), ErrorGuard())
{}
UDQDefine::UDQDefine(const UDQFunctionTable& udqft,
UDQDefine::UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
const std::vector<std::string>& deck_data,
const ParseContext& parseContext,
ErrorGuard& errors) :
udq_params(udq_params),
m_keyword(keyword),
m_var_type(UDQ::varType(keyword)),
udqft(udqft)
m_var_type(UDQ::varType(keyword))
{
std::vector<std::string> tokens;
for (const std::string& deck_item : deck_data) {
@@ -121,7 +121,7 @@ UDQDefine::UDQDefine(const UDQFunctionTable& udqft,
}
}
this->ast = std::make_shared<UDQASTNode>( UDQParser::parse(udqft, tokens) );
this->ast = std::make_shared<UDQASTNode>( UDQParser::parse(this->udq_params, tokens, parseContext, errors) );
this->tokens = tokens;
}

View File

@@ -55,8 +55,7 @@ namespace Opm {
double value = std::stod(data.back());
this->m_assignments.emplace_back( quantity, selector, value );
} else
this->m_expressions.emplace_back(this->udqft, quantity, data);
this->m_definitions.emplace_back(this->udq_params, quantity, data);
this->keywords.insert(quantity);
}

View File

@@ -20,6 +20,7 @@
#include <iostream>
#include <cstring>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include "UDQParser.hpp"
namespace Opm {
@@ -145,6 +146,8 @@ UDQASTNode UDQParser::parse_pow() {
auto func_node = current;
this->next();
auto right = this->parse_mul();
if (right.type == UDQTokenType::end)
return UDQASTNode(UDQTokenType::error);
return UDQASTNode(current.type, current.value, left, right);
}
@@ -164,6 +167,8 @@ UDQASTNode UDQParser::parse_mul() {
auto func_node = current;
this->next();
auto right = this->parse_mul();
if (right.type == UDQTokenType::end)
return UDQASTNode(UDQTokenType::error);
return UDQASTNode(current.type, current.value, left, right);
}
@@ -180,8 +185,10 @@ UDQASTNode UDQParser::parse_add() {
if (current.type == UDQTokenType::binary_op_add || current.type == UDQTokenType::binary_op_sub) {
auto func_node = current;
this->next();
auto next = this->next();
auto right = this->parse_add();
if (right.type == UDQTokenType::end)
return UDQASTNode(UDQTokenType::error);
return UDQASTNode(current.type, current.value, left, right);
}
@@ -195,10 +202,11 @@ UDQASTNode UDQParser::parse_add() {
auto cmp = a + b < c;
The sum (a+b) is evaluated and then compared with c, that is the the order of
The sum (a+b) is evaluated and then compared with c, that is the order of
presedence implemented here. But reading the eclipse UDQ manual one can get
the imporession that the relation operators should bind "very strong", i.e.
that (b < c) should be evaluated first, and then the result added to a.
that (b < c) should be evaluated first, and then the result of the comparison
added to a.
*/
UDQASTNode UDQParser::parse_cmp() {
@@ -211,6 +219,8 @@ UDQASTNode UDQParser::parse_cmp() {
auto func_node = current;
this->next();
auto right = this->parse_cmp();
if (right.type == UDQTokenType::end)
return UDQASTNode(UDQTokenType::error);
return UDQASTNode(current.type, current.value, left, right);
}
@@ -222,23 +232,29 @@ UDQASTNode UDQParser::parse_cmp() {
UDQASTNode UDQParser::parse(const UDQFunctionTable& udqft, const std::vector<std::string>& tokens)
UDQASTNode UDQParser::parse(const UDQParams& udq_params, const std::vector<std::string>& tokens, const ParseContext& parseContext, ErrorGuard& errors)
{
UDQParser parser(udqft, tokens);
UDQParser parser(udq_params, tokens);
parser.next();
auto tree = parser.parse_cmp();
auto current = parser.current();
if (current.type != UDQTokenType::end) {
size_t index = parser.current_pos;
throw std::invalid_argument("Extra unhandled data starting with token[" + std::to_string(index) + "] = " + current.value);
}
if (tree.type == UDQTokenType::error)
throw std::invalid_argument("Failed to parse UDQ DEFINE tokens");
if (current.type != UDQTokenType::end || tree.type == UDQTokenType::error) {
if (current.type != UDQTokenType::end) {
size_t index = parser.current_pos;
std::string msg = "Extra unhandled data starting with token[" + std::to_string(index) + "] = " + current.value;
parseContext.handleError(ParseContext::UDQ_PARSE_ERROR, msg, errors);
}
if (tree.type == UDQTokenType::error) {
std::string msg = "Failed to parse UDQ expression";
parseContext.handleError(ParseContext::UDQ_PARSE_ERROR, msg, errors);
}
return UDQASTNode( udq_params.undefinedValue() );
}
return tree;
}
}

View File

@@ -24,12 +24,16 @@
#include <vector>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunctionTable.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include "UDQASTNode.hpp"
namespace Opm {
class ParseContext;
class ErrorGuard;
struct UDQParseNode {
UDQParseNode(UDQTokenType type_arg, const std::string& value_arg, const std::vector<std::string>& selector) :
type(type_arg),
@@ -54,11 +58,12 @@ struct UDQParseNode {
class UDQParser {
public:
static UDQASTNode parse(const UDQFunctionTable& udqft, const std::vector<std::string>& tokens);
static UDQASTNode parse(const UDQParams& udq_params, const std::vector<std::string>& tokens, const ParseContext& parseContext, ErrorGuard& errors);
private:
UDQParser(const UDQFunctionTable& udqft, const std::vector<std::string>& tokens) :
udqft(udqft),
UDQParser(const UDQParams& udq_params, const std::vector<std::string>& tokens) :
udq_params(udq_params),
udqft(UDQFunctionTable(udq_params)),
tokens(tokens)
{}
@@ -73,7 +78,8 @@ private:
UDQTokenType get_type(const std::string& arg) const;
std::size_t current_size() const;
const UDQFunctionTable& udqft;
const UDQParams& udq_params;
UDQFunctionTable udqft;
std::vector<std::string> tokens;
ssize_t current_pos = -1;
};

View File

@@ -105,6 +105,8 @@ namespace Opm {
addKey(SIMULATOR_KEYWORD_NOT_SUPPORTED, InputError::WARN);
addKey(SIMULATOR_KEYWORD_ITEM_NOT_SUPPORTED, InputError::WARN);
addKey(UDQ_PARSE_ERROR, InputError::THROW_EXCEPTION);
}
void ParseContext::initEnv() {
@@ -334,4 +336,6 @@ namespace Opm {
const std::string ParseContext::SIMULATOR_KEYWORD_NOT_SUPPORTED = "SIMULATOR_KEYWORD_NOT_SUPPORTED";
const std::string ParseContext::SIMULATOR_KEYWORD_ITEM_NOT_SUPPORTED = "SIMULATOR_KEYWORD_ITEM_NOT_SUPPORTED";
const std::string ParseContext::UDQ_PARSE_ERROR = "UDQ_PARSE_ERROR";
}

View File

@@ -50,7 +50,8 @@ Schedule make_schedule(const std::string& input) {
BOOST_AUTO_TEST_CASE(MIX_SCALAR) {
UDQFunctionTable udqft;
UDQDefine def_add(udqft, "WU", {"WOPR", "+", "1"});
UDQParams udqp;
UDQDefine def_add(udqp, "WU", {"WOPR", "+", "1"});
SummaryState st;
UDQContext context(udqft, st);
@@ -62,8 +63,8 @@ BOOST_AUTO_TEST_CASE(MIX_SCALAR) {
BOOST_AUTO_TEST_CASE(UDQ_TABLE_EXCEPTION) {
UDQFunctionTable udqft;
BOOST_CHECK_THROW(UDQDefine(udqft, "WU", {"TUPRICE[WOPR]"}), std::invalid_argument);
UDQParams udqp;
BOOST_CHECK_THROW(UDQDefine(udqp, "WU", {"TUPRICE[WOPR]"}), std::invalid_argument);
}
@@ -113,9 +114,10 @@ BOOST_AUTO_TEST_CASE(UDQWellSetTest) {
BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
UDQFunctionTable udqft;
UDQParams udqp;
UDQFunctionTable udqft(udqp);
{
UDQDefine def(udqft, "WUBHP", {"WBHP"});
UDQDefine def(udqp, "WUBHP", {"WBHP"});
SummaryState st;
UDQContext context(udqft, st);
@@ -129,7 +131,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
BOOST_CHECK_EQUAL( res["W3"].value(), 3 );
}
{
UDQDefine def(udqft, "WUBHP", {"WBHP" , "'P*'"});
UDQDefine def(udqp, "WUBHP", {"WBHP" , "'P*'"});
SummaryState st;
UDQContext context(udqft, st);
@@ -146,7 +148,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
BOOST_CHECK_EQUAL( res["I1"].defined(), false);
}
{
UDQDefine def(udqft, "WUBHP", {"WBHP" , "'P1'"});
UDQDefine def(udqp, "WUBHP", {"WBHP" , "'P1'"});
SummaryState st;
UDQContext context(udqft, st);
@@ -156,7 +158,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
}
{
UDQDefine def(udqft, "WUBHP", {"NINT" , "(", "WBHP", ")"});
UDQDefine def(udqp, "WUBHP", {"NINT" , "(", "WBHP", ")"});
SummaryState st;
UDQContext context(udqft, st);
st.add_well_var("P1", "WBHP", 4);
@@ -175,7 +177,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
// scalar context and that is not appropriate for the WUBHP variable which
// should evaluate to a full well set.
{
UDQDefine def(udqft, "WUBHP", {"SUM" , "(", "WBHP", ")"});
UDQDefine def(udqp, "WUBHP", {"SUM" , "(", "WBHP", ")"});
SummaryState st;
UDQContext context(udqft, st);
@@ -804,8 +806,9 @@ BOOST_AUTO_TEST_CASE(UDQASSIGN_TEST) {
BOOST_AUTO_TEST_CASE(UDQ_POW_TEST) {
UDQFunctionTable udqft;
UDQDefine def_pow1(udqft, "WU", {"WOPR", "+", "WWPR", "*", "WGOR", "^", "WWIR"});
UDQDefine def_pow2(udqft, "WU", {"(", "WOPR", "+", "WWPR", ")", "^", "(", "WOPR", "+" , "WGOR", "*", "WWIR", "-", "WOPT", ")"});
UDQParams udqp;
UDQDefine def_pow1(udqp, "WU", {"WOPR", "+", "WWPR", "*", "WGOR", "^", "WWIR"});
UDQDefine def_pow2(udqp, "WU", {"(", "WOPR", "+", "WWPR", ")", "^", "(", "WOPR", "+" , "WGOR", "*", "WWIR", "-", "WOPT", ")"});
SummaryState st;
UDQContext context(udqft, st);
@@ -823,7 +826,8 @@ BOOST_AUTO_TEST_CASE(UDQ_POW_TEST) {
BOOST_AUTO_TEST_CASE(UDQ_CMP_TEST) {
UDQFunctionTable udqft;
UDQDefine def_cmp(udqft, "WU", {"WOPR", ">", "WWPR", "+", "WGOR", "*", "WWIR"});
UDQParams udqp;
UDQDefine def_cmp(udqp, "WU", {"WOPR", ">", "WWPR", "+", "WGOR", "*", "WWIR"});
SummaryState st;
UDQContext context(udqft, st);
@@ -842,15 +846,22 @@ BOOST_AUTO_TEST_CASE(UDQ_CMP_TEST) {
BOOST_CHECK_EQUAL( res_cmp["P2"].value() , 0.0);
}
/*BOOST_AUTO_TEST_CASE(UDQPARSE_ERROR) {
setUDQFunctionTable udqft;
UDQDefine def1(udqft, "WUBHP", {"WWCT", "+"});
}
*/
BOOST_AUTO_TEST_CASE(UDQ_BASIC_MATH_TEST) {
UDQParams udqp;
UDQFunctionTable udqft;
UDQDefine def_add(udqft, "WU2OPR", {"WOPR", "+", "WOPR"});
UDQDefine def_sub(udqft, "WU2OPR", {"WOPR", "-", "WOPR"});
UDQDefine def_mul(udqft, "WU2OPR", {"WOPR", "*", "WOPR"});
UDQDefine def_div(udqft, "WU2OPR", {"WOPR", "/", "WOPR"});
UDQDefine def_muladd(udqft , "WUX", {"WOPR", "+", "WOPR", "*", "WOPR"});
UDQDefine def_wuwct(udqft , "WUWCT", {"WWPR", "/", "(", "WOPR", "+", "WWPR", ")"});
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", ")"});
SummaryState st;
UDQContext context(udqft, st);
@@ -909,16 +920,37 @@ BOOST_AUTO_TEST_CASE(UDQ_BASIC_MATH_TEST) {
BOOST_AUTO_TEST_CASE(UDQPARSE_TEST1) {
UDQFunctionTable udqft;
UDQDefine def1(udqft, "WUBHP", {"1/(WWCT", "'W1*')"});
UDQParams udqp;
UDQDefine def1(udqp, "WUBHP", {"1/(WWCT", "'W1*')"});
std::vector<std::string> tokens1 = {"1", "/", "(", "WWCT", "W1*", ")"};
BOOST_CHECK_EQUAL_COLLECTIONS(tokens1.begin(), tokens1.end(),
def1.tokens.begin(), def1.tokens.end());
UDQDefine def2(udqft, "WUBHP", {"2*(1", "+" , "WBHP)"});
UDQDefine def2(udqp, "WUBHP", {"2*(1", "+" , "WBHP)"});
std::vector<std::string> tokens2 = {"2", "*", "(", "1", "+", "WBHP", ")"};
BOOST_CHECK_EQUAL_COLLECTIONS(tokens2.begin(), tokens2.end(),
def2.tokens.begin(), def2.tokens.end());
}
BOOST_AUTO_TEST_CASE(UDQPARSE_PARSECONTEXT) {
UDQParams udqp;
ParseContext parseContext;
ErrorGuard errors;
std::vector<std::string> tokens = {"WBHP", "+"};
parseContext.update(ParseContext::UDQ_PARSE_ERROR, InputError::IGNORE);
{
UDQDefine def1(udqp, "WUBHP", tokens, parseContext, errors);
SummaryState st;
UDQContext context(UDQFunctionTable(udqp), st);
st.add_well_var("P1", "WOPR", 1);
printf("Have returned with def1 \n");
auto res = def1.eval_wells(context);
BOOST_CHECK_EQUAL(res["P1"].value(), udqp.undefinedValue());
}
parseContext.update(ParseContext::UDQ_PARSE_ERROR, InputError::THROW_EXCEPTION);
BOOST_CHECK_THROW( UDQDefine(udqp, "WUBHP", tokens, parseContext, errors), std::invalid_argument);
}