Merge pull request #2112 from joakim-hove/udq-update

Support UDQ UPDATE
This commit is contained in:
Joakim Hove 2020-11-17 10:31:47 +01:00 committed by GitHub
commit 8ffb918650
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 350 additions and 123 deletions

View File

@ -59,8 +59,9 @@ namespace Opm {
void add_record(const DeckRecord& record, const KeywordLocation& location, std::size_t report_step);
void add_unit(const std::string& keyword, const std::string& unit);
void add_update(const std::string& keyword, std::size_t report_step, const KeywordLocation& location, const std::vector<std::string>& data);
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 KeywordLocation& location, const std::vector<std::string>& expression);
void add_define(const std::string& quantity, const KeywordLocation& location, const std::vector<std::string>& expression, std::size_t report_step);
void eval(std::size_t report_step, const WellMatcher& wm, SummaryState& st, UDQState& udq_state) const;
const UDQDefine& define(const std::string& key) const;

View File

@ -44,7 +44,7 @@ namespace Opm {
std::optional<double> get_group_var(const std::string& group, const std::string& var) const;
void add(const std::string& key, double value);
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);
void update_define(std::size_t report_step, const std::string& keyword, const UDQSet& udq_result);
const UDQFunctionTable& function_table() const;
std::vector<std::string> wells() const;
std::vector<std::string> wells(const std::string& pattern) const;

View File

@ -44,11 +44,13 @@ public:
UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
std::size_t report_step,
const KeywordLocation& location,
const std::vector<std::string>& deck_data);
UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
std::size_t report_step,
const KeywordLocation& location,
const std::vector<std::string>& deck_data,
const ParseContext& parseContext,
@ -57,6 +59,7 @@ public:
template <typename T>
UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
std::size_t report_step,
const KeywordLocation& location,
const std::vector<std::string>& deck_data,
const ParseContext& parseContext,
@ -71,6 +74,8 @@ public:
UDQVarType var_type() const;
std::set<UDQTokenType> func_tokens() const;
void required_summary(std::unordered_set<std::string>& summary_keys) const;
void update_status(UDQUpdate update_status, std::size_t report_step);
std::pair<UDQUpdate, std::size_t> status() const;
bool operator==(const UDQDefine& data) const;
@ -82,6 +87,8 @@ public:
serializer(m_var_type);
m_location.serializeOp(serializer);
serializer(string_data);
serializer(m_update_status);
serializer(m_report_step);
}
private:
@ -89,6 +96,8 @@ private:
std::shared_ptr<UDQASTNode> ast;
UDQVarType m_var_type;
KeywordLocation m_location;
std::size_t m_report_step;
UDQUpdate m_update_status;
std::string string_data;
};
}

View File

