diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 8927a2326..38547a8d4 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -232,7 +232,11 @@ if(ENABLE_ECL_OUTPUT) src/opm/io/eclipse/ESmry.cpp src/opm/io/eclipse/OutputStream.cpp src/opm/io/eclipse/rst/connection.cpp + src/opm/io/eclipse/rst/group.cpp src/opm/io/eclipse/rst/header.cpp + src/opm/io/eclipse/rst/segment.cpp + src/opm/io/eclipse/rst/state.cpp + src/opm/io/eclipse/rst/well.cpp src/opm/output/eclipse/AggregateActionxData.cpp src/opm/output/eclipse/AggregateConnectionData.cpp src/opm/output/eclipse/AggregateGroupData.cpp @@ -366,6 +370,7 @@ if(ENABLE_ECL_OUTPUT) tests/test_PaddedOutputString.cpp tests/test_Restart.cpp tests/test_RFT.cpp + tests/test_rst.cpp tests/test_Solution.cpp tests/test_Summary.cpp tests/test_Tables.cpp @@ -427,6 +432,7 @@ if(ENABLE_ECL_INPUT) examples/opmi.cpp examples/opmpack.cpp examples/opmhash.cpp + tests/rst_load.cpp ) endif() @@ -691,7 +697,11 @@ if(ENABLE_ECL_OUTPUT) opm/io/eclipse/PaddedOutputString.hpp opm/io/eclipse/OutputStream.hpp opm/io/eclipse/rst/connection.hpp + opm/io/eclipse/rst/group.hpp opm/io/eclipse/rst/header.hpp + opm/io/eclipse/rst/segment.hpp + opm/io/eclipse/rst/state.hpp + opm/io/eclipse/rst/well.hpp opm/output/data/Aquifer.hpp opm/output/data/Cells.hpp opm/output/data/Solution.hpp diff --git a/ExtraTests.cmake b/ExtraTests.cmake index 79c33e647..bab224bfc 100644 --- a/ExtraTests.cmake +++ b/ExtraTests.cmake @@ -60,6 +60,7 @@ foreach (test BoxTest endforeach () # opm-tests dependent tests +opm_add_test("RST_LOAD" NO_COMPILE EXE_NAME rst_load TEST_ARGS "${PROJECT_SOURCE_DIR}/tests/SPE1_TESTCASE.UNRST") if(HAVE_OPM_TESTS) opm_add_test(parse_write ONLY_COMPILE SOURCES tests/parser/integration/parse_write.cpp @@ -103,6 +104,8 @@ if(HAVE_OPM_TESTS) opm_add_test("SPE9_CP_GROUP2" NO_COMPILE EXE_NAME parse_write TEST_ARGS "${OPM_TESTS_ROOT}/spe9group/SPE9_CP_GROUP.DATA") set_property(TEST NORNE_ATW2013 PROPERTY ENVIRONMENT "OPM_ERRORS_IGNORE=PARSE_RANDOM_SLASH") + + opm_add_test("RST_LOAD_MSW" NO_COMPILE EXE_NAME rst_load TEST_ARGS "${OPM_TESTS_ROOT}/msw_3d_hfa/opm-simulation-reference/flow/3D_MSW.UNRST") endif() # JSON tests diff --git a/opm/io/eclipse/rst/connection.hpp b/opm/io/eclipse/rst/connection.hpp index 247863489..2cd92ac97 100644 --- a/opm/io/eclipse/rst/connection.hpp +++ b/opm/io/eclipse/rst/connection.hpp @@ -25,8 +25,8 @@ namespace RestartIO { class Header; -struct Connection { - Connection(const int* icon, const float* scon, const double *xcon); +struct RstConnection { + RstConnection(const int* icon, const float* scon, const double *xcon); int insert_index; std::array ijk; diff --git a/opm/io/eclipse/rst/group.hpp b/opm/io/eclipse/rst/group.hpp new file mode 100644 index 000000000..22d4f74f3 --- /dev/null +++ b/opm/io/eclipse/rst/group.hpp @@ -0,0 +1,81 @@ +/* + 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 . +*/ + +#ifndef RST_GROUP +#define RST_GROUP + +#include +#include +#include + +namespace Opm { +namespace RestartIO { + +class RstHeader; + +struct RstGroup { + RstGroup(const std::string* zwel, + const int * igrp, + const float * sgrp, + const double * xgrp); + + std::string name; + float oil_rate_limit; + float water_rate_limit; + float gas_rate_limit; + float liquid_rate_limit; + float water_surface_limit; + float water_reservoir_limit; + float water_reinject_limit; + float water_voidage_limit; + float gas_surface_limit; + float gas_reservoir_limit; + float gas_reinject_limit; + float gas_voidage_limit; + + double oil_production_rate; + double water_production_rate; + double gas_production_rate; + double liquid_production_rate; + double water_injection_rate; + double gas_injection_rate; + double wct; + double gor; + double oil_production_total; + double water_production_total; + double gas_production_total; + double voidage_production_total; + double water_injection_total; + double gas_injection_total; + double oil_production_potential; + double water_production_potential; + double history_total_oil_production; + double history_total_water_production; + double history_total_water_injection; + double history_total_gas_production; + double history_total_gas_injection; +}; + + +} +} + + + + +#endif diff --git a/opm/io/eclipse/rst/header.hpp b/opm/io/eclipse/rst/header.hpp index ea857dd78..48e47df10 100644 --- a/opm/io/eclipse/rst/header.hpp +++ b/opm/io/eclipse/rst/header.hpp @@ -23,8 +23,8 @@ namespace Opm { namespace RestartIO { -struct Header { - Header(const std::vector& intehead, const std::vector& logihead, const std::vector& doubhead); +struct RstHeader { + RstHeader(const std::vector& intehead, const std::vector& logihead, const std::vector& doubhead); int nx; int ny; diff --git a/opm/io/eclipse/rst/segment.hpp b/opm/io/eclipse/rst/segment.hpp new file mode 100644 index 000000000..9e03d9454 --- /dev/null +++ b/opm/io/eclipse/rst/segment.hpp @@ -0,0 +1,73 @@ +/* + 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 . +*/ + +#ifndef RST_SEGMENT +#define RST_SEGMENT + +#include + +namespace Opm { +namespace RestartIO { + +struct RstSegment { + RstSegment(const int* iseg, const double * rseg); + + int segment; + int outlet_segment; + int branch; + int segment_type; + int icd_scaling_mode; + int icd_open_flag; + + double dist_outlet; + double outlet_dz; + double diameter; + double roughness; + double area; + double volume; + double dist_bhp_ref; + double bhp_ref_dz; + double total_flow; + double water_flow_fraction; + double gas_flow_fraction; + double pressure; + double valve_length; + double valve_area; + double valve_flow_coeff; + double valve_max_area; + double base_strength; + double fluid_density; + double fluid_viscosity; + double critical_water_fraction; + double transition_region_width; + double max_emulsion_ratio; + double max_valid_flow_rate; + double icd_length; + double valve_area_fraction; + + std::vector inflow_segments; +}; + + +} +} + + + + +#endif diff --git a/opm/io/eclipse/rst/state.hpp b/opm/io/eclipse/rst/state.hpp new file mode 100644 index 000000000..89926e304 --- /dev/null +++ b/opm/io/eclipse/rst/state.hpp @@ -0,0 +1,83 @@ +/* + 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 . +*/ + +#ifndef RST_STATE +#define RST_STATE + +#include +#include + +#include +#include +#include + +namespace Opm { +namespace RestartIO { +struct RstState { + RstState(const std::vector& intehead, + const std::vector& logihead, + const std::vector& doubhead, + const std::vector& zgrp, + const std::vector& igrp, + const std::vector& sgrp, + const std::vector& xgrp, + const std::vector& zwel, + const std::vector& iwel, + const std::vector& swel, + const std::vector& xwel, + const std::vector& icon, + const std::vector& scon, + const std::vector& xcon); + + RstState(const std::vector& intehead, + const std::vector& logihead, + const std::vector& doubhead, + const std::vector& zgrp, + const std::vector& igrp, + const std::vector& sgrp, + const std::vector& xgrp, + const std::vector& zwel, + const std::vector& iwel, + const std::vector& swel, + const std::vector& xwel, + const std::vector& icon, + const std::vector& scon, + const std::vector& xcon, + const std::vector& iseg, + const std::vector& rseg); + + + static RstState load(EclIO::ERst& rst_file, int report_step); + + std::vector wells; + std::vector groups; + +private: + void add_groups(const RstHeader& header, + const std::vector& zgrp, + const std::vector& igrp, + const std::vector& sgrp, + const std::vector& xgrp); +}; +} +} + + + + +#endif diff --git a/opm/io/eclipse/rst/well.hpp b/opm/io/eclipse/rst/well.hpp new file mode 100644 index 000000000..21ae67f74 --- /dev/null +++ b/opm/io/eclipse/rst/well.hpp @@ -0,0 +1,115 @@ +/* + 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 . +*/ + +#ifndef RST_WELL +#define RST_WELL + +#include +#include +#include +#include + + +#include +#include + +namespace Opm { +namespace RestartIO { + +class RstHeader; + +struct RstWell { + RstWell(const RstHeader& header, + const std::string* zwel, + const int * iwel, + const float * swel, + const double * xwel, + const int * icon, + const float * scon, + const double * xcon); + + RstWell(const RstHeader& header, + const std::string* zwel, + const int * iwel, + const float * swel, + const double * xwel, + const int * icon, + const float * scon, + const double * xcon, + const std::vector& iseg, + const std::vector& rseg); + + std::string name; + std::array ij; + std::pair k1k2; + int wtype; + int active_control; + int vfp_table; + int pred_requested_control; + int xflow; + int hist_requested_control; + int msw_index; + int completion_ordering; + + float orat_target; + float wrat_target; + float grat_target; + float lrat_target; + float resv_target; + float thp_target; + float bhp_target_float; + float hist_lrat_target; + float hist_grat_target; + float hist_bhp_target; + + double oil_rate; + double water_rate; + double gas_rate; + double liquid_rate; + double void_rate; + double flow_bhp; + double wct; + double gor; + double oil_total; + double water_total; + double gas_total; + double void_total; + double water_inj_total; + double gas_inj_total; + double gas_fvf; + double bhp_target_double; + double hist_oil_total; + double hist_wat_total; + double hist_gas_total; + double hist_water_inj_total; + double hist_gas_inj_total; + double water_void_rate; + double gas_void_rate; + + std::vector connections; + std::vector segments; +}; + + +} +} + + + + +#endif diff --git a/opm/output/eclipse/VectorItems/group.hpp b/opm/output/eclipse/VectorItems/group.hpp index 2f9027b54..7f08285c6 100644 --- a/opm/output/eclipse/VectorItems/group.hpp +++ b/opm/output/eclipse/VectorItems/group.hpp @@ -34,7 +34,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems }; enum inj_index : std::vector::size_type { - waterSurfRateLimit = 15, // Group's water surface volume injection rate target/limit + waterSurfRateLimit = 15, //i Group's water surface volume injection rate target/limit waterResRateLimit = 16, // Group's water reservoir volume injection rate target/limit waterReinjectionLimit = 17, // Group's water reinjection fraction target/limit waterVoidageLimit = 18, // Group's water voidage injection fraction target/limit diff --git a/src/opm/io/eclipse/rst/connection.cpp b/src/opm/io/eclipse/rst/connection.cpp index f876d7f36..7e3a00bf9 100644 --- a/src/opm/io/eclipse/rst/connection.cpp +++ b/src/opm/io/eclipse/rst/connection.cpp @@ -26,7 +26,7 @@ namespace VI = ::Opm::RestartIO::Helpers::VectorItems; namespace Opm { namespace RestartIO { -Connection::Connection(const int* icon, const float* scon, const double* xcon) : +RstConnection::RstConnection(const int* icon, const float* scon, const double* xcon) : insert_index(icon[VI::IConn::SeqIndex]), ijk({icon[VI::IConn::CellI] - 1, icon[VI::IConn::CellJ] - 1, icon[VI::IConn::CellK] - 1}), status(icon[VI::IConn::ConnStat]), diff --git a/src/opm/io/eclipse/rst/group.cpp b/src/opm/io/eclipse/rst/group.cpp new file mode 100644 index 000000000..b6464a66f --- /dev/null +++ b/src/opm/io/eclipse/rst/group.cpp @@ -0,0 +1,75 @@ +/* + 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 . +*/ + +#include + +#include +#include + +#include + + +namespace VI = ::Opm::RestartIO::Helpers::VectorItems; + +namespace Opm { +namespace RestartIO { + +RstGroup::RstGroup(const std::string* zwel, + const int *, + const float * sgrp, + const double * xgrp) : + name(trim_copy(zwel[0])), + oil_rate_limit(sgrp[VI::SGroup::OilRateLimit]), + water_rate_limit(sgrp[VI::SGroup::WatRateLimit]), + gas_rate_limit(sgrp[VI::SGroup::GasRateLimit]), + liquid_rate_limit(sgrp[VI::SGroup::LiqRateLimit]), + water_surface_limit(sgrp[VI::SGroup::waterSurfRateLimit]), + water_reservoir_limit(sgrp[VI::SGroup::waterResRateLimit]), + water_reinject_limit(sgrp[VI::SGroup::waterReinjectionLimit]), + water_voidage_limit(sgrp[VI::SGroup::waterVoidageLimit]), + gas_surface_limit(sgrp[VI::SGroup::gasSurfRateLimit]), + gas_reservoir_limit(sgrp[VI::SGroup::gasResRateLimit]), + gas_reinject_limit(sgrp[VI::SGroup::gasReinjectionLimit]), + gas_voidage_limit(sgrp[VI::SGroup::gasVoidageLimit]), + oil_production_rate(xgrp[VI::XGroup::OilPrRate]), + water_production_rate(xgrp[VI::XGroup::WatPrRate]), + gas_production_rate(xgrp[VI::XGroup::GasPrRate]), + liquid_production_rate(xgrp[VI::XGroup::LiqPrRate]), + water_injection_rate(xgrp[VI::XGroup::WatInjRate]), + gas_injection_rate(xgrp[VI::XGroup::GasInjRate]), + wct(xgrp[VI::XGroup::WatCut]), + gor(xgrp[VI::XGroup::GORatio]), + oil_production_total(xgrp[VI::XGroup::OilPrTotal]), + water_production_total(xgrp[VI::XGroup::WatPrTotal]), + gas_production_total(xgrp[VI::XGroup::GasPrTotal]), + voidage_production_total(xgrp[VI::XGroup::VoidPrTotal]), + water_injection_total(xgrp[VI::XGroup::WatInjTotal]), + gas_injection_total(xgrp[VI::XGroup::GasInjTotal]), + oil_production_potential(xgrp[VI::XGroup::OilPrPot]), + water_production_potential(xgrp[VI::XGroup::WatPrPot]), + history_total_oil_production(xgrp[VI::XGroup::HistOilPrTotal]), + history_total_water_production(xgrp[VI::XGroup::HistWatPrTotal]), + history_total_water_injection(xgrp[VI::XGroup::HistWatInjTotal]), + history_total_gas_production(xgrp[VI::XGroup::HistGasPrTotal]), + history_total_gas_injection(xgrp[VI::XGroup::HistGasInjTotal]) +{ +} + + +} +} diff --git a/src/opm/io/eclipse/rst/header.cpp b/src/opm/io/eclipse/rst/header.cpp index 78b6a5ce5..f31bcf1e9 100644 --- a/src/opm/io/eclipse/rst/header.cpp +++ b/src/opm/io/eclipse/rst/header.cpp @@ -26,7 +26,7 @@ namespace VI = ::Opm::RestartIO::Helpers::VectorItems; namespace Opm { namespace RestartIO { -Header::Header(const std::vector& intehead, const std::vector& logihead, const std::vector& doubhead) : +RstHeader::RstHeader(const std::vector& intehead, const std::vector& logihead, const std::vector& doubhead) : nx(intehead[VI::intehead::NX]), ny(intehead[VI::intehead::NY]), nz(intehead[VI::intehead::NZ]), diff --git a/src/opm/io/eclipse/rst/segment.cpp b/src/opm/io/eclipse/rst/segment.cpp new file mode 100644 index 000000000..0e348226e --- /dev/null +++ b/src/opm/io/eclipse/rst/segment.cpp @@ -0,0 +1,66 @@ +/* + 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 . +*/ +#include + +#include +#include + +namespace VI = ::Opm::RestartIO::Helpers::VectorItems; + +namespace Opm { +namespace RestartIO { + +RstSegment::RstSegment(const int * iseg, const double * rseg) : + segment(iseg[VI::ISeg::SegNo]), + outlet_segment(iseg[VI::ISeg::OutSeg]), + branch(iseg[VI::ISeg::BranchNo]), + segment_type(iseg[VI::ISeg::SegmentType]), + icd_scaling_mode(iseg[VI::ISeg::ICDScalingMode]), + icd_open_flag(iseg[VI::ISeg::ICDOpenShutFlag]), + dist_outlet(rseg[VI::RSeg::DistOutlet]), + outlet_dz(rseg[VI::RSeg::OutletDepthDiff]), + diameter(rseg[VI::RSeg::SegDiam]), + roughness(rseg[VI::RSeg::SegRough]), + area(rseg[VI::RSeg::SegArea]), + volume(rseg[VI::RSeg::SegVolume]), + dist_bhp_ref(rseg[VI::RSeg::DistBHPRef]), + bhp_ref_dz(rseg[VI::RSeg::DepthBHPRef]), + total_flow(rseg[VI::RSeg::TotFlowRate]), + water_flow_fraction(rseg[VI::RSeg::WatFlowFract]), + gas_flow_fraction(rseg[VI::RSeg::GasFlowFract]), + pressure(rseg[VI::RSeg::Pressure]), + valve_length(rseg[VI::RSeg::ValveLength]), + valve_area(rseg[VI::RSeg::ValveArea]), + valve_flow_coeff(rseg[VI::RSeg::ValveFlowCoeff]), + valve_max_area(rseg[VI::RSeg::ValveMaxArea]), + base_strength(rseg[VI::RSeg::DeviceBaseStrength]), + fluid_density(rseg[VI::RSeg::CalibrFluidDensity]), + fluid_viscosity(rseg[VI::RSeg::CalibrFluidViscosity]), + critical_water_fraction(rseg[VI::RSeg::CriticalWaterFraction]), + transition_region_width(rseg[VI::RSeg::TransitionRegWidth]), + max_emulsion_ratio(rseg[VI::RSeg::MaxEmulsionRatio]), + max_valid_flow_rate(rseg[VI::RSeg::MaxValidFlowRate]), + icd_length(rseg[VI::RSeg::ICDLength]), + valve_area_fraction(rseg[VI::RSeg::ValveAreaFraction]) +{ + if (iseg[VI::ISeg::InSegCurBranch] != 0) + this->inflow_segments.push_back(iseg[VI::ISeg::InSegCurBranch]); +} + +} +} diff --git a/src/opm/io/eclipse/rst/state.cpp b/src/opm/io/eclipse/rst/state.cpp new file mode 100644 index 000000000..173d55488 --- /dev/null +++ b/src/opm/io/eclipse/rst/state.cpp @@ -0,0 +1,172 @@ +/* + 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 . +*/ + +#include +#include +#include +#include + +#include +#include + +namespace VI = ::Opm::RestartIO::Helpers::VectorItems; + +namespace Opm { +namespace RestartIO { + +RstState::RstState(const std::vector& intehead, + const std::vector& logihead, + const std::vector& doubhead, + const std::vector& zgrp, + const std::vector& igrp, + const std::vector& sgrp, + const std::vector& xgrp, + const std::vector& zwel, + const std::vector& iwel, + const std::vector& swel, + const std::vector& xwel, + const std::vector& icon, + const std::vector& scon, + const std::vector& xcon) +{ + RstHeader header(intehead, logihead, doubhead); + this->add_groups(header, zgrp, igrp, sgrp, xgrp); + + for (int iw = 0; iw < header.num_wells; iw++) { + std::size_t zwel_offset = iw * header.nzwelz; + std::size_t iwel_offset = iw * header.niwelz; + std::size_t swel_offset = iw * header.nswelz; + std::size_t xwel_offset = iw * header.nxwelz; + std::size_t icon_offset = iw * header.niconz * header.ncwmax; + std::size_t scon_offset = iw * header.nsconz * header.ncwmax; + std::size_t xcon_offset = iw * header.nxconz * header.ncwmax; + + this->wells.emplace_back(header, + zwel.data() + zwel_offset, + iwel.data() + iwel_offset, + swel.data() + swel_offset, + xwel.data() + xwel_offset, + icon.data() + icon_offset, + scon.data() + scon_offset, + xcon.data() + xcon_offset); + + if (this->wells.back().msw_index) + throw std::logic_error("MSW data not accounted for in this constructor"); + } +} + +RstState::RstState(const std::vector& intehead, + const std::vector& logihead, + const std::vector& doubhead, + const std::vector& zgrp, + const std::vector& igrp, + const std::vector& sgrp, + const std::vector& xgrp, + const std::vector& zwel, + const std::vector& iwel, + const std::vector& swel, + const std::vector& xwel, + const std::vector& icon, + const std::vector& scon, + const std::vector& xcon, + const std::vector& iseg, + const std::vector& rseg) +{ + RstHeader header(intehead, logihead, doubhead); + this->add_groups(header, zgrp, igrp, sgrp, xgrp); + + for (int iw = 0; iw < header.num_wells; iw++) { + std::size_t zwel_offset = iw * header.nzwelz; + std::size_t iwel_offset = iw * header.niwelz; + std::size_t swel_offset = iw * header.nswelz; + std::size_t xwel_offset = iw * header.nxwelz; + std::size_t icon_offset = iw * header.niconz * header.ncwmax; + std::size_t scon_offset = iw * header.nsconz * header.ncwmax; + std::size_t xcon_offset = iw * header.nxconz * header.ncwmax; + + this->wells.emplace_back(header, + zwel.data() + zwel_offset, + iwel.data() + iwel_offset, + swel.data() + swel_offset, + xwel.data() + xwel_offset, + icon.data() + icon_offset, + scon.data() + scon_offset, + xcon.data() + xcon_offset, + iseg, + rseg); + } +} + +void RstState::add_groups(const RstHeader& header, + const std::vector& zgrp, + const std::vector& igrp, + const std::vector& sgrp, + const std::vector& xgrp) +{ + for (int ig=0; ig < header.ngroup; ig++) { + std::size_t zgrp_offset = ig * header.nzgrpz; + std::size_t igrp_offset = ig * header.nigrpz; + std::size_t sgrp_offset = ig * header.nsgrpz; + std::size_t xgrp_offset = ig * header.nxgrpz; + + this->groups.emplace_back(zgrp.data() + zgrp_offset, + igrp.data() + igrp_offset, + sgrp.data() + sgrp_offset, + xgrp.data() + xgrp_offset); + } +} + + +RstState RstState::load(EclIO::ERst& rst_file, int report_step) { + rst_file.loadReportStepNumber(report_step); + const auto& intehead = rst_file.getRst("INTEHEAD", report_step, 0); + const auto& logihead = rst_file.getRst("LOGIHEAD", report_step, 0); + const auto& doubhead = rst_file.getRst("DOUBHEAD", report_step, 0); + + const auto& zgrp = rst_file.getRst("ZGRP", report_step, 0); + const auto& igrp = rst_file.getRst("IGRP", report_step, 0); + const auto& sgrp = rst_file.getRst("SGRP", report_step, 0); + const auto& xgrp = rst_file.getRst("XGRP", report_step, 0); + + const auto& zwel = rst_file.getRst("ZWEL", report_step, 0); + const auto& iwel = rst_file.getRst("IWEL", report_step, 0); + const auto& swel = rst_file.getRst("SWEL", report_step, 0); + const auto& xwel = rst_file.getRst("XWEL", report_step, 0); + + const auto& icon = rst_file.getRst("ICON", report_step, 0); + const auto& scon = rst_file.getRst("SCON", report_step, 0); + const auto& xcon = rst_file.getRst("XCON", report_step, 0); + + if (rst_file.hasKey("ISEG")) { + const auto& iseg = rst_file.getRst("ISEG", report_step, 0); + const auto& rseg = rst_file.getRst("RSEG", report_step, 0); + + return RstState(intehead, logihead, doubhead, + zgrp, igrp, sgrp, xgrp, + zwel, iwel, swel, xwel, + icon, scon, xcon, + iseg, rseg); + } else + return RstState(intehead, logihead, doubhead, + zgrp, igrp, sgrp, xgrp, + zwel, iwel, swel, xwel, + icon, scon, xcon); +} + +} +} diff --git a/src/opm/io/eclipse/rst/well.cpp b/src/opm/io/eclipse/rst/well.cpp new file mode 100644 index 000000000..a04237df8 --- /dev/null +++ b/src/opm/io/eclipse/rst/well.cpp @@ -0,0 +1,133 @@ +/* + 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 . +*/ + +#include + +#include +#include +#include + +#include +#include +#include + + +namespace VI = ::Opm::RestartIO::Helpers::VectorItems; + +namespace Opm { +namespace RestartIO { + +RstWell::RstWell(const RstHeader& header, + const std::string* zwel, + const int * iwel, + const float * swel, + const double * xwel, + const int * icon, + const float * scon, + const double * xcon) : + name(trim_copy(zwel[0])), + ij({iwel[VI::IWell::IHead] - 1, iwel[VI::IWell::JHead] - 1}), + k1k2(std::make_pair(iwel[VI::IWell::FirstK] - 1, iwel[VI::IWell::LastK] - 1)), + wtype(iwel[VI::IWell::WType]), + active_control(iwel[VI::IWell::ActWCtrl]), + vfp_table(iwel[VI::IWell::VFPTab]), + pred_requested_control(iwel[VI::IWell::PredReqWCtrl]), + xflow(iwel[VI::IWell::XFlow]), + hist_requested_control(iwel[VI::IWell::HistReqWCtrl]), + msw_index(iwel[VI::IWell::MsWID]), + completion_ordering(iwel[VI::IWell::CompOrd]), + orat_target(swel[VI::SWell::OilRateTarget]), + wrat_target(swel[VI::SWell::WatRateTarget]), + grat_target(swel[VI::SWell::GasRateTarget]), + lrat_target(swel[VI::SWell::LiqRateTarget]), + resv_target(swel[VI::SWell::ResVRateTarget]), + thp_target(swel[VI::SWell::THPTarget]), + bhp_target_float(swel[VI::SWell::BHPTarget]), + hist_lrat_target(swel[VI::SWell::HistLiqRateTarget]), + hist_grat_target(swel[VI::SWell::HistGasRateTarget]), + hist_bhp_target(swel[VI::SWell::HistBHPTarget]), + oil_rate(xwel[VI::XWell::OilPrRate]), + water_rate(xwel[VI::XWell::WatPrRate]), + gas_rate(xwel[VI::XWell::GasPrRate]), + liquid_rate(xwel[VI::XWell::LiqPrRate]), + void_rate(xwel[VI::XWell::VoidPrRate]), + flow_bhp(xwel[VI::XWell::FlowBHP]), + wct(xwel[VI::XWell::WatCut]), + gor(xwel[VI::XWell::GORatio]), + oil_total(xwel[VI::XWell::OilPrTotal]), + water_total(xwel[VI::XWell::WatPrTotal]), + gas_total(xwel[VI::XWell::GasPrTotal]), + void_total(xwel[VI::XWell::VoidPrTotal]), + water_inj_total(xwel[VI::XWell::WatInjTotal]), + gas_inj_total(xwel[VI::XWell::GasInjTotal]), + gas_fvf(xwel[VI::XWell::GasFVF]), + bhp_target_double(xwel[VI::XWell::BHPTarget]), + hist_oil_total(xwel[VI::XWell::HistOilPrTotal]), + hist_wat_total(xwel[VI::XWell::HistWatPrTotal]), + hist_gas_total(xwel[VI::XWell::HistGasPrTotal]), + hist_water_inj_total(xwel[VI::XWell::HistWatInjTotal]), + hist_gas_inj_total(xwel[VI::XWell::HistGasInjTotal]), + water_void_rate(xwel[VI::XWell::WatVoidPrRate]), + gas_void_rate(xwel[VI::XWell::GasVoidPrRate]) +{ + for (int ic = 0; ic < iwel[VI::IWell::NConn]; ic++) { + std::size_t icon_offset = ic * header.niconz; + std::size_t scon_offset = ic * header.nsconz; + std::size_t xcon_offset = ic * header.nxconz; + this->connections.emplace_back( icon + icon_offset, scon + scon_offset, xcon + xcon_offset); + } +} + + + +RstWell::RstWell(const RstHeader& header, + const std::string* zwel, + const int * iwel, + const float * swel, + const double * xwel, + const int * icon, + const float * scon, + const double * xcon, + const std::vector& iseg, + const std::vector& rseg) : + RstWell(header, zwel, iwel, swel, xwel, icon, scon, xcon) +{ + + if (this->msw_index) { + std::unordered_map segment_map; + for (int is=0; is < header.nsegmx; is++) { + std::size_t iseg_offset = header.nisegz * (is + (this->msw_index - 1) * header.nsegmx); + std::size_t rseg_offset = header.nrsegz * (is + (this->msw_index - 1) * header.nsegmx); + auto segment_number = iseg[iseg_offset + VI::ISeg::SegNo]; + if (segment_number != 0) { + segment_map.insert({segment_number, this->segments.size()}); + this->segments.emplace_back( iseg.data() + iseg_offset, rseg.data() + rseg_offset); + } + } + + for (auto& segment : this->segments) { + if (segment.outlet_segment != 0) { + auto& outlet_segment = this->segments[ segment_map[segment.outlet_segment] ]; + outlet_segment.inflow_segments.push_back(segment.segment); + } + } + } +} + +} +} diff --git a/tests/rst_load.cpp b/tests/rst_load.cpp new file mode 100644 index 000000000..211ed5179 --- /dev/null +++ b/tests/rst_load.cpp @@ -0,0 +1,34 @@ +/* + 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 . +*/ + +#include +#include + + + + +int main(int argc, char ** argv) { + for (int iarg = 1; iarg < argc; iarg++) { + Opm::EclIO::ERst rst_file(argv[iarg]); + for (int report_step : rst_file.listOfReportStepNumbers()) { + if (report_step > 0) + const auto& state = Opm::RestartIO::RstState::load(rst_file, report_step); + } + } +} diff --git a/tests/test_AggregateConnectionData.cpp b/tests/test_AggregateConnectionData.cpp index 992cc2f01..2e62a06f3 100644 --- a/tests/test_AggregateConnectionData.cpp +++ b/tests/test_AggregateConnectionData.cpp @@ -803,7 +803,7 @@ BOOST_AUTO_TEST_CASE(TestRestartIOConnection) { const auto ih = MockIH {static_cast(simCase.sched.getWells(rptStep).size())}; const Opm::data::WellRates wrc = wr(); - Opm::RestartIO::Header header(ih.value, lh, dh); + Opm::RestartIO::RstHeader header(ih.value, lh, dh); auto conn = Opm::RestartIO::Helpers::AggregateConnectionData{ih.value}; conn.captureDeclaredConnData(simCase.sched, simCase.grid, @@ -816,7 +816,7 @@ BOOST_AUTO_TEST_CASE(TestRestartIOConnection) { const auto scon = conn.getSConn(); const auto xcon = conn.getXConn(); - std::vector connections; + std::vector connections; for (int iw = 0; iw < header.num_wells; iw++) { for (int ic = 0; ic < header.ncwmax; ic++) { std::size_t icon_offset = header.niconz * (header.ncwmax * iw + ic); diff --git a/tests/test_AggregateMSWData.cpp b/tests/test_AggregateMSWData.cpp index e23e4be76..5bf34795b 100644 --- a/tests/test_AggregateMSWData.cpp +++ b/tests/test_AggregateMSWData.cpp @@ -29,6 +29,7 @@ #include +#include #include #include #include @@ -819,4 +820,32 @@ BOOST_AUTO_TEST_CASE (Declared_MSW_Data) } +BOOST_AUTO_TEST_CASE(MSW_RST) { + const auto simCase = SimulationCase{first_sim()}; + + // Report Step 1: 2115-01-01 --> 2015-01-03 + const auto rptStep = std::size_t{1}; + + const auto ih = MockIH { + static_cast(simCase.sched.getWells(rptStep).size()) + }; + + const auto smry = sim_state(); + const Opm::data::WellRates wrc = wr(); + auto amswd = Opm::RestartIO::Helpers::AggregateMSWData{ih.value}; + amswd.captureDeclaredMSWData(simCase.sched, + rptStep, + simCase.es.getUnits(), + ih.value, + simCase.grid, + smry, + wrc + ); + const auto& iseg = amswd.getISeg(); + const auto& rseg = amswd.getRSeg(); + auto segment = Opm::RestartIO::RstSegment(iseg.data(), rseg.data()); +} + + + BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_AggregateWellData.cpp b/tests/test_AggregateWellData.cpp index e8b500466..2ff5d8e0b 100644 --- a/tests/test_AggregateWellData.cpp +++ b/tests/test_AggregateWellData.cpp @@ -23,10 +23,15 @@ #include #include +#include #include #include #include +#include + +#include +#include #include @@ -342,17 +347,21 @@ TSTEP -- 8 return xw; } -} + + +} // namespace struct SimulationCase { explicit SimulationCase(const Opm::Deck& deck) : es { deck } + , grid { deck } , sched{ deck, es } {} // Order requirement: 'es' must be declared/initialised before 'sched'. Opm::EclipseState es; + Opm::EclipseGrid grid; Opm::Schedule sched; }; @@ -774,4 +783,76 @@ BOOST_AUTO_TEST_CASE (Dynamic_Well_Data_Step2) } } + +BOOST_AUTO_TEST_CASE(WELL_POD) { + const auto simCase = SimulationCase{first_sim()}; + const auto& units = simCase.es.getUnits(); + // Report Step 2: 2011-01-20 --> 2013-06-15 + const auto rptStep = std::size_t{2}; + const auto sim_step = rptStep - 1; + Opm::SummaryState sumState(std::chrono::system_clock::now()); + + const auto ih = Opm::RestartIO::Helpers::createInteHead(simCase.es, + simCase.grid, + simCase.sched, + 0, + sim_step, + sim_step); + + auto wellData = Opm::RestartIO::Helpers::AggregateWellData(ih); + wellData.captureDeclaredWellData(simCase.sched, units, sim_step, sumState, ih); + wellData.captureDynamicWellData(simCase.sched, sim_step, {} , sumState); + + auto connectionData = Opm::RestartIO::Helpers::AggregateConnectionData(ih); + connectionData.captureDeclaredConnData(simCase.sched, simCase.grid, units, {} , sim_step); + + const auto& iwel = wellData.getIWell(); + const auto& swel = wellData.getSWell(); + const auto& xwel = wellData.getXWell(); + const auto& zwel8 = wellData.getZWell(); + + const auto& icon = connectionData.getIConn(); + const auto& scon = connectionData.getSConn(); + const auto& xcon = connectionData.getXConn(); + + Opm::RestartIO::RstHeader header(ih, std::vector(100), std::vector(1000)); + std::vector wells; + std::vector zwel; + for (const auto& s8: zwel8) + zwel.push_back(s8.c_str()); + + for (auto iw = 0; iw < header.num_wells; iw++) { + std::size_t zwel_offset = header.nzwelz * iw; + std::size_t iwel_offset = header.niwelz * iw; + std::size_t swel_offset = header.nswelz * iw; + std::size_t xwel_offset = header.nxwelz * iw; + std::size_t icon_offset = header.niconz * header.ncwmax * iw; + std::size_t scon_offset = header.nsconz * header.ncwmax * iw; + std::size_t xcon_offset = header.nxconz * header.ncwmax * iw; + + wells.emplace_back(header, + zwel.data() + zwel_offset, + iwel.data() + iwel_offset, + swel.data() + swel_offset, + xwel.data() + xwel_offset, + icon.data() + icon_offset, + scon.data() + scon_offset, + xcon.data() + xcon_offset); + + } + // Well OP2 + const auto& well2 = wells[1]; + BOOST_CHECK_EQUAL(well2.k1k2.first, 1); + BOOST_CHECK_EQUAL(well2.k1k2.second, 1); + BOOST_CHECK_EQUAL(well2.ij[0], 8); + BOOST_CHECK_EQUAL(well2.ij[1], 8); + BOOST_CHECK_EQUAL(well2.name, "OP_2"); + + BOOST_CHECK_EQUAL(well2.connections.size(), 1); + const auto& conn1 = well2.connections[0]; + BOOST_CHECK_EQUAL(conn1.ijk[0], 8); + BOOST_CHECK_EQUAL(conn1.ijk[1], 8); + BOOST_CHECK_EQUAL(conn1.ijk[2], 1); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_InteHEAD.cpp b/tests/test_InteHEAD.cpp index e4bffe5a0..022c27640 100755 --- a/tests/test_InteHEAD.cpp +++ b/tests/test_InteHEAD.cpp @@ -571,7 +571,7 @@ BOOST_AUTO_TEST_CASE(TestHeader) { .regionDimensions({ntfip, nmfipr, 0,0,0}) .ngroups({ngroup}); - Opm::RestartIO::Header header(ih.data(), std::vector(100), std::vector(1000)); + Opm::RestartIO::RstHeader header(ih.data(), std::vector(100), std::vector(1000)); BOOST_CHECK_EQUAL(header.nx, nx); BOOST_CHECK_EQUAL(header.ny, ny); BOOST_CHECK_EQUAL(header.nactive, nactive); diff --git a/tests/test_rst.cpp b/tests/test_rst.cpp new file mode 100644 index 000000000..798d6c7d2 --- /dev/null +++ b/tests/test_rst.cpp @@ -0,0 +1,314 @@ +/* + 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 . +*/ + +#define BOOST_TEST_MODULE test_rst + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace { + Opm::Deck first_sim() + { + // Mostly copy of tests/FIRST_SIM.DATA + const auto input = std::string { + R"~( +RUNSPEC +OIL +GAS +WATER +DISGAS +VAPOIL +UNIFOUT +UNIFIN +DIMENS + 10 10 10 / + +GRID +DXV +10*0.25 / +DYV +10*0.25 / +DZV +10*0.25 / +TOPS +100*0.25 / + +PORO +1000*0.2 / + +SOLUTION +RESTART +FIRST_SIM 1/ + + +START -- 0 +1 NOV 1979 / + +SCHEDULE +SKIPREST +RPTRST +BASIC=1 +/ +DATES -- 1 + 10 OKT 2008 / +/ +WELSPECS + 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / + 'OP_2' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / +/ +COMPDAT + 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / + 'OP_2' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / + 'OP_1' 9 9 3 3 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / +/ +WCONPROD + 'OP_1' 'OPEN' 'ORAT' 20000 4* 1000 / +/ +WCONINJE + 'OP_2' 'GAS' 'OPEN' 'RATE' 100 200 400 / +/ + +DATES -- 2 + 20 JAN 2011 / +/ +WELSPECS + 'OP_3' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / +/ +COMPDAT + 'OP_3' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / +/ +WCONPROD + 'OP_3' 'OPEN' 'ORAT' 20000 4* 1000 / +/ +WCONINJE + 'OP_2' 'WATER' 'OPEN' 'RATE' 100 200 400 / +/ + +DATES -- 3 + 15 JUN 2013 / +/ +COMPDAT + 'OP_2' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / + 'OP_1' 9 9 7 7 'SHUT' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / +/ + +DATES -- 4 + 22 APR 2014 / +/ +WELSPECS + 'OP_4' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / +/ +COMPDAT + 'OP_4' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / + 'OP_3' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / +/ +WCONPROD + 'OP_4' 'OPEN' 'ORAT' 20000 4* 1000 / +/ + +DATES -- 5 + 30 AUG 2014 / +/ +WELSPECS + 'OP_5' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / +/ +COMPDAT + 'OP_5' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / +/ +WCONPROD + 'OP_5' 'OPEN' 'ORAT' 20000 4* 1000 / +/ + +DATES -- 6 + 15 SEP 2014 / +/ +WCONPROD + 'OP_3' 'SHUT' 'ORAT' 20000 4* 1000 / +/ + +DATES -- 7 + 9 OCT 2014 / +/ +WELSPECS + 'OP_6' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / +/ +COMPDAT + 'OP_6' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / +/ +WCONPROD + 'OP_6' 'OPEN' 'ORAT' 20000 4* 1000 / +/ +TSTEP -- 8 +10 / +)~" }; + + return Opm::Parser{}.parseString(input); + } + + + +} // namespace + +struct SimulationCase +{ + explicit SimulationCase(const Opm::Deck& deck) + : es { deck } + , grid { deck } + , sched{ deck, es } + {} + + // Order requirement: 'es' must be declared/initialised before 'sched'. + Opm::EclipseState es; + Opm::EclipseGrid grid; + Opm::Schedule sched; +}; + +// ===================================================================== +BOOST_AUTO_TEST_CASE(group_test) { + const auto simCase = SimulationCase{first_sim()}; + const auto& units = simCase.es.getUnits(); + // Report Step 2: 2011-01-20 --> 2013-06-15 + const auto rptStep = std::size_t{2}; + const auto sim_step = rptStep - 1; + Opm::SummaryState sumState(std::chrono::system_clock::now()); + + const auto ih = Opm::RestartIO::Helpers::createInteHead(simCase.es, + simCase.grid, + simCase.sched, + 0, + sim_step, + sim_step); + + const auto lh = Opm::RestartIO::Helpers::createLogiHead(simCase.es); + + const auto dh = Opm::RestartIO::Helpers::createDoubHead(simCase.es, + simCase.sched, + sim_step, + 0, 0); + + auto groupData = Opm::RestartIO::Helpers::AggregateGroupData(ih); + groupData.captureDeclaredGroupData(simCase.sched, units, sim_step, sumState, ih); + + const auto& igrp = groupData.getIGroup(); + const auto& sgrp = groupData.getSGroup(); + const auto& xgrp = groupData.getXGroup(); + const auto& zgrp8 = groupData.getZGroup(); + + std::vector zgrp; + for (const auto& s8: zgrp8) + zgrp.push_back(s8.c_str()); + + Opm::RestartIO::RstHeader header(ih,lh,dh); + for (int ig=0; ig < header.ngroup; ig++) { + std::size_t zgrp_offset = ig * header.nzgrpz; + std::size_t igrp_offset = ig * header.nigrpz; + std::size_t sgrp_offset = ig * header.nsgrpz; + std::size_t xgrp_offset = ig * header.nxgrpz; + + Opm::RestartIO::RstGroup group(zgrp.data() + zgrp_offset, + igrp.data() + igrp_offset, + sgrp.data() + sgrp_offset, + xgrp.data() + xgrp_offset); + } +} + +BOOST_AUTO_TEST_CASE(State_test) { + const auto simCase = SimulationCase{first_sim()}; + const auto& units = simCase.es.getUnits(); + // Report Step 2: 2011-01-20 --> 2013-06-15 + const auto rptStep = std::size_t{2}; + const auto sim_step = rptStep - 1; + Opm::SummaryState sumState(std::chrono::system_clock::now()); + + const auto ih = Opm::RestartIO::Helpers::createInteHead(simCase.es, + simCase.grid, + simCase.sched, + 0, + sim_step, + sim_step); + + const auto lh = Opm::RestartIO::Helpers::createLogiHead(simCase.es); + + const auto dh = Opm::RestartIO::Helpers::createDoubHead(simCase.es, + simCase.sched, + sim_step, + 0, 0); + + auto wellData = Opm::RestartIO::Helpers::AggregateWellData(ih); + wellData.captureDeclaredWellData(simCase.sched, units, sim_step, sumState, ih); + wellData.captureDynamicWellData(simCase.sched, sim_step, {} , sumState); + + auto connectionData = Opm::RestartIO::Helpers::AggregateConnectionData(ih); + connectionData.captureDeclaredConnData(simCase.sched, simCase.grid, units, {} , sim_step); + + auto groupData = Opm::RestartIO::Helpers::AggregateGroupData(ih); + groupData.captureDeclaredGroupData(simCase.sched, units, sim_step, sumState, ih); + + const auto& iwel = wellData.getIWell(); + const auto& swel = wellData.getSWell(); + const auto& xwel = wellData.getXWell(); + const auto& zwel8 = wellData.getZWell(); + + const auto& icon = connectionData.getIConn(); + const auto& scon = connectionData.getSConn(); + const auto& xcon = connectionData.getXConn(); + + const auto& zgrp8 = groupData.getZGroup(); + const auto& igrp = groupData.getIGroup(); + const auto& sgrp = groupData.getSGroup(); + const auto& xgrp = groupData.getXGroup(); + + std::vector zwel; + for (const auto& s8: zwel8) + zwel.push_back(s8.c_str()); + + std::vector zgrp; + for (const auto& s8: zgrp8) + zgrp.push_back(s8.c_str()); + + Opm::RestartIO::RstState state(ih, lh, dh, + zgrp, igrp, sgrp, xgrp, + zwel, iwel, swel, xwel, + icon, scon, xcon); +}