UDQ: Ensure that scalar right hand side is accepted into sets
This commit is contained in:
parent
83cb209ad8
commit
772bd3cee5
@ -103,48 +103,61 @@ UDQSet UDQASTNode::eval(UDQVarType target_type, const UDQContext& context) const
|
||||
if (this->type == UDQTokenType::ecl_expr) {
|
||||
if (this->var_type == UDQVarType::WELL_VAR) {
|
||||
const auto& wells = context.wells();
|
||||
auto res = UDQSet::wells(this->string_value, wells);
|
||||
|
||||
if (this->selector.size() > 0) {
|
||||
int fnmatch_flags = 0;
|
||||
const std::string& well_pattern = this->selector[0];
|
||||
if (well_pattern.find("*") == std::string::npos)
|
||||
throw std::invalid_argument("When evaluating a well UDQ you can not use fully qualified well variables");
|
||||
|
||||
for (const auto& well : wells) {
|
||||
if (fnmatch(well_pattern.c_str(), well.c_str(), fnmatch_flags) == 0)
|
||||
res.assign(well, context.get_well_var(well, this->string_value));
|
||||
/*
|
||||
The well name has been fully qualified - i.e. this
|
||||
evaulates to a scalar, which will then subsequently be
|
||||
scattered to all wells.
|
||||
*/
|
||||
return UDQSet::scalar(this->string_value, context.get_well_var(well_pattern, this->string_value));
|
||||
else {
|
||||
auto res = UDQSet::wells(this->string_value, wells);
|
||||
for (const auto& well : wells) {
|
||||
if (fnmatch(well_pattern.c_str(), well.c_str(), fnmatch_flags) == 0)
|
||||
res.assign(well, context.get_well_var(well, this->string_value));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
auto res = UDQSet::wells(this->string_value, wells);
|
||||
for (const auto& well : wells)
|
||||
res.assign(well, context.get_well_var(well, this->string_value));
|
||||
return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
if (this->var_type == UDQVarType::GROUP_VAR) {
|
||||
const auto& groups = context.groups();
|
||||
auto res = UDQSet::groups(this->string_value, groups);
|
||||
|
||||
if (this->selector.size() > 0) {
|
||||
int fnmatch_flags = 0;
|
||||
const std::string& group_pattern = this->selector[0];
|
||||
if (group_pattern.find("*") == std::string::npos)
|
||||
throw std::invalid_argument("When evaluating a group UDQ you can not use fully qualified group variables");
|
||||
|
||||
for (const auto& group : groups) {
|
||||
if (fnmatch(group_pattern.c_str(), group.c_str(), fnmatch_flags) == 0)
|
||||
res.assign(group, context.get_group_var(group, this->string_value));
|
||||
/*
|
||||
The group name has been fully qualified - i.e. this
|
||||
evaulates to a scalar, which will then subsequently be
|
||||
scattered to all groups.
|
||||
*/
|
||||
return UDQSet::scalar(this->string_value, context.get_group_var(group_pattern, this->string_value));
|
||||
else {
|
||||
auto res = UDQSet::groups(this->string_value, groups);
|
||||
for (const auto& group : groups) {
|
||||
if (fnmatch(group_pattern.c_str(), group.c_str(), fnmatch_flags) == 0)
|
||||
res.assign(group, context.get_group_var(group, this->string_value));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
auto res = UDQSet::groups(this->string_value, groups);
|
||||
for (const auto& group : groups)
|
||||
res.assign(group, context.get_group_var(group, this->string_value));
|
||||
return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
throw std::invalid_argument("When evaluating general inner kernel only Wxxx end Gxxx xpressions are allowed - for now.");
|
||||
}
|
||||
|
||||
|
||||
|
@ -133,6 +133,45 @@ UDQSet UDQDefine::eval(const UDQContext& context) const {
|
||||
std::string msg = "Invalid runtime type conversion detected when evaluating UDQ";
|
||||
throw std::invalid_argument(msg);
|
||||
}
|
||||
|
||||
if (res.var_type() == UDQVarType::SCALAR) {
|
||||
/*
|
||||
If the right hand side evaluates to a scalar that scalar value should
|
||||
be set for all wells in the wellset:
|
||||
|
||||
UDQ
|
||||
DEFINE WUINJ1 SUM(WOPR) * 1.25 /
|
||||
DEFINE WUINJ2 WOPR OP1 * 5.0 /
|
||||
/
|
||||
|
||||
Both the expressions "SUM(WOPR)" and "WOPR OP1" evaluate to a scalar,
|
||||
this should then be copied all wells, so that WUINJ1:$WELL should
|
||||
evaulate to the same numerical value for all wells; the same should
|
||||
also apply for group sets.
|
||||
*/
|
||||
|
||||
double scalar_value = res[0].value();
|
||||
if (this->var_type() == UDQVarType::WELL_VAR) {
|
||||
const std::vector<std::string> wells = context.wells();
|
||||
UDQSet well_res = UDQSet::wells(this->m_keyword, wells);
|
||||
|
||||
for (const auto& well : wells)
|
||||
well_res.assign(well, scalar_value);
|
||||
|
||||
return well_res;
|
||||
}
|
||||
|
||||
if (this->var_type() == UDQVarType::GROUP_VAR) {
|
||||
const std::vector<std::string> groups = context.groups();
|
||||
UDQSet group_res = UDQSet::groups(this->m_keyword, groups);
|
||||
|
||||
for (const auto& group : groups)
|
||||
group_res.assign(group, scalar_value);
|
||||
|
||||
return group_res;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ bool compatibleTypes(UDQVarType lhs, UDQVarType rhs) {
|
||||
if (lhs == rhs)
|
||||
return true;
|
||||
|
||||
if (lhs == UDQVarType::FIELD_VAR && rhs == UDQVarType::SCALAR)
|
||||
if (rhs == UDQVarType::SCALAR)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -197,16 +197,6 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
|
||||
BOOST_CHECK_EQUAL( res["I1"].defined(), false);
|
||||
BOOST_CHECK_EQUAL( res["I1"].defined(), false);
|
||||
}
|
||||
{
|
||||
UDQDefine def(udqp, "WUBHP", {"WBHP" , "'P1'"});
|
||||
SummaryState st;
|
||||
UDQContext context(udqft, st);
|
||||
|
||||
|
||||
st.update_well_var("P1", "WBHP", 1);
|
||||
BOOST_CHECK_THROW( def.eval( context ), std::invalid_argument);
|
||||
}
|
||||
|
||||
{
|
||||
UDQDefine def(udqp, "WUBHP", {"NINT" , "(", "WBHP", ")"});
|
||||
SummaryState st;
|
||||
@ -897,6 +887,70 @@ BOOST_AUTO_TEST_CASE(UDQ_CMP_TEST) {
|
||||
}
|
||||
*/
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
|
||||
UDQParams udqp;
|
||||
UDQFunctionTable udqft;
|
||||
SummaryState st;
|
||||
UDQContext context(udqft, st);
|
||||
|
||||
st.update_well_var("P1", "WOPR", 1);
|
||||
st.update_well_var("P2", "WOPR", 2);
|
||||
st.update_well_var("P3", "WOPR", 3);
|
||||
st.update_well_var("P4", "WOPR", 4);
|
||||
|
||||
st.update_well_var("P1", "WWPR", 1);
|
||||
st.update_well_var("P2", "WWPR", 2);
|
||||
st.update_well_var("P3", "WWPR", 3);
|
||||
st.update_well_var("P4", "WWPR", 4);
|
||||
|
||||
{
|
||||
UDQDefine def(udqp, "WUOPR", {"WOPR", "'*1'"});
|
||||
auto res = def.eval(context);
|
||||
BOOST_CHECK_EQUAL(4, res.size());
|
||||
auto well1 = res["P1"];
|
||||
BOOST_CHECK( well1.defined() );
|
||||
BOOST_CHECK_EQUAL(well1.value() , 1);
|
||||
|
||||
auto well2 = res["P2"];
|
||||
BOOST_CHECK( !well2.defined() );
|
||||
|
||||
auto well4 = res["P4"];
|
||||
BOOST_CHECK( !well4.defined() );
|
||||
}
|
||||
{
|
||||
UDQDefine def(udqp, "WUOPR", {"1"});
|
||||
auto res = def.eval(context);
|
||||
BOOST_CHECK_EQUAL(4, res.size());
|
||||
auto well1 = res["P1"];
|
||||
BOOST_CHECK( well1.defined() );
|
||||
BOOST_CHECK_EQUAL(well1.value() , 1);
|
||||
|
||||
auto well2 = res["P2"];
|
||||
BOOST_CHECK( well2.defined() );
|
||||
BOOST_CHECK_EQUAL(well2.value() , 1);
|
||||
|
||||
auto well4 = res["P4"];
|
||||
BOOST_CHECK( well4.defined() );
|
||||
BOOST_CHECK_EQUAL(well4.value() , 1);
|
||||
}
|
||||
{
|
||||
UDQDefine def(udqp, "WUOPR", {"WOPR", "'P1'"});
|
||||
auto res = def.eval(context);
|
||||
BOOST_CHECK_EQUAL(4, res.size());
|
||||
auto well1 = res["P1"];
|
||||
BOOST_CHECK( well1.defined() );
|
||||
BOOST_CHECK_EQUAL(well1.value() , 1);
|
||||
|
||||
auto well2 = res["P2"];
|
||||
BOOST_CHECK( well2.defined() );
|
||||
BOOST_CHECK_EQUAL(well2.value() , 1);
|
||||
|
||||
auto well4 = res["P4"];
|
||||
BOOST_CHECK( well4.defined() );
|
||||
BOOST_CHECK_EQUAL(well4.value() , 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UDQ_BASIC_MATH_TEST) {
|
||||
UDQParams udqp;
|
||||
@ -988,7 +1042,8 @@ BOOST_AUTO_TEST_CASE(UDQ_PARSE_ERROR) {
|
||||
{
|
||||
UDQDefine def1(udqp, "WUBHP", tokens, parseContext, errors);
|
||||
SummaryState st;
|
||||
UDQContext context(UDQFunctionTable(udqp), st);
|
||||
UDQFunctionTable udqft(udqp);
|
||||
UDQContext context(udqft, st);
|
||||
st.update_well_var("P1", "WBHP", 1);
|
||||
|
||||
auto res = def1.eval(context);
|
||||
@ -1011,8 +1066,10 @@ BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
|
||||
UDQDefine def2(udqp, "WUBHP", tokens2, parseContext, errors);
|
||||
|
||||
SummaryState st;
|
||||
UDQContext context(UDQFunctionTable(udqp), st);
|
||||
UDQFunctionTable udqft(udqp);
|
||||
UDQContext context(udqft, st);
|
||||
st.update_well_var("P1", "WBHP", 1);
|
||||
st.update_well_var("P2", "WBHP", 2);
|
||||
|
||||
auto res1 = def1.eval(context);
|
||||
BOOST_CHECK_EQUAL(res1[0].value(), udqp.undefinedValue());
|
||||
@ -1020,16 +1077,13 @@ BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
|
||||
auto res2 = def2.eval(context);
|
||||
BOOST_CHECK_EQUAL(res2.size(), st.num_wells());
|
||||
for (std::size_t index = 0; index < res2.size(); index++)
|
||||
BOOST_CHECK_EQUAL(res2[index].value(), udqp.undefinedValue());
|
||||
BOOST_CHECK_EQUAL(res2[index].value(), 3);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// This fails because the scalar expression SUM(WBHP) is assigned to the well variable WUBHP
|
||||
BOOST_CHECK_THROW( UDQDefine(udqp, "WUBHP", tokens2, parseContext, errors), std::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user