Differentiate better between UDQ ASSIGN and UDQ DEFINE

A quite typical situation is that a UDQ keyword is first initialized with UDQ
ASSIGN statement, and then subsequently a formula for updates every timestep is
entered with UDQ DEFINE:

  UDQ
     ASSIGN FU_VAR1 0 /
     DEFINE FU_VAR1 FU_VAR1 + 1 /
  /

Then the assign statement should be run once, and the define formula should be
evaluated for every subsequent timestep.
This commit is contained in:
Joakim Hove 2020-09-08 12:08:16 +02:00
parent 49460edf39
commit 5a060910a3
12 changed files with 215 additions and 78 deletions

View File

@ -42,10 +42,12 @@ public:
struct AssignRecord { struct AssignRecord {
std::vector<std::string> selector; std::vector<std::string> selector;
double value; double value;
std::size_t report_step;
bool operator==(const AssignRecord& data) const { bool operator==(const AssignRecord& data) const {
return selector == data.selector && return selector == data.selector &&
value == data.value; report_step == data.report_step &&
value == data.value;
} }
template<class Serializer> template<class Serializer>
@ -53,19 +55,21 @@ public:
{ {
serializer(selector); serializer(selector);
serializer(value); serializer(value);
serializer(report_step);
} }
}; };
UDQAssign(); UDQAssign();
UDQAssign(const std::string& keyword, const std::vector<std::string>& selector, double value); UDQAssign(const std::string& keyword, const std::vector<std::string>& selector, double value, std::size_t report_step);
static UDQAssign serializeObject(); static UDQAssign serializeObject();
const std::string& keyword() const; const std::string& keyword() const;
UDQVarType var_type() const; UDQVarType var_type() const;
void add_record(const std::vector<std::string>& selector, double value); void add_record(const std::vector<std::string>& selector, double value, std::size_t report_step);
UDQSet eval(const std::vector<std::string>& wells) const; UDQSet eval(const std::vector<std::string>& wells) const;
UDQSet eval() const; UDQSet eval() const;
std::size_t report_step() const;
bool operator==(const UDQAssign& data) const; bool operator==(const UDQAssign& data) const;

View File

@ -53,10 +53,10 @@ namespace Opm {
const std::string& unit(const std::string& key) const; const std::string& unit(const std::string& key) const;
bool has_unit(const std::string& keyword) const; bool has_unit(const std::string& keyword) const;
bool has_keyword(const std::string& keyword) const; bool has_keyword(const std::string& keyword) const;
void add_record(const DeckRecord& record); void add_record(const DeckRecord& record, std::size_t report_step);
void add_unit(const std::string& keyword, const std::string& unit); void add_unit(const std::string& keyword, const std::string& unit);
void add_assign(const std::string& quantity, const std::vector<std::string>& selector, double value); void add_assign(const std::string& quantity, const std::vector<std::string>& selector, double value, std::size_t report_step);
void add_define(const std::string& quantity, const std::vector<std::string>& expression); void add_define(const std::string& quantity, const std::vector<std::string>& expression);
void eval(std::size_t report_step, SummaryState& st, UDQState& udq_state) const; void eval(std::size_t report_step, SummaryState& st, UDQState& udq_state) const;
@ -96,6 +96,8 @@ namespace Opm {
private: private:
void add_node(const std::string& quantity, UDQAction action); void add_node(const std::string& quantity, UDQAction action);
UDQAction action_type(const std::string& udq_key) const;
UDQParams udq_params; UDQParams udq_params;
UDQFunctionTable udqft; UDQFunctionTable udqft;

View File

@ -42,7 +42,8 @@ namespace Opm {
std::optional<double> get_well_var(const std::string& well, const std::string& var) const; std::optional<double> get_well_var(const std::string& well, const std::string& var) const;
std::optional<double> get_group_var(const std::string& group, const std::string& var) const; std::optional<double> get_group_var(const std::string& group, const std::string& var) const;
void add(const std::string& key, double value); void add(const std::string& key, double value);
void update(const std::string& keyword, const UDQSet& udq_result); void update_assign(std::size_t report_step, const std::string& keyword, const UDQSet& udq_result);
void update_define(const std::string& keyword, const UDQSet& udq_result);
const UDQFunctionTable& function_table() const; const UDQFunctionTable& function_table() const;
std::vector<std::string> wells() const; std::vector<std::string> wells() const;
std::vector<std::string> groups() const; std::vector<std::string> groups() const;

View File

@ -39,15 +39,19 @@ public:
double get(const std::string& key) const; double get(const std::string& key) const;
double get_group_var(const std::string& well, const std::string& var) const; double get_group_var(const std::string& well, const std::string& var) const;
double get_well_var(const std::string& well, const std::string& var) const; double get_well_var(const std::string& well, const std::string& var) const;
void add(const std::string& udq_key, const UDQSet& result); void add_define(const std::string& udq_key, const UDQSet& result);
void add_assign(std::size_t report_step, const std::string& udq_key, const UDQSet& result);
bool assign(std::size_t report_step, const std::string& udq_key) const;
std::vector<char> serialize() const; std::vector<char> serialize() const;
void deserialize(const std::vector<char>& buffer); void deserialize(const std::vector<char>& buffer);
bool operator==(const UDQState& other) const; bool operator==(const UDQState& other) const;
private: private:
void add(const std::string& udq_key, const UDQSet& result);
double get_wg_var(const std::string& well, const std::string& key, UDQVarType var_type) const; double get_wg_var(const std::string& well, const std::string& key, UDQVarType var_type) const;
double undefined_value; double undefined_value;
std::unordered_map<std::string, UDQSet> values; std::unordered_map<std::string, UDQSet> values;
std::unordered_map<std::string, std::size_t> assignments;
}; };
} }