@ -133,6 +133,13 @@ enum class UDQAction {
UPDATE
};
enum class UDQUpdate {
ON,
OFF,
NEXT
};
enum class UDAControl {
WCONPROD_ORAT,
WCONPROD_GRAT,
@ -170,6 +177,7 @@ namespace UDQ {
UDQVarType varType(const std::string& keyword);
UDQVarType coerce(UDQVarType t1, UDQVarType t2);
UDQAction actionType(const std::string& action_string);
UDQUpdate updateType(const std::string& update_string);
UDQTokenType tokenType(const std::string& func_name);
UDQTokenType funcType(const std::string& func_name);
bool binaryFunc(UDQTokenType token_type);

View File

@ -64,7 +64,6 @@ public:
class UDQSet {
public:
UDQSet(const std::string& name);
UDQSet(const std::string& name, UDQVarType var_type);
UDQSet(const std::string& name, UDQVarType var_type, const std::vector<std::string>& wgnames);
UDQSet(const std::string& name, UDQVarType var_type, std::size_t size);

View File

@ -39,9 +39,10 @@ public:
double get(const std::string& key) 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;
void add_define(const std::string& udq_key, const UDQSet& result);
void add_define(std::size_t report_step, 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;
bool define(const std::string& udq_key, std::pair<UDQUpdate, std::size_t> update_status) const;
double undefined_value() const;
std::vector<char> serialize() const;
@ -53,6 +54,7 @@ private:
double undef_value;
std::unordered_map<std::string, UDQSet> values;
std::unordered_map<std::string, std::size_t> assignments;
std::unordered_map<std::string, std::size_t> defines;
};
}

View File

@ -2070,6 +2070,7 @@ namespace Evaluator {
const auto val = st.get_elapsed() + stepSize;
st.update(this->saveKey_, usys.from_si(m, val));
st.update("TIME", usys.from_si(m, val));
}
private:
@ -2997,6 +2998,7 @@ std::vector<Opm::EclIO::SummaryNode> make_default_nodes(const std::string& keywo
void Opm::out::Summary::SummaryImplementation::configureUDQ(const SummaryConfig& summary_config, const Schedule& sched) {
const std::unordered_set<std::string> time_vectors = {"TIME", "DAY", "MONTH", "YEAR", "YEARS"};
auto nodes = std::vector<Opm::EclIO::SummaryNode> {};
std::unordered_set<std::string> summary_keys;
for (const auto& udq_ptr : sched.udqConfigList())
@ -3009,20 +3011,31 @@ void Opm::out::Summary::SummaryImplementation::configureUDQ(const SummaryConfig&
}
for (const auto& node: nodes) {
// Handler already configured/requested through the normal SummaryConfig path.
if (summary_config.hasSummaryKey(node.unique_key()))
// Handler already exists. Don't add second evaluation.
continue;
// Time related vectors are special cased in the valueKeys_ vector and must be checked explicitly.
if (time_vectors.count(node.keyword) > 0)
continue;
// Handler already registered in the summary evaluator, in some other way.
if ( std::find(this->valueKeys_.begin(), this->valueKeys_.end(), node.unique_key()) != this->valueKeys_.end())
continue;
auto fun_pos = funs.find(node.keyword);
if (fun_pos != funs.end())
if (fun_pos != funs.end()) {
this->extra_parameters.emplace( node.unique_key(), std::make_unique<Evaluator::FunctionRelation>(node, fun_pos->second) );
else {
auto unit = single_values_units.find(node.keyword);
if (unit == single_values_units.end())
throw std::logic_error(fmt::format("Evaluation function for: {} not found ", node.keyword));
this->extra_parameters.emplace( node.unique_key(), std::make_unique<Evaluator::GlobalProcessValue>(node, unit->second));
continue;
}
auto unit = single_values_units.find(node.keyword);
if (unit != single_values_units.end()) {
this->extra_parameters.emplace( node.unique_key(), std::make_unique<Evaluator::GlobalProcessValue>(node, unit->second));
continue;
}
throw std::logic_error(fmt::format("Evaluation function for: {} not found ", node.keyword));
}
}

View File

@ -17,7 +17,11 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <fmt/format.h>
#include <opm/common/OpmLog/KeywordLocation.hpp>
#include <opm/common/utility/OpmInputError.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
@ -87,13 +91,13 @@ namespace Opm {
}
void UDQConfig::add_define(const std::string& quantity, const KeywordLocation& location, const std::vector<std::string>& expression) {
void UDQConfig::add_define(const std::string& quantity, const KeywordLocation& location, const std::vector<std::string>& expression, std::size_t report_step) {
this->add_node(quantity, UDQAction::DEFINE);
auto defined_iter = this->m_definitions.find( quantity );
if (defined_iter != this->m_definitions.end())
this->m_definitions.erase( defined_iter );
this->m_definitions.insert( std::make_pair(quantity, UDQDefine(this->udq_params, quantity, location, expression)));
this->m_definitions.insert( std::make_pair(quantity, UDQDefine(this->udq_params, quantity, report_step, location, expression)));
this->define_order.insert(quantity);
}
@ -120,15 +124,28 @@ namespace Opm {
}
void UDQConfig::add_update(const std::string& keyword, std::size_t report_step, const KeywordLocation& location, const std::vector<std::string>& data) {
if (data.empty())
throw OpmInputError( fmt::format("Missing third item: ON|OFF|NEXT for UDQ update of {}", keyword), location);
if (this->m_definitions.count(keyword) == 0)
throw OpmInputError( fmt::format("UDQ variable: {} must be defined before you can use UPDATE", keyword), location);
auto update_status = UDQ::updateType(data[0]);
auto& define = this->m_definitions[keyword];
define.update_status( update_status, report_step );
}
void UDQConfig::add_record(const DeckRecord& record, const KeywordLocation& location, std::size_t report_step) {
auto action = UDQ::actionType(record.getItem("ACTION").get<RawString>(0));
const auto& quantity = record.getItem("QUANTITY").get<std::string>(0);
const auto& data = RawString::strings( record.getItem("DATA").getData<RawString>() );
if (action == UDQAction::UPDATE)
throw std::invalid_argument("The UDQ action UPDATE is not yet implemented in opm/flow");
if (action == UDQAction::UNITS)
this->add_update(quantity, report_step, location, data);
else if (action == UDQAction::UNITS)
this->add_unit( quantity, data[0] );
else {
if (action == UDQAction::ASSIGN) {
@ -136,7 +153,7 @@ namespace Opm {
double value = std::stod(data.back());
this->add_assign(quantity, selector, value, report_step);
} else if (action == UDQAction::DEFINE)
this->add_define(quantity, location, data);
this->add_define(quantity, location, data, report_step);
else
throw std::runtime_error("Internal error - should not be here");
}
@ -314,8 +331,10 @@ namespace Opm {
}
for (const auto& def : this->definitions(UDQVarType::WELL_VAR)) {
auto ws = def.eval(context);
context.update_define(def.keyword(), ws);
if (udq_state.define(def.keyword(), def.status())) {
auto ws = def.eval(context);
context.update_define(report_step, def.keyword(), ws);
}
}
for (const auto& assign : this->assignments(UDQVarType::GROUP_VAR)) {
@ -326,8 +345,10 @@ namespace Opm {
}
for (const auto& def : this->definitions(UDQVarType::GROUP_VAR)) {
auto ws = def.eval(context);
context.update_define(def.keyword(), ws);
if (udq_state.define(def.keyword(), def.status())) {
auto ws = def.eval(context);
context.update_define(report_step, def.keyword(), ws);
}
}
for (const auto& assign : this->assignments(UDQVarType::FIELD_VAR)) {
@ -338,8 +359,10 @@ namespace Opm {
}
for (const auto& def : this->definitions(UDQVarType::FIELD_VAR)) {
auto field_udq = def.eval(context);
context.update_define(def.keyword(), field_udq);
if (udq_state.define(def.keyword(), def.status())) {
auto field_udq = def.eval(context);
context.update_define(report_step, def.keyword(), field_udq);
}
}
}

View File

@ -56,12 +56,10 @@ bool is_udq(const std::string& key) {
the underlying summary state object.
*/
this->add("ELAPSED", 0.0);
this->add("MSUMLINS", 0.0);
this->add("MSUMNEWT", 0.0);
this->add("NEWTON", 0.0);
this->add("TCPU", 0.0);
this->add("TIME", 0.0);
}
@ -138,8 +136,8 @@ bool is_udq(const std::string& key) {
this->summary_state.update_udq(udq_result, this->udq_state.undefined_value());
}
void UDQContext::update_define(const std::string& keyword, const UDQSet& udq_result) {
this->udq_state.add_define(keyword, udq_result);
void UDQContext::update_define(std::size_t report_step, const std::string& keyword, const UDQSet& udq_result) {
this->udq_state.add_define(report_step, keyword, udq_result);
this->summary_state.update_udq(udq_result, this->udq_state.undefined_value());
}
}

View File

@ -114,19 +114,21 @@ UDQDefine::UDQDefine()
template <typename T>
UDQDefine::UDQDefine(const UDQParams& udq_params_arg,
const std::string& keyword,
std::size_t report_step,
const KeywordLocation& location,
const std::vector<std::string>& deck_data,
const ParseContext& parseContext,
T&& errors) :
UDQDefine(udq_params_arg, keyword, location, deck_data, parseContext, errors)
UDQDefine(udq_params_arg, keyword, report_step, location, deck_data, parseContext, errors)
{}
UDQDefine::UDQDefine(const UDQParams& udq_params_arg,
const std::string& keyword,
std::size_t report_step,
const KeywordLocation& location,
const std::vector<std::string>& deck_data) :
UDQDefine(udq_params_arg, keyword, location, deck_data, ParseContext(), ErrorGuard())
UDQDefine(udq_params_arg, keyword, report_step, location, deck_data, ParseContext(), ErrorGuard())
{}
namespace {
@ -163,13 +165,16 @@ std::optional<std::string> next_token(const std::string& item, std::size_t offse
UDQDefine::UDQDefine(const UDQParams& udq_params,
const std::string& keyword,
std::size_t report_step,
const KeywordLocation& location,
const std::vector<std::string>& deck_data,
const ParseContext& parseContext,
ErrorGuard& errors) :
m_keyword(keyword),
m_var_type(UDQ::varType(keyword)),
m_location(location)
m_report_step(report_step),
m_location(location),
m_update_status(UDQUpdate::ON)
{
std::vector<std::string> string_tokens;
for (const std::string& deck_item : deck_data) {
@ -201,6 +206,11 @@ UDQDefine::UDQDefine(const UDQParams& udq_params,
}
}
void UDQDefine::update_status(UDQUpdate update, std::size_t report_step) {
this->m_update_status = update;
this->m_report_step = report_step;
}
UDQDefine UDQDefine::serializeObject()
@ -211,7 +221,8 @@ UDQDefine UDQDefine::serializeObject()
result.m_var_type = UDQVarType::SEGMENT_VAR;
result.string_data = "test2";
result.m_location = KeywordLocation{"KEYWOR", "file", 100};
result.m_update_status = UDQUpdate::NEXT;
result.m_report_step = 99;
return result;
}
@ -324,6 +335,12 @@ std::set<UDQTokenType> UDQDefine::func_tokens() const {
return this->ast->func_tokens();
}
std::pair<UDQUpdate, std::size_t> UDQDefine::status() const {
return std::make_pair(this->m_update_status, this->m_report_step);
}
bool UDQDefine::operator==(const UDQDefine& data) const {
if ((ast && !data.ast) || (!ast && data.ast))
return false;
@ -333,6 +350,7 @@ bool UDQDefine::operator==(const UDQDefine& data) const {
return this->keyword() == data.keyword() &&
this->m_location == data.location() &&
this->var_type() == data.var_type() &&
this->status() == data.status() &&
this->input_string() == data.input_string();
}

View File

@ -226,6 +226,21 @@ UDQAction actionType(const std::string& action_string) {
}
UDQUpdate updateType(const std::string& update_string) {
if (update_string == "ON")
return UDQUpdate::ON;
if (update_string == "OFF")
return UDQUpdate::OFF;
if (update_string == "NEXT")
return UDQUpdate::NEXT;
throw std::invalid_argument("Invalid status update string " + update_string);
}
bool binaryFunc(UDQTokenType token_type) {
return (binary_func.count(token_type) > 0);
}

View File

@ -87,7 +87,8 @@ void UDQState::add(const std::string& udq_key, const UDQSet& result) {
res_iter->second = result;
}
void UDQState::add_define(const std::string& udq_key, const UDQSet& result) {
void UDQState::add_define(std::size_t report_step, const std::string& udq_key, const UDQSet& result) {
this->defines[udq_key] = report_step;
this->add(udq_key, result);
}
@ -136,7 +137,9 @@ double UDQState::get_group_var(const std::string& group, const std::string& key)
bool UDQState::operator==(const UDQState& other) const {
return this->undef_value == other.undef_value &&
this->values == other.values;
this->values == other.values &&
this->assignments == other.assignments &&
this->defines == other.defines;
}
@ -149,6 +152,20 @@ bool UDQState::assign(std::size_t report_step, const std::string& udq_key) const
return report_step > assign_iter->second;
}
bool UDQState::define(const std::string& udq_key, std::pair<UDQUpdate, std::size_t> update_status) const {
if (update_status.first == UDQUpdate::ON)
return true;
if (update_status.first == UDQUpdate::OFF)
return false;
auto define_iter = this->defines.find(udq_key);
if (define_iter == this->defines.end())
return true;
return define_iter->second < update_status.second;
}
std::vector<char> UDQState::serialize() const {
Serializer ser;
ser.put(this->undef_value);
@ -158,6 +175,7 @@ std::vector<char> UDQState::serialize() const {
set_pair.second.serialize( ser );
}
ser.put(this->assignments);
ser.put(this->defines);
return ser.buffer;
}
@ -177,6 +195,7 @@ void UDQState::deserialize(const std::vector<char>& buffer) {
}
}
this->assignments = ser.get<std::string, std::size_t>();
this->defines = ser.get<std::string, std::size_t>();
}
}

View File

@ -287,6 +287,8 @@ SUMMARY
FOPR
FU_TIME
WGOR
/
WOPR
@ -382,6 +384,7 @@ UDQ
UNITS WUWCT '1' /
DEFINE FUOPR SUM(WOPR) /
UNITS FUOPR 'SM3/DAY' /
DEFINE FU_TIME TIME/
/
@ -450,75 +453,87 @@ WCONINJE
-- BHP upper limit (item 7) should not be exceeding the highest
-- pressure in the PVT table=9014.7psia (default is 100 000psia)
DATES
DATES -- 1
1 'JAN' 2015 /
/
DATES
DATES -- 2
1 'FEB' 2015 /
/
DATES
DATES -- 3
1 'MAR' 2015 /
/
DATES
DATES -- 4
1 'APR' 2015 /
/
DATES
DATES -- 5
1 'MAI' 2015 /
/
DATES
DATES -- 6
1 'JUN' 2015 /
/
DATES
DATES -- 7
1 'JUL' 2015 /
/
DATES
DATES -- 8
1 'AUG' 2015 /
/
DATES
UDQ
UPDATE FU_TIME OFF /
/
DATES -- 9
1 'SEP' 2015 /
/
DATES
DATES -- 10
1 'OCT' 2015 /
/
DATES
DATES -- 11
1 'NOV' 2015 /
/
DATES
DATES -- 12
1 'DEC' 2015 /
/
DATES
UDQ
UPDATE FU_TIME NEXT /
/
DATES -- 13
1 'JAN' 2016 /
/
DATES
DATES -- 14
1 'FEB' 2016 /
/
DATES
DATES -- 15
1 'MAR' 2016 /
/
DATES
UDQ
UPDATE FU_TIME ON /
/
DATES -- 16
1 'APR' 2016 /
/
DATES
DATES -- 17
1 'MAI' 2016 /
/
DATES
DATES -- 18
1 'JUN' 2016 /
/

View File

@ -155,10 +155,12 @@ int ecl_sum_get_last_report_step(const EclIO::ESmry& smry)
return static_cast<int>(smry.get_at_rstep("TIME").size());
}
int ecl_sum_iget_report_end(const EclIO::ESmry& smry, const int reportStep)
{
return smry.timestepIdxAtReportstepStart(reportStep + 1) - 1;
}
}
@ -342,6 +344,23 @@ BOOST_AUTO_TEST_CASE(UDQ_WUWCT) {
ecl_sum_get_general_var(ecl_sum, step, "FUOPR"));
BOOST_CHECK_EQUAL( wopr_sum, ecl_sum_get_general_var(ecl_sum, step, "FOPR"));
}
{
const auto& fu_time = ecl_sum.get_at_rstep("FU_TIME");
BOOST_CHECK_CLOSE(fu_time[7 - 1], 212, 1e-5);
// UPDATE OFF
BOOST_CHECK_CLOSE(fu_time[8 - 1], 212, 1e-5);
BOOST_CHECK_CLOSE(fu_time[9 - 1] , 212, 1e-5);
BOOST_CHECK_CLOSE(fu_time[10 - 1], 212, 1e-5);
BOOST_CHECK_CLOSE(fu_time[11 - 1], 212, 1e-5);
// UPDATE NEXT
BOOST_CHECK_CLOSE(fu_time[12 - 1], 342, 1e-5);
BOOST_CHECK_CLOSE(fu_time[13 - 1], 342, 1e-5);
BOOST_CHECK_CLOSE(fu_time[14 - 1], 342, 1e-5);
// UPDATE ON
BOOST_CHECK_CLOSE(fu_time[15 - 1], 456, 1e-5);
BOOST_CHECK_CLOSE(fu_time[16 - 1], 487, 1e-5);
}
}
}

View File

@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(GROUP_VARIABLES)
KeywordLocation location;
UDQParams udqp;
UDQFunctionTable udqft;
UDQDefine def_group(udqp, "GUOPRL", location, {"(", "5000", "-", "GOPR", "LOWER", "*", "0.13", "-", "GOPR", "UPPER", "*", "0.15", ")" , "*", "0.89"});
UDQDefine def_group(udqp, "GUOPRL", 0, location, {"(", "5000", "-", "GOPR", "LOWER", "*", "0.13", "-", "GOPR", "UPPER", "*", "0.15", ")" , "*", "0.89"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, {}, st, udq_state);
@ -104,8 +104,8 @@ BOOST_AUTO_TEST_CASE(SUBTRACT)
KeywordLocation location;
UDQParams udqp;
UDQFunctionTable udqft;
UDQDefine def(udqp, "WU", location, {"16", "-", "8", "-", "4", "-", "2", "-", "1"});
UDQDefine scalar(udqp, "WU", location, {"16"});
UDQDefine def(udqp, "WU", 0, location, {"16", "-", "8", "-", "4", "-", "2", "-", "1"});
UDQDefine scalar(udqp, "WU", 0, location, {"16"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
@ -124,10 +124,10 @@ BOOST_AUTO_TEST_CASE(TEST)
KeywordLocation location;
UDQParams udqp;
UDQFunctionTable udqft;
UDQDefine def1(udqp, "WUWI3", location, {"GOPR" , "MAU", "*", "2.0", "*", "0.25", "*", "10"});
UDQDefine def2(udqp, "WUWI3", location, {"2.0", "*", "0.25", "*", "3"});
UDQDefine def3(udqp, "WUWI3", location, {"GOPR" , "FIELD", "-", "2.0", "*", "3"});
UDQDefine def4(udqp, "WUWI3", location, {"FOPR" , "/", "2"});
UDQDefine def1(udqp, "WUWI3",0, location, {"GOPR" , "MAU", "*", "2.0", "*", "0.25", "*", "10"});
UDQDefine def2(udqp, "WUWI3",0, location, {"2.0", "*", "0.25", "*", "3"});
UDQDefine def3(udqp, "WUWI3",0, location, {"GOPR" , "FIELD", "-", "2.0", "*", "3"});
UDQDefine def4(udqp, "WUWI3",0, location, {"FOPR" , "/", "2"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
@ -160,12 +160,12 @@ BOOST_AUTO_TEST_CASE(TEST)
This expression has a well set as target type, and involves group with
wildcard that is not supported by flow.
*/
BOOST_CHECK_THROW( UDQDefine(udqp, "WUWI2", location, {"GOPR", "G*", "*", "2.0"}), OpmInputError);
BOOST_CHECK_THROW( UDQDefine(udqp, "WUWI2",0, location, {"GOPR", "G*", "*", "2.0"}), OpmInputError);
/*
UDQVarType == BLOCK is not yet supported.
*/
BOOST_CHECK_THROW( UDQDefine(udqp, "WUWI2", location, {"BPR", "1","1", "1", "*", "2.0"}), OpmInputError);
BOOST_CHECK_THROW( UDQDefine(udqp, "WUWI2",0, location, {"BPR", "1","1", "1", "*", "2.0"}), OpmInputError);
}
@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE(MIX_SCALAR) {
UDQFunctionTable udqft;
UDQParams udqp;
KeywordLocation location;
UDQDefine def_add(udqp, "WU", location, {"WOPR", "+", "1"});
UDQDefine def_add(udqp, "WU",0, location, {"WOPR", "+", "1"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1"}), st, udq_state);
@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE(MIX_SCALAR) {
BOOST_AUTO_TEST_CASE(UDQ_TABLE_EXCEPTION) {
UDQParams udqp;
KeywordLocation location;
BOOST_CHECK_THROW(UDQDefine(udqp, "WU", location, {"TUPRICE[WOPR]"}), std::invalid_argument);
BOOST_CHECK_THROW(UDQDefine(udqp, "WU",0, location, {"TUPRICE[WOPR]"}), std::invalid_argument);
}
@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(UDQFieldSetTest) {
*/
{
UDQDefine def_fopr(udqp, "FUOPR", location, {"SUM", "(", "WOPR", ")"});
UDQDefine def_fopr(udqp, "FUOPR",0, location, {"SUM", "(", "WOPR", ")"});
auto fopr_res = def_fopr.eval(context);
BOOST_CHECK_EQUAL( fopr_res[0].get(), 10.0 );
}
@ -300,7 +300,7 @@ BOOST_AUTO_TEST_CASE(UDQ_GROUP_TEST) {
KeywordLocation location;
UDQParams udqp;
UDQFunctionTable udqft(udqp);
UDQDefine def_fopr(udqp, "FUOPR", location, {"SUM", "(", "GOPR", ")"});
UDQDefine def_fopr(udqp, "FUOPR",0, location, {"SUM", "(", "GOPR", ")"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, {}, st, udq_state);
@ -323,7 +323,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
UDQFunctionTable udqft(udqp);
KeywordLocation location;
{
UDQDefine def(udqp, "WUBHP", location, {"WBHP"});
UDQDefine def(udqp, "WUBHP",0, location, {"WBHP"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"W1", "W2", "W3"}), st, udq_state);
@ -342,7 +342,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
BOOST_CHECK(!empty_value);
}
{
UDQDefine def(udqp, "WUBHP", location, {"WBHP" , "'P*'"});
UDQDefine def(udqp, "WUBHP",0, location, {"WBHP" , "'P*'"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"I1", "I2", "P1", "P2"}), st, udq_state);
@ -360,7 +360,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
BOOST_CHECK_EQUAL( res["I1"].defined(), false);
}
{
UDQDefine def(udqp, "WUBHP", location, {"NINT" , "(", "WBHP", ")"});
UDQDefine def(udqp, "WUBHP",0, location, {"NINT" , "(", "WBHP", ")"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1", "P2", "I1", "I2"}), st, udq_state);
@ -583,7 +583,7 @@ BOOST_AUTO_TEST_CASE(UDQ_CONTEXT) {
BOOST_CHECK_EQUAL(*ctx.get("JAN"), 1.0);
BOOST_CHECK_THROW(ctx.get("NO_SUCH_KEY"), std::out_of_range);
for (std::string& key : std::vector<std::string>({"ELAPSED", "MSUMLINS", "MSUMNEWT", "NEWTON", "TCPU", "TIME"}))
for (std::string& key : std::vector<std::string>({"MSUMLINS", "MSUMNEWT", "NEWTON", "TCPU"}))
BOOST_CHECK_NO_THROW( ctx.get(key) );
st.update("SX:KEY", 1.0);
@ -986,8 +986,8 @@ BOOST_AUTO_TEST_CASE(UDQ_POW_TEST) {
KeywordLocation location;
UDQFunctionTable udqft;
UDQParams udqp;
UDQDefine def_pow1(udqp, "WU", location, {"WOPR", "+", "WWPR", "*", "WGOR", "^", "WWIR"});
UDQDefine def_pow2(udqp, "WU", location, {"(", "WOPR", "+", "WWPR", ")", "^", "(", "WOPR", "+" , "WGOR", "*", "WWIR", "-", "WBHP", ")"});
UDQDefine def_pow1(udqp, "WU",0, location, {"WOPR", "+", "WWPR", "*", "WGOR", "^", "WWIR"});
UDQDefine def_pow2(udqp, "WU",0, location, {"(", "WOPR", "+", "WWPR", ")", "^", "(", "WOPR", "+" , "WGOR", "*", "WWIR", "-", "WBHP", ")"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1"}), st, udq_state);
@ -1008,7 +1008,7 @@ BOOST_AUTO_TEST_CASE(UDQ_CMP_TEST) {
KeywordLocation location;
UDQFunctionTable udqft;
UDQParams udqp;
UDQDefine def_cmp(udqp, "WU", location, {"WOPR", ">", "WWPR", "+", "WGOR", "*", "WWIR"});
UDQDefine def_cmp(udqp, "WU",0, location, {"WOPR", ">", "WWPR", "+", "WGOR", "*", "WWIR"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1", "P2"}), st, udq_state);
@ -1053,7 +1053,7 @@ BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
st.update_well_var("PD4", "WWPR", 4);
{
UDQDefine def(udqp, "WUOPR", location, {"WOPR", "'PA*'"});
UDQDefine def(udqp, "WUOPR",0, location, {"WOPR", "'PA*'"});
auto res = def.eval(context);
BOOST_CHECK_EQUAL(4U, res.size());
auto well1 = res["PA1"];
@ -1067,7 +1067,7 @@ BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
BOOST_CHECK( !well4.defined() );
}
{
UDQDefine def(udqp, "WUOPR", location, {"1"});
UDQDefine def(udqp, "WUOPR",0, location, {"1"});
auto res = def.eval(context);
BOOST_CHECK_EQUAL(4U, res.size());
auto well1 = res["PA1"];
@ -1083,7 +1083,7 @@ BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
BOOST_CHECK_EQUAL(well4.get() , 1);
}
{
UDQDefine def(udqp, "WUOPR", location, {"WOPR", "'PA1'"});
UDQDefine def(udqp, "WUOPR",0, location, {"WOPR", "'PA1'"});
auto res = def.eval(context);
BOOST_CHECK_EQUAL(4U, res.size());
auto well1 = res["PA1"];
@ -1106,8 +1106,8 @@ BOOST_AUTO_TEST_CASE(UDQ_SORTD_NAN) {
UDQParams udqp;
UDQFunctionTable udqft;
KeywordLocation location;
UDQDefine def(udqp, "WUPR1" , location, {"1", "/", "(", "WWIR", "'OP*'" , ")"});
UDQDefine def_sort(udqp , "WUPR3", location, {"SORTD", "(", "WUPR1", ")" });
UDQDefine def(udqp, "WUPR1" ,0, location, {"1", "/", "(", "WWIR", "'OP*'" , ")"});
UDQDefine def_sort(udqp , "WUPR3",0, location, {"SORTD", "(", "WUPR1", ")" });
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"OP1", "OP2", "OP3", "OP4"}), st, udq_state);
@ -1118,10 +1118,10 @@ BOOST_AUTO_TEST_CASE(UDQ_SORTD_NAN) {
st.update_well_var("OP4", "WWIR", 4.0);
auto res1 = def.eval(context);
context.update_define(def.keyword(), res1);
context.update_define(0, def.keyword(), res1);
auto res_sort1 = def_sort.eval(context);
context.update_define(def_sort.keyword(), res_sort1);
context.update_define(0, def_sort.keyword(), res_sort1);
BOOST_CHECK_EQUAL(res_sort1["OP1"].get(), 1.0);
BOOST_CHECK_EQUAL(res_sort1["OP2"].get(), 2.0);
BOOST_CHECK_EQUAL(res_sort1["OP3"].get(), 3.0);
@ -1133,11 +1133,11 @@ BOOST_AUTO_TEST_CASE(UDQ_SORTD_NAN) {
auto res2 = def.eval(context);
BOOST_CHECK_EQUAL(res2.defined_size(), 3U);
context.update_define(def.keyword(), res2);
context.update_define(0, def.keyword(), res2);
BOOST_CHECK( st.has_well_var("OP4", "WUPR1"));
auto res_sort2 = def_sort.eval(context);
context.update_define(def.keyword(), res2);
context.update_define(0, def.keyword(), res2);
BOOST_CHECK_EQUAL(res_sort2.defined_size(), 3U);
BOOST_CHECK_EQUAL(res_sort2["OP2"].get(), 1.0);
@ -1152,8 +1152,8 @@ BOOST_AUTO_TEST_CASE(UDQ_SORTA) {
KeywordLocation location;
UDQParams udqp;
UDQFunctionTable udqft;
UDQDefine def1(udqp, "WUPR1" , location, {"1", "/", "(", "WWCT", "'OP*'", "+", "0.00001", ")"});
UDQDefine def_sort(udqp , "WUPR3", location, {"SORTA", "(", "WUPR1", ")" });
UDQDefine def1(udqp, "WUPR1" ,0, location, {"1", "/", "(", "WWCT", "'OP*'", "+", "0.00001", ")"});
UDQDefine def_sort(udqp , "WUPR3",0, location, {"SORTA", "(", "WUPR1", ")" });
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"OPL01", "OPL02", "OPU01", "OPU02"}), st, udq_state);
@ -1164,7 +1164,7 @@ BOOST_AUTO_TEST_CASE(UDQ_SORTA) {
st.update_well_var("OPU02", "WWCT", 0.0);
auto res1 = def1.eval(context);
context.update_define(def1.keyword(), res1);
context.update_define(0, def1.keyword(), res1);
auto res_sort = def_sort.eval(context);
BOOST_CHECK_EQUAL(res_sort["OPL02"].get(), 1.0);
@ -1178,12 +1178,12 @@ BOOST_AUTO_TEST_CASE(UDQ_BASIC_MATH_TEST) {
UDQParams udqp;
UDQFunctionTable udqft;
KeywordLocation location;
UDQDefine def_add(udqp, "WU2OPR", location, {"WOPR", "+", "WOPR"});
UDQDefine def_sub(udqp, "WU2OPR", location, {"WOPR", "-", "WOPR"});
UDQDefine def_mul(udqp, "WU2OPR", location, {"WOPR", "*", "WOPR"});
UDQDefine def_div(udqp, "WU2OPR", location, {"WOPR", "/", "WOPR"});
UDQDefine def_muladd(udqp, "WUX", location, {"WOPR", "+", "WOPR", "*", "WOPR"});
UDQDefine def_wuwct(udqp , "WUWCT", location, {"WWPR", "/", "(", "WOPR", "+", "WWPR", ")"});
UDQDefine def_add(udqp, "WU2OPR",0, location, {"WOPR", "+", "WOPR"});
UDQDefine def_sub(udqp, "WU2OPR",0, location, {"WOPR", "-", "WOPR"});
UDQDefine def_mul(udqp, "WU2OPR",0, location, {"WOPR", "*", "WOPR"});
UDQDefine def_div(udqp, "WU2OPR",0, location, {"WOPR", "/", "WOPR"});
UDQDefine def_muladd(udqp, "WUX",0, location, {"WOPR", "+", "WOPR", "*", "WOPR"});
UDQDefine def_wuwct(udqp , "WUWCT",0, location, {"WWPR", "/", "(", "WOPR", "+", "WWPR", ")"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1", "P2", "P3", "P4"}), st, udq_state);
@ -1245,7 +1245,7 @@ BOOST_AUTO_TEST_CASE(DECK_TEST) {
KeywordLocation location;
UDQParams udqp;
UDQFunctionTable udqft(udqp);
UDQDefine def(udqp, "WUOPRL", location, {"(", "WOPR", "OP1", "-", "150", ")", "*", "0.90"});
UDQDefine def(udqp, "WUOPRL",0, location, {"(", "WOPR", "OP1", "-", "150", ")", "*", "0.90"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"OP1", "OP2", "OP3"}), st, udq_state);
@ -1264,10 +1264,10 @@ BOOST_AUTO_TEST_CASE(DECK_TEST) {
BOOST_AUTO_TEST_CASE(UDQPARSE_TEST1) {
KeywordLocation location;
UDQParams udqp;
UDQDefine def1(udqp, "WUBHP", location, {"1/(WWCT", "'W1*')"});
UDQDefine def1(udqp, "WUBHP",0, location, {"1/(WWCT", "'W1*')"});
BOOST_CHECK_EQUAL( def1.input_string() , "1/(WWCT 'W1*')");
UDQDefine def2(udqp, "WUBHP", location, {"2*(1", "+" , "WBHP)"});
UDQDefine def2(udqp, "WUBHP",0, location, {"2*(1", "+" , "WBHP)"});
BOOST_CHECK_EQUAL( def2.input_string() , "2*(1 + WBHP)");
}
@ -1280,7 +1280,7 @@ BOOST_AUTO_TEST_CASE(UDQ_PARSE_ERROR) {
KeywordLocation location;
parseContext.update(ParseContext::UDQ_PARSE_ERROR, InputError::IGNORE);
{
UDQDefine def1(udqp, "WUBHP", location, tokens, parseContext, errors);
UDQDefine def1(udqp, "WUBHP",0, location, tokens, parseContext, errors);
SummaryState st(std::chrono::system_clock::now());
UDQFunctionTable udqft(udqp);
UDQState udq_state(udqp.undefinedValue());
@ -1292,7 +1292,7 @@ BOOST_AUTO_TEST_CASE(UDQ_PARSE_ERROR) {
}
parseContext.update(ParseContext::UDQ_PARSE_ERROR, InputError::THROW_EXCEPTION);
BOOST_CHECK_THROW( UDQDefine(udqp, "WUBHP", location, tokens, parseContext, errors), OpmInputError);
BOOST_CHECK_THROW( UDQDefine(udqp, "WUBHP",0, location, tokens, parseContext, errors), OpmInputError);
}
BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
@ -1304,8 +1304,8 @@ BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
KeywordLocation location;
parseContext.update(ParseContext::UDQ_TYPE_ERROR, InputError::IGNORE);
{
UDQDefine def1(udqp, "FUBHP", location, tokens1, parseContext, errors);
UDQDefine def2(udqp, "WUBHP", location, tokens2, parseContext, errors);
UDQDefine def1(udqp, "FUBHP",0, location, tokens1, parseContext, errors);
UDQDefine def2(udqp, "WUBHP",0, location, tokens2, parseContext, errors);
SummaryState st(std::chrono::system_clock::now());
UDQFunctionTable udqft(udqp);
@ -1326,7 +1326,7 @@ BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
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", location, tokens1, parseContext, errors), OpmInputError);
BOOST_CHECK_THROW( UDQDefine(udqp, "FUBHP",0, location, tokens1, parseContext, errors), OpmInputError);
}
@ -1868,12 +1868,12 @@ BOOST_AUTO_TEST_CASE(UDQSTATE) {
BOOST_CHECK_THROW(st.get("FUPR"), std::out_of_range);
auto fxpr = UDQSet::scalar("FXPR", 100);
BOOST_CHECK_THROW(st.add_define("FXPR", fxpr), std::logic_error);
BOOST_CHECK_THROW(st.add_define(0, "FXPR", fxpr), std::logic_error);
BOOST_CHECK_THROW(st.get_well_var("OP1", "WUPR"), std::out_of_range);
auto fupr = UDQSet::scalar("FUPR", 100);
st.add_define("FUPR", fupr);
st.add_define(0, "FUPR", fupr);
// This is not a well quantity
BOOST_CHECK_THROW(st.get_well_var("OP1", "FUPR"), std::logic_error);
@ -1882,7 +1882,7 @@ BOOST_AUTO_TEST_CASE(UDQSTATE) {
auto wupr = UDQSet::wells("WUPR", {"P1", "P2"});
wupr.assign("P1", 75);
st.add_define("WUPR", wupr);
st.add_define(0, "WUPR", wupr);
BOOST_CHECK(st.has_well_var("P1", "WUPR"));
// We have a well P2 - but we have not assigned a value to it!
@ -2283,7 +2283,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DIV_TEST) {
KeywordLocation location;
UDQFunctionTable udqft;
UDQParams udqp;
UDQDefine def_div(udqp, "FU", location, {"128", "/", "2", "/", "4", "/", "8"});
UDQDefine def_div(udqp, "FU",0, location, {"128", "/", "2", "/", "4", "/", "8"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, {}, st, udq_state);
@ -2396,3 +2396,91 @@ UDQ
BOOST_CHECK_EQUAL(fu_var3, 50);
BOOST_CHECK_EQUAL(fu_var4, 50);
}
BOOST_AUTO_TEST_CASE(UDQ_UPDATE) {
std::string invalid1 = R"(
SCHEDULE
UDQ
UPDATE FU_XXX /
/
)";
std::string valid = R"(
SCHEDULE
UDQ
DEFINE FU_TIME TIME /
/
TSTEP
1 /
UDQ
UPDATE FU_TIME OFF /
/
TSTEP
1 /
TSTEP
1 /
UDQ
UPDATE FU_TIME NEXT /
/
TSTEP
1 /
TSTEP
1 /
UDQ
UPDATE FU_TIME OFF /
/
TSTEP
1 /
)";
BOOST_CHECK_THROW(make_schedule(invalid1), std::exception);
auto schedule = make_schedule(valid);
UDQState udq_state(0);
SummaryState st(std::chrono::system_clock::now());
UDQSet result = UDQSet::scalar("RES", 0);
{
const auto& udq = schedule.getUDQConfig(0);
const auto& def = udq.define("FU_TIME");
BOOST_CHECK( udq_state.define(def.keyword(), def.status()));
udq_state.add_define(0, def.keyword(), result);
}
{
const auto& udq = schedule.getUDQConfig(1);
const auto& def = udq.define("FU_TIME");
BOOST_CHECK( !udq_state.define(def.keyword(), def.status()));
}
{
const auto& udq = schedule.getUDQConfig(2);
const auto& def = udq.define("FU_TIME");
BOOST_CHECK( !udq_state.define(def.keyword(), def.status()));
}
{
const auto& udq = schedule.getUDQConfig(3);
const auto& def = udq.define("FU_TIME");
BOOST_CHECK( udq_state.define(def.keyword(), def.status()));
udq_state.add_define(3, def.keyword(), result);
}
{
const auto& udq = schedule.getUDQConfig(4);
const auto& def = udq.define("FU_TIME");
BOOST_CHECK( !udq_state.define(def.keyword(), def.status()));
}
{
const auto& udq = schedule.getUDQConfig(5);
const auto& def = udq.define("FU_TIME");
BOOST_CHECK( !udq_state.define(def.keyword(), def.status()));
}
}

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};
state.add_define("WUOPRL", make_udq_set("WUOPRL",
Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"},
{210, 211, 212, 213}));
state.add_define(0, "WUOPRL", make_udq_set("WUOPRL",
Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"},
{210, 211, 212, 213}));
state.add_define("WUOPRU", make_udq_set("WUOPRU",
Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"},
{220, 221, 222, 223}));
state.add_define(0, "WUOPRU", make_udq_set("WUOPRU",
Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"},
{220, 221, 222, 223}));
state.add_define("WULPRL", make_udq_set("WULPRL",
Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"},
{230, 231, 232, 233}));
state.add_define(0, "WULPRL", make_udq_set("WULPRL",
Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"},
{230, 231, 232, 233}));
state.add_define("WULPRU", make_udq_set("WULPRU",
Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"},
{160, 161, 162, 163}));
state.add_define(0, "WULPRU", make_udq_set("WULPRU",
Opm::UDQVarType::WELL_VAR,
{"PROD1", "PROD2", "WINJ1", "WINJ2"},
{160, 161, 162, 163}));
state.add_define("GUOPRU", make_udq_set("GUOPRU",
Opm::UDQVarType::GROUP_VAR,
{"WGRP1", "WGRP2", "GRP1"},
{360, 361, 362}));
state.add_define(0, "GUOPRU", make_udq_set("GUOPRU",
Opm::UDQVarType::GROUP_VAR,
{"WGRP1", "WGRP2", "GRP1"},
{360, 361, 362}));
state.add_define("FULPR", Opm::UDQSet::scalar("FULPR", 460));
state.add_define(0, "FULPR", Opm::UDQSet::scalar("FULPR", 460));
return state;
}