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_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_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_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; void eval(std::size_t report_step, const WellMatcher& wm, SummaryState& st, UDQState& udq_state) const;
const UDQDefine& define(const std::string& key) 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; 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_assign(std::size_t report_step, 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); void update_define(std::size_t report_step, 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> wells(const std::string& pattern) const; std::vector<std::string> wells(const std::string& pattern) const;

View File

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

View File

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

View File

@ -64,7 +64,6 @@ public:
class UDQSet { class UDQSet {
public: public:
UDQSet(const std::string& name);
UDQSet(const std::string& name, UDQVarType var_type); 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, const std::vector<std::string>& wgnames);
UDQSet(const std::string& name, UDQVarType var_type, std::size_t size); 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(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_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); 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 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; double undefined_value() const;
std::vector<char> serialize() const; std::vector<char> serialize() const;
@ -53,6 +54,7 @@ private:
double undef_value; double undef_value;
std::unordered_map<std::string, UDQSet> values; std::unordered_map<std::string, UDQSet> values;
std::unordered_map<std::string, std::size_t> assignments; 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; const auto val = st.get_elapsed() + stepSize;
st.update(this->saveKey_, usys.from_si(m, val)); st.update(this->saveKey_, usys.from_si(m, val));
st.update("TIME", usys.from_si(m, val));
} }
private: 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) { 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> {}; auto nodes = std::vector<Opm::EclIO::SummaryNode> {};
std::unordered_set<std::string> summary_keys; std::unordered_set<std::string> summary_keys;
for (const auto& udq_ptr : sched.udqConfigList()) for (const auto& udq_ptr : sched.udqConfigList())
@ -3009,20 +3011,31 @@ void Opm::out::Summary::SummaryImplementation::configureUDQ(const SummaryConfig&
} }
for (const auto& node: nodes) { for (const auto& node: nodes) {
// Handler already configured/requested through the normal SummaryConfig path.
if (summary_config.hasSummaryKey(node.unique_key())) 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; continue;
auto fun_pos = funs.find(node.keyword); 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) ); this->extra_parameters.emplace( node.unique_key(), std::make_unique<Evaluator::FunctionRelation>(node, fun_pos->second) );
else { continue;
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));
} }
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/>. along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <fmt/format.h>
#include <opm/common/OpmLog/KeywordLocation.hpp> #include <opm/common/OpmLog/KeywordLocation.hpp>
#include <opm/common/utility/OpmInputError.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp> #include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.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); this->add_node(quantity, UDQAction::DEFINE);
auto defined_iter = this->m_definitions.find( quantity ); auto defined_iter = this->m_definitions.find( quantity );
if (defined_iter != this->m_definitions.end()) if (defined_iter != this->m_definitions.end())
this->m_definitions.erase( defined_iter ); 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); 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) { 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)); 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>() );
if (action == UDQAction::UPDATE) if (action == UDQAction::UPDATE)
throw std::invalid_argument("The UDQ action UPDATE is not yet implemented in opm/flow"); this->add_update(quantity, report_step, location, data);
else if (action == UDQAction::UNITS)
if (action == UDQAction::UNITS)
this->add_unit( quantity, data[0] ); this->add_unit( quantity, data[0] );
else { else {
if (action == UDQAction::ASSIGN) { if (action == UDQAction::ASSIGN) {
@ -136,7 +153,7 @@ namespace Opm {
double value = std::stod(data.back()); double value = std::stod(data.back());
this->add_assign(quantity, selector, value, report_step); this->add_assign(quantity, selector, value, report_step);
} else if (action == UDQAction::DEFINE) } else if (action == UDQAction::DEFINE)
this->add_define(quantity, location, data); this->add_define(quantity, location, data, report_step);
else else
throw std::runtime_error("Internal error - should not be here"); 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)) { for (const auto& def : this->definitions(UDQVarType::WELL_VAR)) {
auto ws = def.eval(context); if (udq_state.define(def.keyword(), def.status())) {
context.update_define(def.keyword(), ws); auto ws = def.eval(context);
context.update_define(report_step, def.keyword(), ws);
}
} }
for (const auto& assign : this->assignments(UDQVarType::GROUP_VAR)) { for (const auto& assign : this->assignments(UDQVarType::GROUP_VAR)) {
@ -326,8 +345,10 @@ namespace Opm {
} }
for (const auto& def : this->definitions(UDQVarType::GROUP_VAR)) { for (const auto& def : this->definitions(UDQVarType::GROUP_VAR)) {
auto ws = def.eval(context); if (udq_state.define(def.keyword(), def.status())) {
context.update_define(def.keyword(), ws); auto ws = def.eval(context);
context.update_define(report_step, def.keyword(), ws);
}
} }
for (const auto& assign : this->assignments(UDQVarType::FIELD_VAR)) { for (const auto& assign : this->assignments(UDQVarType::FIELD_VAR)) {
@ -338,8 +359,10 @@ namespace Opm {
} }
for (const auto& def : this->definitions(UDQVarType::FIELD_VAR)) { for (const auto& def : this->definitions(UDQVarType::FIELD_VAR)) {
auto field_udq = def.eval(context); if (udq_state.define(def.keyword(), def.status())) {
context.update_define(def.keyword(), field_udq); 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. the underlying summary state object.
*/ */
this->add("ELAPSED", 0.0);
this->add("MSUMLINS", 0.0); this->add("MSUMLINS", 0.0);
this->add("MSUMNEWT", 0.0); this->add("MSUMNEWT", 0.0);
this->add("NEWTON", 0.0); this->add("NEWTON", 0.0);
this->add("TCPU", 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()); this->summary_state.update_udq(udq_result, this->udq_state.undefined_value());
} }
void UDQContext::update_define(const std::string& keyword, const UDQSet& udq_result) { void UDQContext::update_define(std::size_t report_step, const std::string& keyword, const UDQSet& udq_result) {
this->udq_state.add_define(keyword, udq_result); this->udq_state.add_define(report_step, keyword, udq_result);
this->summary_state.update_udq(udq_result, this->udq_state.undefined_value()); this->summary_state.update_udq(udq_result, this->udq_state.undefined_value());
} }
} }

View File

@ -114,19 +114,21 @@ UDQDefine::UDQDefine()
template <typename T> template <typename T>
UDQDefine::UDQDefine(const UDQParams& udq_params_arg, UDQDefine::UDQDefine(const UDQParams& udq_params_arg,
const std::string& keyword, const std::string& keyword,
std::size_t report_step,
const KeywordLocation& location, const KeywordLocation& location,
const std::vector<std::string>& deck_data, const std::vector<std::string>& deck_data,
const ParseContext& parseContext, const ParseContext& parseContext,
T&& errors) : 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, UDQDefine::UDQDefine(const UDQParams& udq_params_arg,
const std::string& keyword, const std::string& keyword,
std::size_t report_step,
const KeywordLocation& location, const KeywordLocation& location,
const std::vector<std::string>& deck_data) : 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 { 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, UDQDefine::UDQDefine(const UDQParams& udq_params,
const std::string& keyword, const std::string& keyword,
std::size_t report_step,
const KeywordLocation& location, const KeywordLocation& location,
const std::vector<std::string>& deck_data, const std::vector<std::string>& deck_data,
const ParseContext& parseContext, const ParseContext& parseContext,
ErrorGuard& errors) : ErrorGuard& errors) :
m_keyword(keyword), m_keyword(keyword),
m_var_type(UDQ::varType(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; std::vector<std::string> string_tokens;
for (const std::string& deck_item : deck_data) { 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() UDQDefine UDQDefine::serializeObject()
@ -211,7 +221,8 @@ UDQDefine UDQDefine::serializeObject()
result.m_var_type = UDQVarType::SEGMENT_VAR; result.m_var_type = UDQVarType::SEGMENT_VAR;
result.string_data = "test2"; result.string_data = "test2";
result.m_location = KeywordLocation{"KEYWOR", "file", 100}; result.m_location = KeywordLocation{"KEYWOR", "file", 100};
result.m_update_status = UDQUpdate::NEXT;
result.m_report_step = 99;
return result; return result;
} }
@ -324,6 +335,12 @@ std::set<UDQTokenType> UDQDefine::func_tokens() const {
return this->ast->func_tokens(); 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 { bool UDQDefine::operator==(const UDQDefine& data) const {
if ((ast && !data.ast) || (!ast && data.ast)) if ((ast && !data.ast) || (!ast && data.ast))
return false; return false;
@ -333,6 +350,7 @@ bool UDQDefine::operator==(const UDQDefine& data) const {
return this->keyword() == data.keyword() && return this->keyword() == data.keyword() &&
this->m_location == data.location() && this->m_location == data.location() &&
this->var_type() == data.var_type() && this->var_type() == data.var_type() &&
this->status() == data.status() &&
this->input_string() == data.input_string(); 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) { bool binaryFunc(UDQTokenType token_type) {
return (binary_func.count(token_type) > 0); 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; 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); 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 { bool UDQState::operator==(const UDQState& other) const {
return this->undef_value == other.undef_value && 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; 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 { std::vector<char> UDQState::serialize() const {
Serializer ser; Serializer ser;
ser.put(this->undef_value); ser.put(this->undef_value);
@ -158,6 +175,7 @@ std::vector<char> UDQState::serialize() const {
set_pair.second.serialize( ser ); set_pair.second.serialize( ser );
} }
ser.put(this->assignments); ser.put(this->assignments);
ser.put(this->defines);
return ser.buffer; 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->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 FOPR
FU_TIME
WGOR WGOR
/ /
WOPR WOPR
@ -382,6 +384,7 @@ UDQ
UNITS WUWCT '1' / UNITS WUWCT '1' /
DEFINE FUOPR SUM(WOPR) / DEFINE FUOPR SUM(WOPR) /
UNITS FUOPR 'SM3/DAY' / UNITS FUOPR 'SM3/DAY' /
DEFINE FU_TIME TIME/
/ /
@ -450,75 +453,87 @@ WCONINJE
-- BHP upper limit (item 7) should not be exceeding the highest -- BHP upper limit (item 7) should not be exceeding the highest
-- pressure in the PVT table=9014.7psia (default is 100 000psia) -- pressure in the PVT table=9014.7psia (default is 100 000psia)
DATES DATES -- 1
1 'JAN' 2015 / 1 'JAN' 2015 /
/ /
DATES DATES -- 2
1 'FEB' 2015 / 1 'FEB' 2015 /
/ /
DATES DATES -- 3
1 'MAR' 2015 / 1 'MAR' 2015 /
/ /
DATES DATES -- 4
1 'APR' 2015 / 1 'APR' 2015 /
/ /
DATES DATES -- 5
1 'MAI' 2015 / 1 'MAI' 2015 /
/ /
DATES DATES -- 6
1 'JUN' 2015 / 1 'JUN' 2015 /
/ /
DATES DATES -- 7
1 'JUL' 2015 / 1 'JUL' 2015 /
/ /
DATES DATES -- 8
1 'AUG' 2015 / 1 'AUG' 2015 /
/ /
DATES UDQ
UPDATE FU_TIME OFF /
/
DATES -- 9
1 'SEP' 2015 / 1 'SEP' 2015 /
/ /
DATES DATES -- 10
1 'OCT' 2015 / 1 'OCT' 2015 /
/ /
DATES DATES -- 11
1 'NOV' 2015 / 1 'NOV' 2015 /
/ /
DATES DATES -- 12
1 'DEC' 2015 / 1 'DEC' 2015 /
/ /
DATES UDQ
UPDATE FU_TIME NEXT /
/
DATES -- 13
1 'JAN' 2016 / 1 'JAN' 2016 /
/ /
DATES DATES -- 14
1 'FEB' 2016 / 1 'FEB' 2016 /
/ /
DATES DATES -- 15
1 'MAR' 2016 / 1 'MAR' 2016 /
/ /
DATES UDQ
UPDATE FU_TIME ON /
/
DATES -- 16
1 'APR' 2016 / 1 'APR' 2016 /
/ /
DATES DATES -- 17
1 'MAI' 2016 / 1 'MAI' 2016 /
/ /
DATES DATES -- 18
1 'JUN' 2016 / 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()); return static_cast<int>(smry.get_at_rstep("TIME").size());
} }
int ecl_sum_iget_report_end(const EclIO::ESmry& smry, const int reportStep) int ecl_sum_iget_report_end(const EclIO::ESmry& smry, const int reportStep)
{ {
return smry.timestepIdxAtReportstepStart(reportStep + 1) - 1; 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")); ecl_sum_get_general_var(ecl_sum, step, "FUOPR"));
BOOST_CHECK_EQUAL( wopr_sum, ecl_sum_get_general_var(ecl_sum, step, "FOPR")); 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; KeywordLocation location;
UDQParams udqp; UDQParams udqp;
UDQFunctionTable udqft; 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()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, {}, st, udq_state); UDQContext context(udqft, {}, st, udq_state);
@ -104,8 +104,8 @@ BOOST_AUTO_TEST_CASE(SUBTRACT)
KeywordLocation location; KeywordLocation location;
UDQParams udqp; UDQParams udqp;
UDQFunctionTable udqft; UDQFunctionTable udqft;
UDQDefine def(udqp, "WU", location, {"16", "-", "8", "-", "4", "-", "2", "-", "1"}); UDQDefine def(udqp, "WU", 0, location, {"16", "-", "8", "-", "4", "-", "2", "-", "1"});
UDQDefine scalar(udqp, "WU", location, {"16"}); UDQDefine scalar(udqp, "WU", 0, location, {"16"});
SummaryState st(std::chrono::system_clock::now()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
@ -124,10 +124,10 @@ BOOST_AUTO_TEST_CASE(TEST)
KeywordLocation location; KeywordLocation location;
UDQParams udqp; UDQParams udqp;
UDQFunctionTable udqft; UDQFunctionTable udqft;
UDQDefine def1(udqp, "WUWI3", location, {"GOPR" , "MAU", "*", "2.0", "*", "0.25", "*", "10"}); UDQDefine def1(udqp, "WUWI3",0, location, {"GOPR" , "MAU", "*", "2.0", "*", "0.25", "*", "10"});
UDQDefine def2(udqp, "WUWI3", location, {"2.0", "*", "0.25", "*", "3"}); UDQDefine def2(udqp, "WUWI3",0, location, {"2.0", "*", "0.25", "*", "3"});
UDQDefine def3(udqp, "WUWI3", location, {"GOPR" , "FIELD", "-", "2.0", "*", "3"}); UDQDefine def3(udqp, "WUWI3",0, location, {"GOPR" , "FIELD", "-", "2.0", "*", "3"});
UDQDefine def4(udqp, "WUWI3", location, {"FOPR" , "/", "2"}); UDQDefine def4(udqp, "WUWI3",0, location, {"FOPR" , "/", "2"});
SummaryState st(std::chrono::system_clock::now()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); 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 This expression has a well set as target type, and involves group with
wildcard that is not supported by flow. 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. 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; UDQFunctionTable udqft;
UDQParams udqp; UDQParams udqp;
KeywordLocation location; 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()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1"}), st, udq_state); 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) { BOOST_AUTO_TEST_CASE(UDQ_TABLE_EXCEPTION) {
UDQParams udqp; UDQParams udqp;
KeywordLocation location; 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); auto fopr_res = def_fopr.eval(context);
BOOST_CHECK_EQUAL( fopr_res[0].get(), 10.0 ); BOOST_CHECK_EQUAL( fopr_res[0].get(), 10.0 );
} }
@ -300,7 +300,7 @@ BOOST_AUTO_TEST_CASE(UDQ_GROUP_TEST) {
KeywordLocation location; KeywordLocation location;
UDQParams udqp; UDQParams udqp;
UDQFunctionTable udqft(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()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, {}, st, udq_state); UDQContext context(udqft, {}, st, udq_state);
@ -323,7 +323,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
UDQFunctionTable udqft(udqp); UDQFunctionTable udqft(udqp);
KeywordLocation location; KeywordLocation location;
{ {
UDQDefine def(udqp, "WUBHP", location, {"WBHP"}); UDQDefine def(udqp, "WUBHP",0, location, {"WBHP"});
SummaryState st(std::chrono::system_clock::now()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"W1", "W2", "W3"}), st, udq_state); UDQContext context(udqft, WellMatcher({"W1", "W2", "W3"}), st, udq_state);
@ -342,7 +342,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DEFINETEST) {
BOOST_CHECK(!empty_value); 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()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"I1", "I2", "P1", "P2"}), st, udq_state); 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); 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()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1", "P2", "I1", "I2"}), st, udq_state); 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_EQUAL(*ctx.get("JAN"), 1.0);
BOOST_CHECK_THROW(ctx.get("NO_SUCH_KEY"), std::out_of_range); 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) ); BOOST_CHECK_NO_THROW( ctx.get(key) );
st.update("SX:KEY", 1.0); st.update("SX:KEY", 1.0);
@ -986,8 +986,8 @@ BOOST_AUTO_TEST_CASE(UDQ_POW_TEST) {
KeywordLocation location; KeywordLocation location;
UDQFunctionTable udqft; UDQFunctionTable udqft;
UDQParams udqp; UDQParams udqp;
UDQDefine def_pow1(udqp, "WU", location, {"WOPR", "+", "WWPR", "*", "WGOR", "^", "WWIR"}); UDQDefine def_pow1(udqp, "WU",0, location, {"WOPR", "+", "WWPR", "*", "WGOR", "^", "WWIR"});
UDQDefine def_pow2(udqp, "WU", location, {"(", "WOPR", "+", "WWPR", ")", "^", "(", "WOPR", "+" , "WGOR", "*", "WWIR", "-", "WBHP", ")"}); UDQDefine def_pow2(udqp, "WU",0, location, {"(", "WOPR", "+", "WWPR", ")", "^", "(", "WOPR", "+" , "WGOR", "*", "WWIR", "-", "WBHP", ")"});
SummaryState st(std::chrono::system_clock::now()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1"}), st, udq_state); UDQContext context(udqft, WellMatcher({"P1"}), st, udq_state);
@ -1008,7 +1008,7 @@ BOOST_AUTO_TEST_CASE(UDQ_CMP_TEST) {
KeywordLocation location; KeywordLocation location;
UDQFunctionTable udqft; UDQFunctionTable udqft;
UDQParams udqp; 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()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1", "P2"}), st, udq_state); 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); 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); auto res = def.eval(context);
BOOST_CHECK_EQUAL(4U, res.size()); BOOST_CHECK_EQUAL(4U, res.size());
auto well1 = res["PA1"]; auto well1 = res["PA1"];
@ -1067,7 +1067,7 @@ BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
BOOST_CHECK( !well4.defined() ); BOOST_CHECK( !well4.defined() );
} }
{ {
UDQDefine def(udqp, "WUOPR", location, {"1"}); UDQDefine def(udqp, "WUOPR",0, location, {"1"});
auto res = def.eval(context); auto res = def.eval(context);
BOOST_CHECK_EQUAL(4U, res.size()); BOOST_CHECK_EQUAL(4U, res.size());
auto well1 = res["PA1"]; auto well1 = res["PA1"];
@ -1083,7 +1083,7 @@ BOOST_AUTO_TEST_CASE(UDQ_SCALAR_SET) {
BOOST_CHECK_EQUAL(well4.get() , 1); 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); auto res = def.eval(context);
BOOST_CHECK_EQUAL(4U, res.size()); BOOST_CHECK_EQUAL(4U, res.size());
auto well1 = res["PA1"]; auto well1 = res["PA1"];
@ -1106,8 +1106,8 @@ BOOST_AUTO_TEST_CASE(UDQ_SORTD_NAN) {
UDQParams udqp; UDQParams udqp;
UDQFunctionTable udqft; UDQFunctionTable udqft;
KeywordLocation location; KeywordLocation location;
UDQDefine def(udqp, "WUPR1" , location, {"1", "/", "(", "WWIR", "'OP*'" , ")"}); UDQDefine def(udqp, "WUPR1" ,0, location, {"1", "/", "(", "WWIR", "'OP*'" , ")"});
UDQDefine def_sort(udqp , "WUPR3", location, {"SORTD", "(", "WUPR1", ")" }); UDQDefine def_sort(udqp , "WUPR3",0, location, {"SORTD", "(", "WUPR1", ")" });
SummaryState st(std::chrono::system_clock::now()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"OP1", "OP2", "OP3", "OP4"}), st, udq_state); 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); st.update_well_var("OP4", "WWIR", 4.0);
auto res1 = def.eval(context); 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); 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["OP1"].get(), 1.0);
BOOST_CHECK_EQUAL(res_sort1["OP2"].get(), 2.0); BOOST_CHECK_EQUAL(res_sort1["OP2"].get(), 2.0);
BOOST_CHECK_EQUAL(res_sort1["OP3"].get(), 3.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); auto res2 = def.eval(context);
BOOST_CHECK_EQUAL(res2.defined_size(), 3U); 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")); BOOST_CHECK( st.has_well_var("OP4", "WUPR1"));
auto res_sort2 = def_sort.eval(context); 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.defined_size(), 3U);
BOOST_CHECK_EQUAL(res_sort2["OP2"].get(), 1.0); BOOST_CHECK_EQUAL(res_sort2["OP2"].get(), 1.0);
@ -1152,8 +1152,8 @@ BOOST_AUTO_TEST_CASE(UDQ_SORTA) {
KeywordLocation location; KeywordLocation location;
UDQParams udqp; UDQParams udqp;
UDQFunctionTable udqft; UDQFunctionTable udqft;
UDQDefine def1(udqp, "WUPR1" , location, {"1", "/", "(", "WWCT", "'OP*'", "+", "0.00001", ")"}); UDQDefine def1(udqp, "WUPR1" ,0, location, {"1", "/", "(", "WWCT", "'OP*'", "+", "0.00001", ")"});
UDQDefine def_sort(udqp , "WUPR3", location, {"SORTA", "(", "WUPR1", ")" }); UDQDefine def_sort(udqp , "WUPR3",0, location, {"SORTA", "(", "WUPR1", ")" });
SummaryState st(std::chrono::system_clock::now()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"OPL01", "OPL02", "OPU01", "OPU02"}), st, udq_state); 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); st.update_well_var("OPU02", "WWCT", 0.0);
auto res1 = def1.eval(context); 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); auto res_sort = def_sort.eval(context);
BOOST_CHECK_EQUAL(res_sort["OPL02"].get(), 1.0); BOOST_CHECK_EQUAL(res_sort["OPL02"].get(), 1.0);
@ -1178,12 +1178,12 @@ BOOST_AUTO_TEST_CASE(UDQ_BASIC_MATH_TEST) {
UDQParams udqp; UDQParams udqp;
UDQFunctionTable udqft; UDQFunctionTable udqft;
KeywordLocation location; KeywordLocation location;
UDQDefine def_add(udqp, "WU2OPR", location, {"WOPR", "+", "WOPR"}); UDQDefine def_add(udqp, "WU2OPR",0, location, {"WOPR", "+", "WOPR"});
UDQDefine def_sub(udqp, "WU2OPR", location, {"WOPR", "-", "WOPR"}); UDQDefine def_sub(udqp, "WU2OPR",0, location, {"WOPR", "-", "WOPR"});
UDQDefine def_mul(udqp, "WU2OPR", location, {"WOPR", "*", "WOPR"}); UDQDefine def_mul(udqp, "WU2OPR",0, location, {"WOPR", "*", "WOPR"});
UDQDefine def_div(udqp, "WU2OPR", location, {"WOPR", "/", "WOPR"}); UDQDefine def_div(udqp, "WU2OPR",0, location, {"WOPR", "/", "WOPR"});
UDQDefine def_muladd(udqp, "WUX", location, {"WOPR", "+", "WOPR", "*", "WOPR"}); UDQDefine def_muladd(udqp, "WUX",0, location, {"WOPR", "+", "WOPR", "*", "WOPR"});
UDQDefine def_wuwct(udqp , "WUWCT", location, {"WWPR", "/", "(", "WOPR", "+", "WWPR", ")"}); UDQDefine def_wuwct(udqp , "WUWCT",0, location, {"WWPR", "/", "(", "WOPR", "+", "WWPR", ")"});
SummaryState st(std::chrono::system_clock::now()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"P1", "P2", "P3", "P4"}), st, udq_state); UDQContext context(udqft, WellMatcher({"P1", "P2", "P3", "P4"}), st, udq_state);
@ -1245,7 +1245,7 @@ BOOST_AUTO_TEST_CASE(DECK_TEST) {
KeywordLocation location; KeywordLocation location;
UDQParams udqp; UDQParams udqp;
UDQFunctionTable udqft(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()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, WellMatcher({"OP1", "OP2", "OP3"}), st, udq_state); 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) { BOOST_AUTO_TEST_CASE(UDQPARSE_TEST1) {
KeywordLocation location; KeywordLocation location;
UDQParams udqp; 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*')"); 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)"); BOOST_CHECK_EQUAL( def2.input_string() , "2*(1 + WBHP)");
} }
@ -1280,7 +1280,7 @@ BOOST_AUTO_TEST_CASE(UDQ_PARSE_ERROR) {
KeywordLocation location; KeywordLocation location;
parseContext.update(ParseContext::UDQ_PARSE_ERROR, InputError::IGNORE); 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()); SummaryState st(std::chrono::system_clock::now());
UDQFunctionTable udqft(udqp); UDQFunctionTable udqft(udqp);
UDQState udq_state(udqp.undefinedValue()); 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); 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) { BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
@ -1304,8 +1304,8 @@ BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
KeywordLocation location; KeywordLocation location;
parseContext.update(ParseContext::UDQ_TYPE_ERROR, InputError::IGNORE); parseContext.update(ParseContext::UDQ_TYPE_ERROR, InputError::IGNORE);
{ {
UDQDefine def1(udqp, "FUBHP", location, tokens1, parseContext, errors); UDQDefine def1(udqp, "FUBHP",0, location, tokens1, parseContext, errors);
UDQDefine def2(udqp, "WUBHP", location, tokens2, parseContext, errors); UDQDefine def2(udqp, "WUBHP",0, location, tokens2, parseContext, errors);
SummaryState st(std::chrono::system_clock::now()); SummaryState st(std::chrono::system_clock::now());
UDQFunctionTable udqft(udqp); UDQFunctionTable udqft(udqp);
@ -1326,7 +1326,7 @@ BOOST_AUTO_TEST_CASE(UDQ_TYPE_ERROR) {
parseContext.update(ParseContext::UDQ_TYPE_ERROR, InputError::THROW_EXCEPTION); parseContext.update(ParseContext::UDQ_TYPE_ERROR, InputError::THROW_EXCEPTION);
// This fails because the well expression (WBHP + 1) is assigned to the field variable FUBHP // 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); 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_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); 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_define("FUPR", fupr); st.add_define(0, "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);
@ -1882,7 +1882,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_define("WUPR", wupr); st.add_define(0, "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!
@ -2283,7 +2283,7 @@ BOOST_AUTO_TEST_CASE(UDQ_DIV_TEST) {
KeywordLocation location; KeywordLocation location;
UDQFunctionTable udqft; UDQFunctionTable udqft;
UDQParams udqp; 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()); SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue()); UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, {}, st, udq_state); UDQContext context(udqft, {}, st, udq_state);
@ -2396,3 +2396,91 @@ UDQ
BOOST_CHECK_EQUAL(fu_var3, 50); BOOST_CHECK_EQUAL(fu_var3, 50);
BOOST_CHECK_EQUAL(fu_var4, 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}; auto state = Opm::UDQState{0};
state.add_define("WUOPRL", make_udq_set("WUOPRL", state.add_define(0, "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_define("WUOPRU", make_udq_set("WUOPRU", state.add_define(0, "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_define("WULPRL", make_udq_set("WULPRL", state.add_define(0, "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_define("WULPRU", make_udq_set("WULPRU", state.add_define(0, "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_define("GUOPRU", make_udq_set("GUOPRU", state.add_define(0, "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_define("FULPR", Opm::UDQSet::scalar("FULPR", 460)); state.add_define(0, "FULPR", Opm::UDQSet::scalar("FULPR", 460));
return state; return state;
} }