diff --git a/opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp b/opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp index c21b0ca87..6fc6800c9 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp @@ -90,20 +90,25 @@ public: bool has_well_var(const std::string& var) const; bool has_group_var(const std::string& group, const std::string& var) const; bool has_group_var(const std::string& var) const; + bool has_conn_var(const std::string& well, const std::string& var, std::size_t global_index) const; + void update(const std::string& key, double value); void update_well_var(const std::string& well, const std::string& var, double value); void update_group_var(const std::string& group, const std::string& var, double value); void update_elapsed(double delta); void update_udq(const UDQSet& udq_set, double undefined_value); + void update_conn_var(const std::string& well, const std::string& var, std::size_t global_index, double value); double get(const std::string&) const; double get(const std::string&, double) const; double get_elapsed() const; double get_well_var(const std::string& well, const std::string& var) const; double get_group_var(const std::string& group, const std::string& var) const; + double get_conn_var(const std::string& conn, const std::string& var, std::size_t global_index) const; double get_well_var(const std::string& well, const std::string& var, double) const; double get_group_var(const std::string& group, const std::string& var, double) const; + double get_conn_var(const std::string& conn, const std::string& var, std::size_t global_index, double) const; const std::vector& wells() const; std::vector wells(const std::string& var) const; @@ -130,6 +135,10 @@ private: std::unordered_map> group_values; std::set m_groups; mutable std::optional> group_names; + + // The first key is the variable and the second key is the well and the + // third is the global index. NB: The global_index has offset 1! + std::unordered_map>> conn_values; }; diff --git a/src/opm/output/eclipse/Summary.cpp b/src/opm/output/eclipse/Summary.cpp index 7af799ac7..67cfafa4b 100644 --- a/src/opm/output/eclipse/Summary.cpp +++ b/src/opm/output/eclipse/Summary.cpp @@ -1983,6 +1983,10 @@ void updateValue(const Opm::EclIO::SummaryNode& node, const double value, Opm::S st.update_group_var(node.wgname, node.keyword, value); break; + case Cat::Connection: + st.update_conn_var(node.wgname, node.keyword, node.number, value); + break; + default: st.update(node.unique_key(), value); break; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/SummaryState.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/SummaryState.cpp index b799e617f..b0e8f11b2 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/SummaryState.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/SummaryState.cpp @@ -53,10 +53,11 @@ namespace { return is_total(key.substr(0,sep_pos)); } + template + using map2 = std::unordered_map>; - using map2 = std::unordered_map>; - - bool has_var(const map2& values, const std::string& var1, const std::string var2) { + template + bool has_var(const map2& values, const std::string& var1, const std::string& var2) { const auto& var1_iter = values.find(var1); if (var1_iter == values.end()) return false; @@ -68,7 +69,8 @@ namespace { return true; } - void erase_var(map2& values, std::set& var2_set, const std::string& var1, const std::string var2) { + template + void erase_var(map2& values, std::set& var2_set, const std::string& var1, const std::string& var2) { const auto& var1_iter = values.find(var1); if (var1_iter == values.end()) return; @@ -84,7 +86,8 @@ namespace { } } - std::vector var2_list(const map2& values, const std::string& var1) { + template + std::vector var2_list(const map2& values, const std::string& var1) { const auto& var1_iter = values.find(var1); if (var1_iter == values.end()) return {}; @@ -166,6 +169,35 @@ namespace { } } + bool SummaryState::has_conn_var(const std::string& well, const std::string& var, std::size_t global_index) const { + if (!has_var(this->conn_values, var, well)) + return false; + + const auto& index_map = this->conn_values.at(var).at(well); + return (index_map.count(global_index) > 0); + } + + void SummaryState::update_conn_var(const std::string& well, const std::string& var, std::size_t global_index, double value) { + std::string key = var + ":" + well + ":" + std::to_string(global_index); + if (is_total(var)) { + this->values[key] += value; + this->conn_values[var][well][global_index] += value; + } else { + this->values[key] = value; + this->conn_values[var][well][global_index] = value; + } + } + + double SummaryState::get_conn_var(const std::string& well, const std::string& var, std::size_t global_index) const { + return this->conn_values.at(var).at(well).at(global_index); + } + + double SummaryState::get_conn_var(const std::string& well, const std::string& var, std::size_t global_index, double default_value) const { + if (this->has_conn_var(well, var, global_index)) + return this->get_conn_var(well, var, global_index); + return default_value; + } + void SummaryState::update_udq(const UDQSet& udq_set, double undefined_value) { auto var_type = udq_set.var_type(); @@ -319,6 +351,7 @@ namespace { + std::vector SummaryState::serialize() const { Serializer ser; ser.put(this->sim_start); @@ -327,15 +360,25 @@ namespace { ser.put(this->well_values.size()); - for (const auto& [well, v] : this->well_values) { - ser.put(well); - ser.put_map(v); + for (const auto& [var, well_map] : this->well_values) { + ser.put(var); + ser.put_map(well_map); } ser.put(this->group_values.size()); - for (const auto& [group, v] : this->group_values) { - ser.put(group); - ser.put_map(v); + for (const auto& [var, group_map] : this->group_values) { + ser.put(var); + ser.put_map(group_map); + } + + ser.put(this->conn_values.size()); + for (const auto& [var, well_conn_map] : this->conn_values) { + ser.put(var); + ser.put(well_conn_map.size()); + for (const auto& [well, conn_map] : well_conn_map) { + ser.put(well); + ser.put_map(conn_map); + } } return std::move(ser.buffer); @@ -375,6 +418,19 @@ namespace { } this->group_names.reset(); } + + { + std::size_t num_conn_var = ser.get(); + for (std::size_t var_index = 0; var_index < num_conn_var; var_index++) { + std::string var = ser.get(); + std::size_t num_wells = ser.get(); + for (std::size_t well_index = 0; well_index < num_wells; well_index++) { + std::string well = ser.get(); + auto conn_map = ser.get_map(); + this->conn_values[var][well] = std::move(conn_map); + } + } + } } std::ostream& operator<<(std::ostream& stream, const SummaryState& st) { @@ -395,6 +451,7 @@ namespace { this->wells() == other.wells() && this->group_values == other.group_values && this->m_groups == other.m_groups && - this->groups() == other.groups(); + this->groups() == other.groups() && + this->conn_values == other.conn_values; } } diff --git a/tests/test_Summary.cpp b/tests/test_Summary.cpp index 76a4a1a53..577115330 100755 --- a/tests/test_Summary.cpp +++ b/tests/test_Summary.cpp @@ -2138,6 +2138,13 @@ BOOST_AUTO_TEST_CASE(Test_SummaryState) { BOOST_CHECK( !st.has_group_var("G1", "GWCT")); BOOST_CHECK( !st.has("GWCT:G1") ); + BOOST_CHECK(!st.has_conn_var("OP2", "COPR", 100)); + st.update_conn_var("OP2", "COPR", 100, 123); + BOOST_CHECK(st.has_conn_var("OP2", "COPR", 100)); + BOOST_CHECK_EQUAL(st.get_conn_var("OP2", "COPR", 100), 123); + BOOST_CHECK_EQUAL(st.get_conn_var("OP2", "COPR", 101, 99), 99); + + auto buffer = st.serialize(); Opm::SummaryState st2(TimeService::now()); st2.deserialize(buffer);