UDQ Cast can cast to both lhs type and rhs type

This commit is contained in:
Joakim Hove 2020-11-21 13:36:56 +01:00
parent 74cedd95e2
commit fa3b740d1d
2 changed files with 94 additions and 27 deletions

View File

@ -478,37 +478,59 @@ UDQScalar operator/(double lhs, const UDQScalar& rhs) {
namespace {
bool is_scalar(const UDQSet& udq_set) {
if (udq_set.var_type() == UDQVarType::SCALAR)
return true;
if (udq_set.var_type() == UDQVarType::FIELD_VAR)
return true;
return false;
}
/*
If one result set is scalar and the other represents a set of wells/groups,
the scalar result is promoted to a set of the right type.
*/
UDQSet udq_cast(const UDQSet& lhs, const UDQSet& rhs)
{
if (lhs.size() != rhs.size()) {
if (lhs.var_type() != UDQVarType::SCALAR) {
auto msg = fmt::format("Type/size mismatch when combining UDQs {}(size={}, type={}) and {}(size={}, type={})",
lhs.name(), lhs.size(), lhs.var_type(),
rhs.name(), rhs.size(), rhs.var_type());
throw std::logic_error(msg);
}
This function is quite subconcious about FIELD / SCALAR.
*/
std::pair<UDQSet, UDQSet> udq_cast(const UDQSet& lhs, const UDQSet& rhs)
{
if (lhs.var_type() == rhs.var_type())
return std::make_pair(lhs,rhs);
if (lhs.size() == rhs.size())
return std::make_pair(lhs,rhs);
if (is_scalar(lhs)) {
if (rhs.var_type() == UDQVarType::WELL_VAR)
return UDQSet::wells(lhs.name(), rhs.wgnames(), lhs[0].get());
return std::make_pair(UDQSet::wells(lhs.name(), rhs.wgnames(), lhs[0].get()), rhs);
if (rhs.var_type() == UDQVarType::GROUP_VAR)
return UDQSet::groups(lhs.name(), rhs.wgnames(), lhs[0].get());
return std::make_pair(UDQSet::groups(lhs.name(), rhs.wgnames(), lhs[0].get()), rhs);
}
throw std::logic_error("Don't have a clue");
} else
return lhs;
if (is_scalar(rhs)) {
if (lhs.var_type() == UDQVarType::WELL_VAR)
return std::make_pair(lhs, UDQSet::wells(rhs.name(), lhs.wgnames(), rhs[0].get()));
if (lhs.var_type() == UDQVarType::GROUP_VAR)
return std::make_pair(lhs, UDQSet::groups(rhs.name(), lhs.wgnames(), rhs[0].get()));
}
auto msg = fmt::format("Type/size mismatch when combining UDQs {}(size={}, type={}) and {}(size={}, type={})",
lhs.name(), lhs.size(), lhs.var_type(),
rhs.name(), rhs.size(), rhs.var_type());
throw std::logic_error(msg);
}
}
UDQSet operator+(const UDQSet&lhs, const UDQSet& rhs) {
UDQSet sum = udq_cast(lhs, rhs);
sum += rhs;
return sum;
auto [left,right] = udq_cast(lhs, rhs);
left += right;
return left;
}
UDQSet operator+(const UDQSet&lhs, double rhs) {
@ -524,9 +546,9 @@ UDQSet operator+(double lhs, const UDQSet& rhs) {
}
UDQSet operator-(const UDQSet&lhs, const UDQSet& rhs) {
UDQSet diff = udq_cast(lhs, rhs);
diff -= rhs;
return diff;
auto [left,right] = udq_cast(lhs, rhs);
left -= right;
return left;
}
UDQSet operator-(const UDQSet&lhs, double rhs) {
@ -542,9 +564,9 @@ UDQSet operator-(double lhs, const UDQSet& rhs) {
}
UDQSet operator*(const UDQSet&lhs, const UDQSet& rhs) {
UDQSet prod = udq_cast(lhs, rhs);
prod *= rhs;
return prod;
auto [left,right] = udq_cast(lhs, rhs);
left *= right;
return left;
}
UDQSet operator*(const UDQSet&lhs, double rhs) {
@ -560,9 +582,9 @@ UDQSet operator*(double lhs, const UDQSet& rhs) {
}
UDQSet operator/(const UDQSet&lhs, const UDQSet& rhs) {
UDQSet frac = udq_cast(lhs, rhs);
frac /= rhs;
return frac;
auto [left,right] = udq_cast(lhs, rhs);
left /= right;
return left;
}
UDQSet operator/(const UDQSet&lhs, double rhs) {

View File

@ -2484,3 +2484,48 @@ TSTEP
BOOST_CHECK( !udq_state.define(def.keyword(), def.status()));
}
}
BOOST_AUTO_TEST_CASE(UDQ_TYPE_CAST) {
std::string valid = R"(
SCHEDULE
UDQ
ASSIGN FUBHPP1 100 /
/
TSTEP
10 /
UDQ
DEFINE FU_TIME TIME /
DEFINE WUDELTA WBHP '*' - FUBHPP1 /
DEFINE WU_TEST WUBHPINI '*' - (WGPR '*')/2000.0 /
/
)";
auto schedule = make_schedule(valid);
UDQState udq_state(0);
SummaryState st(std::chrono::system_clock::now());
UDQFunctionTable udqft;
UDQContext context(udqft, WellMatcher({"W1", "W2", "W3"}), st, udq_state);
st.update_well_var("W1", "WBHP", 400);
st.update_well_var("W2", "WBHP", 300);
st.update_well_var("W3", "WBHP", 200);
const auto& udq = schedule.getUDQConfig(1);
{
const auto& ass = udq.assign("FUBHPP1");
context.update_assign(1, "FUBHPP1", ass.eval());
}
const auto& def = udq.define("WUDELTA");
auto res = def.eval(context);
BOOST_CHECK_EQUAL(res["W1"].get(), 300);
BOOST_CHECK_EQUAL(res["W2"].get(), 200);
BOOST_CHECK_EQUAL(res["W3"].get(), 100);
}