View File

@ -1389,7 +1389,7 @@ Schedule::Schedule(const Deck& deck, const EclipseState& es, const ParseContext&
const auto& current = *this->udq_config.get(currentStep); const auto& current = *this->udq_config.get(currentStep);
std::shared_ptr<UDQConfig> new_udq = std::make_shared<UDQConfig>(current); std::shared_ptr<UDQConfig> new_udq = std::make_shared<UDQConfig>(current);
for (const auto& record : keyword) for (const auto& record : keyword)
new_udq->add_record(record); new_udq->add_record(record, currentStep);
this->udq_config.update(currentStep, new_udq); this->udq_config.update(currentStep, new_udq);
} }

View File

@ -27,11 +27,11 @@ UDQAssign::UDQAssign() :
{ {
} }
UDQAssign::UDQAssign(const std::string& keyword, const std::vector<std::string>& selector, double value) : UDQAssign::UDQAssign(const std::string& keyword, const std::vector<std::string>& selector, double value, std::size_t report_step) :
m_keyword(keyword), m_keyword(keyword),
m_var_type(UDQ::varType(keyword)) m_var_type(UDQ::varType(keyword))
{ {
this->add_record(selector, value); this->add_record(selector, value, report_step);
} }
UDQAssign UDQAssign::serializeObject() UDQAssign UDQAssign::serializeObject()
@ -39,13 +39,13 @@ UDQAssign UDQAssign::serializeObject()
UDQAssign result; UDQAssign result;
result.m_keyword = "test"; result.m_keyword = "test";
result.m_var_type = UDQVarType::CONNECTION_VAR; result.m_var_type = UDQVarType::CONNECTION_VAR;
result.records = {{{"test1"}, 1.0}}; result.records = {{{"test1"}, 1.0, 0}};
return result; return result;
} }
void UDQAssign::add_record(const std::vector<std::string>& selector, double value) { void UDQAssign::add_record(const std::vector<std::string>& selector, double value, std::size_t report_step) {
this->records.push_back({selector, value}); this->records.push_back({selector, value, report_step});
} }
const std::string& UDQAssign::keyword() const { const std::string& UDQAssign::keyword() const {
@ -56,6 +56,12 @@ UDQVarType UDQAssign::var_type() const {
return this->m_var_type; return this->m_var_type;
} }
std::size_t UDQAssign::report_step() const {
return this->records.back().report_step;
}
UDQSet UDQAssign::eval(const std::vector<std::string>& wells) const { UDQSet UDQAssign::eval(const std::vector<std::string>& wells) const {
if (this->m_var_type == UDQVarType::WELL_VAR) { if (this->m_var_type == UDQVarType::WELL_VAR) {
UDQSet ws = UDQSet::wells(this->m_keyword, wells); UDQSet ws = UDQSet::wells(this->m_keyword, wells);

View File

@ -22,6 +22,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.hpp>
namespace Opm { namespace Opm {
@ -75,13 +76,13 @@ namespace Opm {
index_iter->second.action = action; index_iter->second.action = action;
} }
void UDQConfig::add_assign(const std::string& quantity, const std::vector<std::string>& selector, double value) { void UDQConfig::add_assign(const std::string& quantity, const std::vector<std::string>& selector, double value, std::size_t report_step) {
this->add_node(quantity, UDQAction::ASSIGN); this->add_node(quantity, UDQAction::ASSIGN);
auto assignment = this->m_assignments.find(quantity); auto assignment = this->m_assignments.find(quantity);
if (assignment == this->m_assignments.end()) if (assignment == this->m_assignments.end())
this->m_assignments.insert( std::make_pair(quantity, UDQAssign(quantity, selector, value ))); this->m_assignments.insert( std::make_pair(quantity, UDQAssign(quantity, selector, value, report_step )));
else else
assignment->second.add_record(selector, value); assignment->second.add_record(selector, value, report_step);
} }
@ -113,12 +114,12 @@ namespace Opm {
keyword. keyword.
*/ */
if (!this->has_keyword(keyword)) if (!this->has_keyword(keyword))
this->add_assign(keyword, {}, 0); this->add_assign(keyword, {}, 0, 0);
this->units[keyword] = unit; this->units[keyword] = unit;
} }
void UDQConfig::add_record(const DeckRecord& record) { void UDQConfig::add_record(const DeckRecord& record, std::size_t report_step) {
auto action = UDQ::actionType(record.getItem("ACTION").get<RawString>(0)); auto action = UDQ::actionType(record.getItem("ACTION").get<RawString>(0));
const auto& quantity = record.getItem("QUANTITY").get<std::string>(0); const auto& quantity = record.getItem("QUANTITY").get<std::string>(0);
const auto& data = RawString::strings( record.getItem("DATA").getData<RawString>() ); const auto& data = RawString::strings( record.getItem("DATA").getData<RawString>() );
@ -132,7 +133,7 @@ namespace Opm {
if (action == UDQAction::ASSIGN) { if (action == UDQAction::ASSIGN) {
std::vector<std::string> selector(data.begin(), data.end() - 1); std::vector<std::string> selector(data.begin(), data.end() - 1);
double value = std::stod(data.back()); double value = std::stod(data.back());
this->add_assign(quantity, selector, value); this->add_assign(quantity, selector, value, report_step);
} else if (action == UDQAction::DEFINE) } else if (action == UDQAction::DEFINE)
this->add_define(quantity, data); this->add_define(quantity, data);
else else
@ -144,13 +145,18 @@ namespace Opm {
return this->m_definitions.at(key); return this->m_definitions.at(key);
} }
UDQAction UDQConfig::action_type(const std::string& udq_key) const {
auto action_iter = this->input_index.find(udq_key);
return action_iter->second.action;
}
std::vector<UDQDefine> UDQConfig::definitions() const { std::vector<UDQDefine> UDQConfig::definitions() const {
std::vector<UDQDefine> ret; std::vector<UDQDefine> ret;
for (const auto& key : this->define_order) for (const auto& key : this->define_order) {
ret.push_back(this->m_definitions.at(key)); if (this->action_type(key) == UDQAction::DEFINE)
ret.push_back(this->m_definitions.at(key));
}
return ret; return ret;
} }
@ -159,7 +165,7 @@ namespace Opm {
std::vector<UDQDefine> filtered_defines; std::vector<UDQDefine> filtered_defines;
for (const auto& key : this->define_order) { for (const auto& key : this->define_order) {
const auto& udq_define = this->m_definitions.at(key); const auto& udq_define = this->m_definitions.at(key);
if (udq_define.var_type() == var_type) if (udq_define.var_type() == var_type && this->action_type(key) == UDQAction::DEFINE)
filtered_defines.push_back(udq_define); filtered_defines.push_back(udq_define);
} }
return filtered_defines; return filtered_defines;
@ -210,16 +216,16 @@ namespace Opm {
std::vector<UDQAssign> UDQConfig::assignments(UDQVarType var_type) const { std::vector<UDQAssign> UDQConfig::assignments(UDQVarType var_type) const {
std::vector<UDQAssign> filtered_defines; std::vector<UDQAssign> filtered_assigns;
for (const auto& index_pair : this->input_index) { for (const auto& index_pair : this->input_index) {
if (index_pair.second.action == UDQAction::ASSIGN) { const std::string& key = index_pair.first;
const std::string& key = index_pair.first; const auto& assign_iter = this->m_assignments.find(key);
const auto& udq_define = this->m_assignments.at(key); if (assign_iter != this->m_assignments.end()) {
if (udq_define.var_type() == var_type) if (assign_iter->second.var_type() == var_type)
filtered_defines.push_back(udq_define); filtered_assigns.push_back(assign_iter->second);
} }
} }
return filtered_defines; return filtered_assigns;
} }
@ -295,38 +301,44 @@ namespace Opm {
UDQContext context(func_table, st, udq_state); UDQContext context(func_table, st, udq_state);
for (const auto& assign : this->assignments(UDQVarType::WELL_VAR)) { for (const auto& assign : this->assignments(UDQVarType::WELL_VAR)) {
auto ws = assign.eval(st.wells()); if (udq_state.assign(report_step, assign.keyword())) {
context.update(assign.keyword(), ws); auto ws = assign.eval(st.wells());
st.update_udq(ws, undefined_value); context.update_assign(report_step, assign.keyword(), ws);
st.update_udq(ws, undefined_value);
}
} }
for (const auto& def : this->definitions(UDQVarType::WELL_VAR)) { for (const auto& def : this->definitions(UDQVarType::WELL_VAR)) {
auto ws = def.eval(context); auto ws = def.eval(context);
context.update(def.keyword(), ws); context.update_define(def.keyword(), ws);
st.update_udq(ws, undefined_value); st.update_udq(ws, undefined_value);
} }
for (const auto& assign : this->assignments(UDQVarType::GROUP_VAR)) { for (const auto& assign : this->assignments(UDQVarType::GROUP_VAR)) {
auto ws = assign.eval(st.groups()); if (udq_state.assign(report_step, assign.keyword())) {
context.update(assign.keyword(), ws); auto ws = assign.eval(st.groups());
st.update_udq(ws, undefined_value); context.update_assign(report_step, assign.keyword(), ws);
st.update_udq(ws, undefined_value);
}
} }
for (const auto& def : this->definitions(UDQVarType::GROUP_VAR)) { for (const auto& def : this->definitions(UDQVarType::GROUP_VAR)) {
auto ws = def.eval(context); auto ws = def.eval(context);
context.update(def.keyword(), ws); context.update_define(def.keyword(), ws);
st.update_udq(ws, undefined_value); st.update_udq(ws, undefined_value);
} }
for (const auto& assign : this->assignments(UDQVarType::FIELD_VAR)) { for (const auto& assign : this->assignments(UDQVarType::FIELD_VAR)) {
auto ws = assign.eval(); if (udq_state.assign(assign.report_step(), assign.keyword())) {
context.update(assign.keyword(), ws); auto ws = assign.eval();
st.update_udq(ws, undefined_value); context.update_assign(report_step, assign.keyword(), ws);
st.update_udq(ws, undefined_value);
}
} }
for (const auto& def : this->definitions(UDQVarType::FIELD_VAR)) { for (const auto& def : this->definitions(UDQVarType::FIELD_VAR)) {
auto field_udq = def.eval(context); auto field_udq = def.eval(context);
context.update(def.keyword(), field_udq); context.update_define(def.keyword(), field_udq);
st.update_udq(field_udq, undefined_value); st.update_udq(field_udq, undefined_value);
} }
} }

View File

@ -62,9 +62,6 @@ bool is_udq(const std::string& key) {
this->add("TIME", 0.0); this->add("TIME", 0.0);
} }
void UDQContext::update(const std::string& keyword, const UDQSet& udq_result) {
this->udq_state.add(keyword, udq_result);
}
void UDQContext::add(const std::string& key, double value) { void UDQContext::add(const std::string& key, double value) {
this->values[key] = value; this->values[key] = value;
@ -116,4 +113,12 @@ bool is_udq(const std::string& key) {
const UDQFunctionTable& UDQContext::function_table() const { const UDQFunctionTable& UDQContext::function_table() const {
return this->udqft; return this->udqft;
} }
void UDQContext::update_assign(std::size_t report_step, const std::string& keyword, const UDQSet& udq_result) {
this->udq_state.add_assign(report_step, keyword, udq_result);
}
void UDQContext::update_define(const std::string& keyword, const UDQSet& udq_result) {
this->udq_state.add_define(keyword, udq_result);
}
} }

View File

@ -254,7 +254,7 @@ UDQSet UDQDefine::eval(UDQContext& context) const {
std::string msg = "Invalid runtime type conversion detected when evaluating UDQ"; std::string msg = "Invalid runtime type conversion detected when evaluating UDQ";
throw std::invalid_argument(msg); throw std::invalid_argument(msg);
} }
context.update(this->keyword(), res); context.update_define(this->keyword(), res);
if (res.var_type() == UDQVarType::SCALAR) { if (res.var_type() == UDQVarType::SCALAR) {
/* /*

View File

@ -82,6 +82,15 @@ void UDQState::add(const std::string& udq_key, const UDQSet& result) {
res_iter->second = result; res_iter->second = result;
} }
void UDQState::add_define(const std::string& udq_key, const UDQSet& result) {
this->add(udq_key, result);
}
void UDQState::add_assign(std::size_t report_step, const std::string& udq_key, const UDQSet& result) {
this->assignments[udq_key] = report_step;
this->add(udq_key, result);
}
double UDQState::get(const std::string& key) const { double UDQState::get(const std::string& key) const {
if (!is_udq(key)) if (!is_udq(key))
throw std::logic_error("Key is not a UDQ variable:" + key); throw std::logic_error("Key is not a UDQ variable:" + key);
@ -125,6 +134,16 @@ bool UDQState::operator==(const UDQState& other) const {
this->values == other.values; this->values == other.values;
} }
bool UDQState::assign(std::size_t report_step, const std::string& udq_key) const {
auto assign_iter = this->assignments.find(udq_key);
if (assign_iter == this->assignments.end())
return true;
else
return report_step > assign_iter->second;
}
std::vector<char> UDQState::serialize() const { std::vector<char> UDQState::serialize() const {
Serializer ser; Serializer ser;
ser.put(this->undefined_value); ser.put(this->undefined_value);
@ -133,7 +152,8 @@ std::vector<char> UDQState::serialize() const {
ser.put( set_pair.first ); ser.put( set_pair.first );
set_pair.second.serialize( ser ); set_pair.second.serialize( ser );
} }
return std::move(ser.buffer); ser.put(this->assignments);
return ser.buffer;
} }
@ -151,6 +171,7 @@ void UDQState::deserialize(const std::vector<char>& buffer) {
this->values.insert( std::make_pair(key, udq_set) ); this->values.insert( std::make_pair(key, udq_set) );
} }
} }
this->assignments = ser.get<std::string, std::size_t>();
} }
} }

View File

@ -942,9 +942,9 @@ BOOST_AUTO_TEST_CASE(UDQ_SET_DIV) {
BOOST_AUTO_TEST_CASE(UDQASSIGN_TEST) { BOOST_AUTO_TEST_CASE(UDQASSIGN_TEST) {
UDQAssign as1("WUPR", {}, 1.0); UDQAssign as1("WUPR", {}, 1.0, 1);
UDQAssign as2("WUPR", {"P*"}, 2.0); UDQAssign as2("WUPR", {"P*"}, 2.0, 2);
UDQAssign as3("WUPR", {"P1"}, 4.0); UDQAssign as3("WUPR", {"P1"}, 4.0, 3);
std::vector<std::string> ws1 = {"P1", "P2", "I1", "I2"}; std::vector<std::string> ws1 = {"P1", "P2", "I1", "I2"};
auto res1 = as1.eval(ws1); auto res1 = as1.eval(ws1);
@ -1455,7 +1455,7 @@ BOOST_AUTO_TEST_CASE(UDQ_USAGE) {
BOOST_CHECK_EQUAL( usage.IUAD_size(), 0 ); BOOST_CHECK_EQUAL( usage.IUAD_size(), 0 );
UDAValue uda1("WUX"); UDAValue uda1("WUX");
conf.add_assign(uda1.get<std::string>(), {}, 100); conf.add_assign(uda1.get<std::string>(), {}, 100, 0);
usage.update(conf, uda1, "W1", UDAControl::WCONPROD_ORAT); usage.update(conf, uda1, "W1", UDAControl::WCONPROD_ORAT);
BOOST_CHECK_EQUAL( usage.IUAD_size(), 1 ); BOOST_CHECK_EQUAL( usage.IUAD_size(), 1 );
@ -1842,12 +1842,12 @@ BOOST_AUTO_TEST_CASE(UDQSTATE) {
BOOST_CHECK_THROW(st.get("FUPR"), std::out_of_range); BOOST_CHECK_THROW(st.get("FUPR"), std::out_of_range);
auto fxpr = UDQSet::scalar("FXPR", 100); auto fxpr = UDQSet::scalar("FXPR", 100);
BOOST_CHECK_THROW(st.add("FXPR", fxpr), std::logic_error); BOOST_CHECK_THROW(st.add_define("FXPR", fxpr), std::logic_error);
BOOST_CHECK_THROW(st.get_well_var("OP1", "WUPR"), std::out_of_range); BOOST_CHECK_THROW(st.get_well_var("OP1", "WUPR"), std::out_of_range);
auto fupr = UDQSet::scalar("FUPR", 100); auto fupr = UDQSet::scalar("FUPR", 100);
st.add("FUPR", fupr); st.add_define("FUPR", fupr);
// This is not a well quantity // This is not a well quantity
BOOST_CHECK_THROW(st.get_well_var("OP1", "FUPR"), std::logic_error); BOOST_CHECK_THROW(st.get_well_var("OP1", "FUPR"), std::logic_error);
@ -1856,7 +1856,7 @@ BOOST_AUTO_TEST_CASE(UDQSTATE) {
auto wupr = UDQSet::wells("WUPR", {"P1", "P2"}); auto wupr = UDQSet::wells("WUPR", {"P1", "P2"});
wupr.assign("P1", 75); wupr.assign("P1", 75);
st.add("WUPR", wupr); st.add_define("WUPR", wupr);
BOOST_CHECK(st.has_well_var("P1", "WUPR")); BOOST_CHECK(st.has_well_var("P1", "WUPR"));
// We have a well P2 - but we have not assigned a value to it! // We have a well P2 - but we have not assigned a value to it!
@ -1946,6 +1946,8 @@ DEFINE WUGASRA 750000 - WGLIR '*' /
BOOST_AUTO_TEST_CASE(UDQ_UNDEFINED) { BOOST_AUTO_TEST_CASE(UDQ_UNDEFINED) {
std::string deck_string = R"( std::string deck_string = R"(
SCHEDULE
-- udq #2 -- udq #2
UDQ UDQ
----XX xxxx xxx ----XX xxxx xxx
@ -2129,15 +2131,13 @@ DEFINE FU_VAR91 GOPR TEST /
st.update_well_var("W1", "WGLIR", 1); st.update_well_var("W1", "WGLIR", 1);
st.update_well_var("W2", "WGLIR", 2); st.update_well_var("W2", "WGLIR", 2);
st.update_well_var("W3", "WGLIR", 3); st.update_well_var("W3", "WGLIR", 3);
st.update_group_var("TEST", "GOPR", 1);
udq.eval(0, st, udq_state); udq.eval(0, st, udq_state);
// The current testcase has some ordering & defined / undefined issues which
} }
BOOST_AUTO_TEST_CASE(UDQ_KEY_ERROR) { BOOST_AUTO_TEST_CASE(UDQ_KEY_ERROR) {
std::string deck_string = R"( std::string deck_string = R"(
-- udq #2 -- udq #2
@ -2156,3 +2156,85 @@ UDQ
BOOST_CHECK_THROW(udq.eval(0, st, udq_state), std::out_of_range); BOOST_CHECK_THROW(udq.eval(0, st, udq_state), std::out_of_range);
} }
BOOST_AUTO_TEST_CASE(UDQ_ASSIGN) {
std::string deck_string = R"(
-- udq #2
SCHEDULE
UDQ
ASSIGN FU_VAR1 5 /
DEFINE FU_VAR1 FU_VAR1 + 5 /
/
)";
auto schedule = make_schedule(deck_string);
const auto& udq = schedule.getUDQConfig(0);
auto undefined_value = udq.params().undefinedValue();
UDQState udq_state(undefined_value);
SummaryState st(std::chrono::system_clock::now());
udq.eval(0, st, udq_state);
BOOST_CHECK_EQUAL(st.get("FU_VAR1"), 10);
}
BOOST_AUTO_TEST_CASE(UDQ_ASSIGN_REASSIGN) {
std::string deck_string = R"(
-- udq #2
SCHEDULE
UDQ
ASSIGN FU_VAR1 0 /
DEFINE FU_VAR1 FU_VAR1 + 1 /
/
TSTEP
1 1 1 1 1 /
UDQ
ASSIGN FU_VAR1 0 /
DEFINE FU_VAR1 FU_VAR1 + 1 /
/
TSTEP
1 1 1 1 1 /
UDQ
ASSIGN FU_VAR1 0 /
/
TSTEP
1 1 1 1 1 /
)";
auto schedule = make_schedule(deck_string);
UDQState udq_state(0);
SummaryState st(std::chrono::system_clock::now());
// Counting: 1,2,3,4,5
for (std::size_t report_step = 0; report_step < 5; report_step++) {
const auto& udq = schedule.getUDQConfig(report_step);
udq.eval(report_step, st, udq_state);
auto fu_var1 = st.get("FU_VAR1");
BOOST_CHECK_EQUAL(fu_var1, report_step + 1);
}
// Reset to zero and count: 1,2,3,4,5
for (std::size_t report_step = 5; report_step < 10; report_step++) {
const auto& udq = schedule.getUDQConfig(report_step);
udq.eval(report_step, st, udq_state);
auto fu_var1 = st.get("FU_VAR1");
BOOST_CHECK_EQUAL(fu_var1, report_step - 4);
}
// Reset to zero and stay there.
for (std::size_t report_step = 10; report_step < 15; report_step++) {
const auto& udq = schedule.getUDQConfig(report_step);
udq.eval(report_step, st, udq_state);
auto fu_var1 = st.get("FU_VAR1");
BOOST_CHECK_EQUAL(fu_var1, 0);
}
}

View File

@ -87,32 +87,32 @@ Opm::UDQSet make_udq_set(const std::string& name, Opm::UDQVarType var_type, cons
{ {
auto state = Opm::UDQState{0}; auto state = Opm::UDQState{0};
state.add("WUOPRL", make_udq_set("WUOPRL", state.add_define("WUOPRL", make_udq_set("WUOPRL",
Opm::UDQVarType::WELL_VAR, Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"}, {"PROD1", "PROD2", "WINJ1", "WINJ2"},
{210, 211, 212, 213})); {210, 211, 212, 213}));
state.add("WUOPRU", make_udq_set("WUOPRU", state.add_define("WUOPRU", make_udq_set("WUOPRU",
Opm::UDQVarType::WELL_VAR, Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"}, {"PROD1", "PROD2", "WINJ1", "WINJ2"},
{220, 221, 222, 223})); {220, 221, 222, 223}));
state.add("WULPRL", make_udq_set("WULPRL", state.add_define("WULPRL", make_udq_set("WULPRL",
Opm::UDQVarType::WELL_VAR, Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"}, {"PROD1", "PROD2", "WINJ1", "WINJ2"},
{230, 231, 232, 233})); {230, 231, 232, 233}));
state.add("WULPRU", make_udq_set("WULPRU", state.add_define("WULPRU", make_udq_set("WULPRU",
Opm::UDQVarType::WELL_VAR, Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"}, {"PROD1", "PROD2", "WINJ1", "WINJ2"},
{160, 161, 162, 163})); {160, 161, 162, 163}));
state.add("GUOPRU", make_udq_set("GUOPRU", state.add_define("GUOPRU", make_udq_set("GUOPRU",
Opm::UDQVarType::GROUP_VAR, Opm::UDQVarType::GROUP_VAR,
{"WGRP1", "WGRP2", "GRP1"}, {"WGRP1", "WGRP2", "GRP1"},
{360, 361, 362})); {360, 361, 362}));
state.add("FULPR", Opm::UDQSet::scalar("FULPR", 460)); state.add_define("FULPR", Opm::UDQSet::scalar("FULPR", 460));
return state; return state;
} }