Serializer class: SummaryState & UDQState
This commit is contained in:
parent
432f666768
commit
4b3304730c
@ -404,6 +404,7 @@ if(ENABLE_ECL_OUTPUT)
|
||||
tests/test_RFT.cpp
|
||||
tests/test_rst.cpp
|
||||
tests/test_Solution.cpp
|
||||
tests/test_Serializer.cpp
|
||||
tests/test_Summary.cpp
|
||||
tests/test_Summary_Group.cpp
|
||||
tests/test_Tables.cpp
|
||||
@ -518,6 +519,7 @@ list( APPEND PUBLIC_HEADER_FILES
|
||||
opm/common/OpmLog/OpmLog.hpp
|
||||
opm/common/OpmLog/StreamLog.hpp
|
||||
opm/common/OpmLog/TimerLog.hpp
|
||||
opm/common/utility/Serializer.hpp
|
||||
opm/common/utility/ActiveGridCells.hpp
|
||||
opm/common/utility/FileSystem.hpp
|
||||
opm/common/utility/numeric/cmp.hpp
|
||||
|
106
opm/common/utility/Serializer.hpp
Normal file
106
opm/common/utility/Serializer.hpp
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2020 Equinor ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#ifndef OPM_SERIALIZER_HPP
|
||||
#define OPM_SERIALIZER_HPP
|
||||
|
||||
namespace Opm {
|
||||
/*
|
||||
This is a very basic serialization class used to support serialization of
|
||||
small state objects from opm common. The main serialization code used in
|
||||
opm/flow is initiated and controlled from the restart code, and therefor
|
||||
slightly cumbersome to use for objects which should be serialized not as part
|
||||
of the restart code.
|
||||
*/
|
||||
|
||||
|
||||
class Serializer {
|
||||
public:
|
||||
Serializer() = default;
|
||||
explicit Serializer(const std::vector<char>& buffer_arg) :
|
||||
buffer(buffer_arg)
|
||||
{}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void put(const T& value) {
|
||||
this->pack(std::addressof(value), sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get() {
|
||||
T value;
|
||||
std::memcpy(&value, &this->buffer[pos], sizeof(T));
|
||||
this->pos += sizeof(T);
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
void put(const std::unordered_map<K,T>& values) {
|
||||
this->put(values.size());
|
||||
for (const auto& value_pair : values) {
|
||||
this->put(value_pair.first);
|
||||
this->put(value_pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename K, typename T>
|
||||
std::unordered_map<K,T> get() {
|
||||
std::unordered_map<K,T> values;
|
||||
auto size = this->get<std::size_t>();
|
||||
for (std::size_t index = 0; index < size; index++) {
|
||||
auto key = this->get<K>();
|
||||
auto value = this->get<T>();
|
||||
values.insert( std::make_pair(key,value) );
|
||||
}
|
||||
return std::move(values);
|
||||
}
|
||||
|
||||
|
||||
std::vector<char> buffer;
|
||||
private:
|
||||
void pack(const void * ptr, std::size_t value_size) {
|
||||
std::size_t write_pos = this->buffer.size();
|
||||
std::size_t new_size = write_pos + value_size;
|
||||
this->buffer.resize( new_size );
|
||||
std::memcpy(&this->buffer[write_pos], ptr, value_size);
|
||||
}
|
||||
|
||||
std::size_t pos = 0;
|
||||
};
|
||||
|
||||
template <>
|
||||
void inline Serializer::put(const std::string& value) {
|
||||
this->put<std::string::size_type>(value.size());
|
||||
this->pack(value.c_str(), value.size());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string inline Serializer::get<std::string>() {
|
||||
std::string::size_type length = this->get<std::string::size_type>();
|
||||
this->pos += length;
|
||||
return {std::addressof(this->buffer[this->pos - length]), length};
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
@ -26,6 +26,7 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <opm/common/utility/Serializer.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
|
||||
|
||||
namespace Opm {
|
||||
@ -35,7 +36,6 @@ public:
|
||||
UDQScalar() = default;
|
||||
explicit UDQScalar(double value);
|
||||
explicit UDQScalar(const std::string& wgname);
|
||||
UDQScalar(const std::string& wgname, double value);
|
||||
|
||||
void operator+=(const UDQScalar& rhs);
|
||||
void operator+=(double rhs);
|
||||
@ -51,6 +51,9 @@ public:
|
||||
bool defined() const;
|
||||
double value() const;
|
||||
const std::string& wgname() const;
|
||||
bool operator==(const UDQScalar& other) const;
|
||||
static UDQScalar deserialize(Serializer& ser);
|
||||
void serialize(Serializer& ser) const;
|
||||
public:
|
||||
std::optional<double> m_value;
|
||||
std::string m_wgname;
|
||||
@ -64,6 +67,8 @@ public:
|
||||
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, std::size_t size);
|
||||
void serialize(Serializer& ser) const;
|
||||
static UDQSet deserialize(Serializer& ser);
|
||||
static UDQSet scalar(const std::string& name, double value);
|
||||
static UDQSet empty(const std::string& name);
|
||||
static UDQSet wells(const std::string& name, const std::vector<std::string>& wells);
|
||||
@ -98,6 +103,7 @@ public:
|
||||
const std::string& name() const;
|
||||
void name(const std::string& name);
|
||||
UDQVarType var_type() const;
|
||||
bool operator==(const UDQSet& other) const;
|
||||
private:
|
||||
UDQSet() = default;
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.hpp>
|
||||
|
||||
@ -40,6 +41,9 @@ public:
|
||||
double get_well_var(const std::string& well, const std::string& var) const;
|
||||
void add(const UDQSet& result);
|
||||
|
||||
std::vector<char> serialize() const;
|
||||
void deserialize(const std::vector<char>& buffer);
|
||||
bool operator==(const UDQState& other) const;
|
||||
private:
|
||||
double get_wg_var(const std::string& well, const std::string& key, UDQVarType var_type) const;
|
||||
double undefined_value;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <opm/common/utility/Serializer.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
|
||||
@ -303,80 +304,22 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
class Serializer {
|
||||
public:
|
||||
Serializer() = default;
|
||||
explicit Serializer(const std::vector<char>& buffer_arg) :
|
||||
buffer(buffer_arg)
|
||||
{}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void put(const T& value) {
|
||||
this->pack(std::addressof(value), sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
T get() {
|
||||
T value;
|
||||
std::memcpy(&value, &this->buffer[pos], sizeof(T));
|
||||
this->pos += sizeof(T);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::vector<char> buffer;
|
||||
private:
|
||||
void pack(const void * ptr, std::size_t value_size) {
|
||||
std::size_t write_pos = this->buffer.size();
|
||||
std::size_t new_size = write_pos + value_size;
|
||||
this->buffer.resize( new_size );
|
||||
std::memcpy(&this->buffer[write_pos], ptr, value_size);
|
||||
}
|
||||
|
||||
std::size_t pos = 0;
|
||||
};
|
||||
|
||||
template <>
|
||||
void Serializer::put(const std::string& value) {
|
||||
this->put<std::string::size_type>(value.size());
|
||||
this->pack(value.c_str(), value.size());
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string Serializer::get() {
|
||||
std::string::size_type length = this->get<std::string::size_type>();
|
||||
this->pos += length;
|
||||
return {std::addressof(this->buffer[this->pos - length]), length};
|
||||
}
|
||||
|
||||
void put_map(Serializer& ser, const std::unordered_map<std::string, double>& values) {
|
||||
ser.put(values.size());
|
||||
for (const auto& value_pair : values) {
|
||||
ser.put(value_pair.first);
|
||||
ser.put(value_pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<char> SummaryState::serialize() const {
|
||||
Serializer ser;
|
||||
ser.put(this->elapsed);
|
||||
put_map(ser, values);
|
||||
ser.put(values);
|
||||
|
||||
ser.put(this->well_values.size());
|
||||
for (const auto& well_var_pair : this->well_values) {
|
||||
ser.put(well_var_pair.first);
|
||||
put_map(ser, well_var_pair.second);
|
||||
ser.put(well_var_pair.second);
|
||||
}
|
||||
|
||||
ser.put(this->group_values.size());
|
||||
for (const auto& group_var_pair : this->group_values) {
|
||||
ser.put(group_var_pair.first);
|
||||
put_map(ser, group_var_pair.second);
|
||||
ser.put(group_var_pair.second);
|
||||
}
|
||||
|
||||
return std::move(ser.buffer);
|
||||
@ -393,14 +336,7 @@ namespace {
|
||||
|
||||
Serializer ser(buffer);
|
||||
this->elapsed = ser.get<double>();
|
||||
{
|
||||
std::size_t num_values = ser.get<std::size_t>();
|
||||
for (std::size_t index = 0; index < num_values; index++) {
|
||||
std::string key = ser.get<std::string>();
|
||||
double value = ser.get<double>();
|
||||
this->update(key, value);
|
||||
}
|
||||
}
|
||||
this->values = ser.get<std::string, double>();
|
||||
|
||||
{
|
||||
std::size_t num_well_var = ser.get<std::size_t>();
|
||||
|
@ -24,6 +24,29 @@
|
||||
|
||||
namespace Opm {
|
||||
|
||||
UDQScalar UDQScalar::deserialize(Serializer& ser) {
|
||||
std::string wgname = ser.get<std::string>();
|
||||
UDQScalar scalar(wgname);
|
||||
|
||||
bool has_value = ser.get<bool>();
|
||||
if (has_value) {
|
||||
double value = ser.get<double>();
|
||||
scalar.assign(value);
|
||||
}
|
||||
|
||||
return scalar;
|
||||
}
|
||||
|
||||
void UDQScalar::serialize(Serializer& ser) const {
|
||||
ser.put<std::string>(this->m_wgname);
|
||||
if (this->m_value.has_value()) {
|
||||
ser.put<bool>(true);
|
||||
ser.put<double>(*this->m_value);
|
||||
} else
|
||||
ser.put<bool>(false);
|
||||
}
|
||||
|
||||
|
||||
UDQScalar::UDQScalar(double value)
|
||||
{
|
||||
this->assign(value);
|
||||
@ -108,6 +131,11 @@ UDQScalar::operator bool() const {
|
||||
return this->defined();
|
||||
}
|
||||
|
||||
bool UDQScalar::operator==(const UDQScalar& other) const {
|
||||
return this->m_value == other.m_value &&
|
||||
this->m_wgname == other.m_wgname;
|
||||
}
|
||||
|
||||
|
||||
const std::string& UDQSet::name() const {
|
||||
return this->m_name;
|
||||
@ -511,4 +539,35 @@ UDQSet operator/(double lhs, const UDQSet&rhs) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool UDQSet::operator==(const UDQSet& other) const {
|
||||
return this->m_name == other.m_name &&
|
||||
this->m_var_type == other.m_var_type &&
|
||||
this->values == other.values;
|
||||
}
|
||||
|
||||
UDQSet UDQSet::deserialize(Serializer& ser)
|
||||
{
|
||||
auto name = ser.get<std::string>();
|
||||
auto var_type = ser.get<UDQVarType>();
|
||||
auto size = ser.get<std::size_t>();
|
||||
|
||||
UDQSet udq_set(name, var_type, size);
|
||||
for (std::size_t index = 0; index < size; index++) {
|
||||
auto value = UDQScalar::deserialize(ser);
|
||||
udq_set.values[index] = std::move(value);
|
||||
}
|
||||
return udq_set;
|
||||
}
|
||||
|
||||
|
||||
void UDQSet::serialize(Serializer& ser) const {
|
||||
ser.put<std::string>(this->m_name);
|
||||
ser.put<UDQVarType>(this->m_var_type);
|
||||
ser.put<std::size_t>(this->values.size());
|
||||
|
||||
for (const auto& value : this->values)
|
||||
value.serialize(ser);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <opm/common/utility/Serializer.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.hpp>
|
||||
|
||||
namespace Opm {
|
||||
@ -119,6 +120,38 @@ double UDQState::get_group_var(const std::string& group, const std::string& key)
|
||||
return this->get_wg_var(group, key, UDQVarType::GROUP_VAR);
|
||||
}
|
||||
|
||||
bool UDQState::operator==(const UDQState& other) const {
|
||||
return this->undefined_value == other.undefined_value &&
|
||||
this->values == other.values;
|
||||
}
|
||||
|
||||
std::vector<char> UDQState::serialize() const {
|
||||
Serializer ser;
|
||||
ser.put(this->undefined_value);
|
||||
ser.put(this->values.size());
|
||||
for (const auto& set_pair : this->values) {
|
||||
ser.put( set_pair.first );
|
||||
set_pair.second.serialize( ser );
|
||||
}
|
||||
return std::move(ser.buffer);
|
||||
}
|
||||
|
||||
|
||||
void UDQState::deserialize(const std::vector<char>& buffer) {
|
||||
Serializer ser(buffer);
|
||||
this->undefined_value = ser.get<double>();
|
||||
this->values.clear();
|
||||
|
||||
{
|
||||
std::size_t size = ser.get<std::size_t>();
|
||||
for (std::size_t index = 0; index < size; index++) {
|
||||
auto key = ser.get<std::string>();
|
||||
auto udq_set = UDQSet::deserialize(ser);
|
||||
|
||||
this->values.insert( std::make_pair(key, udq_set) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -94,8 +94,15 @@ BOOST_AUTO_TEST_CASE(UDQSTATE) {
|
||||
|
||||
BOOST_CHECK_EQUAL(st.get_well_var("P1", "WUPR"), 75);
|
||||
BOOST_CHECK_EQUAL(st.get_well_var("P2", "WUPR"), undefined_value);
|
||||
|
||||
|
||||
const auto buffer = st.serialize();
|
||||
UDQState st2(1067);
|
||||
st2.deserialize( buffer );
|
||||
BOOST_CHECK(st == st2);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TYPE_COERCION) {
|
||||
BOOST_CHECK( UDQVarType::SCALAR == UDQ::coerce(UDQVarType::SCALAR, UDQVarType::SCALAR) );
|
||||
|
||||
@ -247,6 +254,9 @@ BOOST_AUTO_TEST_CASE(UDQFieldSetTest) {
|
||||
BOOST_AUTO_TEST_CASE(UDQWellSetNANTest) {
|
||||
std::vector<std::string> wells = {"P1", "P2", "I1", "I2"};
|
||||
UDQSet ws = UDQSet::wells("NAME", wells);
|
||||
UDQSet ws2 = UDQSet::wells("NAME", wells);
|
||||
|
||||
BOOST_CHECK(ws == ws2);
|
||||
|
||||
for (std::size_t i = 0; i < 4; i++)
|
||||
ws.assign(i, i*1.0);
|
||||
|
50
tests/test_Serializer.cpp
Normal file
50
tests/test_Serializer.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2020 Statoil ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#define BOOST_TEST_MODULE "Serializer"
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <opm/common/utility/Serializer.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SERIALIZER) {
|
||||
Opm::Serializer ser;
|
||||
|
||||
int int_value = 100;
|
||||
double double_value = 3.14;
|
||||
std::string string_value = "String";
|
||||
std::unordered_map<std::string, int> m = {{"A", 1}, {"B", 2}, {"C", 3}};
|
||||
|
||||
ser.put(int_value);
|
||||
ser.put(double_value);
|
||||
ser.put(string_value);
|
||||
ser.put(m);
|
||||
|
||||
Opm::Serializer ser2(ser.buffer);
|
||||
BOOST_CHECK_EQUAL(ser2.get<int>(), int_value);
|
||||
BOOST_CHECK_EQUAL(ser2.get<double>(), double_value);
|
||||
BOOST_CHECK_EQUAL(ser2.get<std::string>(), string_value);
|
||||
|
||||
|
||||
std::unordered_map<std::string, int> m2 = ser2.get<std::string,int>();
|
||||
BOOST_CHECK(m2 == m);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user