Add POD struct for state with wells and groups from restart file

This commit is contained in:
Joakim Hove 2020-01-15 11:41:28 +01:00
parent 51daf43cef
commit 69822e880f
21 changed files with 1280 additions and 11 deletions

View File

@ -232,7 +232,11 @@ if(ENABLE_ECL_OUTPUT)
src/opm/io/eclipse/ESmry.cpp src/opm/io/eclipse/ESmry.cpp
src/opm/io/eclipse/OutputStream.cpp src/opm/io/eclipse/OutputStream.cpp
src/opm/io/eclipse/rst/connection.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/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/AggregateActionxData.cpp
src/opm/output/eclipse/AggregateConnectionData.cpp src/opm/output/eclipse/AggregateConnectionData.cpp
src/opm/output/eclipse/AggregateGroupData.cpp src/opm/output/eclipse/AggregateGroupData.cpp
@ -366,6 +370,7 @@ if(ENABLE_ECL_OUTPUT)
tests/test_PaddedOutputString.cpp tests/test_PaddedOutputString.cpp
tests/test_Restart.cpp tests/test_Restart.cpp
tests/test_RFT.cpp tests/test_RFT.cpp
tests/test_rst.cpp
tests/test_Solution.cpp tests/test_Solution.cpp
tests/test_Summary.cpp tests/test_Summary.cpp
tests/test_Tables.cpp tests/test_Tables.cpp
@ -427,6 +432,7 @@ if(ENABLE_ECL_INPUT)
examples/opmi.cpp examples/opmi.cpp
examples/opmpack.cpp examples/opmpack.cpp
examples/opmhash.cpp examples/opmhash.cpp
tests/rst_load.cpp
) )
endif() endif()
@ -691,7 +697,11 @@ if(ENABLE_ECL_OUTPUT)
opm/io/eclipse/PaddedOutputString.hpp opm/io/eclipse/PaddedOutputString.hpp
opm/io/eclipse/OutputStream.hpp opm/io/eclipse/OutputStream.hpp
opm/io/eclipse/rst/connection.hpp opm/io/eclipse/rst/connection.hpp
opm/io/eclipse/rst/group.hpp
opm/io/eclipse/rst/header.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/Aquifer.hpp
opm/output/data/Cells.hpp opm/output/data/Cells.hpp
opm/output/data/Solution.hpp opm/output/data/Solution.hpp

View File

@ -60,6 +60,7 @@ foreach (test BoxTest
endforeach () endforeach ()
# opm-tests dependent tests # 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) if(HAVE_OPM_TESTS)
opm_add_test(parse_write ONLY_COMPILE opm_add_test(parse_write ONLY_COMPILE
SOURCES tests/parser/integration/parse_write.cpp 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") 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 set_property(TEST NORNE_ATW2013
PROPERTY ENVIRONMENT "OPM_ERRORS_IGNORE=PARSE_RANDOM_SLASH") 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() endif()
# JSON tests # JSON tests

View File

@ -25,8 +25,8 @@ namespace RestartIO {
class Header; class Header;
struct Connection { struct RstConnection {
Connection(const int* icon, const float* scon, const double *xcon); RstConnection(const int* icon, const float* scon, const double *xcon);
int insert_index; int insert_index;
std::array<int,3> ijk; std::array<int,3> ijk;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef RST_GROUP
#define RST_GROUP
#include <array>
#include <vector>
#include <string>
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

View File

@ -23,8 +23,8 @@
namespace Opm { namespace Opm {
namespace RestartIO { namespace RestartIO {
struct Header { struct RstHeader {
Header(const std::vector<int>& intehead, const std::vector<bool>& logihead, const std::vector<double>& doubhead); RstHeader(const std::vector<int>& intehead, const std::vector<bool>& logihead, const std::vector<double>& doubhead);
int nx; int nx;
int ny; int ny;

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef RST_SEGMENT
#define RST_SEGMENT
#include <vector>
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<int> inflow_segments;
};
}
}
#endif

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef RST_STATE
#define RST_STATE
#include <vector>
#include <string>
#include <opm/io/eclipse/ERst.hpp>
#include <opm/io/eclipse/rst/group.hpp>
#include <opm/io/eclipse/rst/well.hpp>
namespace Opm {
namespace RestartIO {
struct RstState {
RstState(const std::vector<int>& intehead,
const std::vector<bool>& logihead,
const std::vector<double>& doubhead,
const std::vector<std::string>& zgrp,
const std::vector<int>& igrp,
const std::vector<float>& sgrp,
const std::vector<double>& xgrp,
const std::vector<std::string>& zwel,
const std::vector<int>& iwel,
const std::vector<float>& swel,
const std::vector<double>& xwel,
const std::vector<int>& icon,
const std::vector<float>& scon,
const std::vector<double>& xcon);
RstState(const std::vector<int>& intehead,
const std::vector<bool>& logihead,
const std::vector<double>& doubhead,
const std::vector<std::string>& zgrp,
const std::vector<int>& igrp,
const std::vector<float>& sgrp,
const std::vector<double>& xgrp,
const std::vector<std::string>& zwel,
const std::vector<int>& iwel,
const std::vector<float>& swel,
const std::vector<double>& xwel,
const std::vector<int>& icon,
const std::vector<float>& scon,
const std::vector<double>& xcon,
const std::vector<int>& iseg,
const std::vector<double>& rseg);
static RstState load(EclIO::ERst& rst_file, int report_step);
std::vector<RstWell> wells;
std::vector<RstGroup> groups;
private:
void add_groups(const RstHeader& header,
const std::vector<std::string>& zgrp,
const std::vector<int>& igrp,
const std::vector<float>& sgrp,
const std::vector<double>& xgrp);
};
}
}
#endif

115
opm/io/eclipse/rst/well.hpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef RST_WELL
#define RST_WELL
#include <array>
#include <vector>
#include <string>
#include <unordered_map>
#include <opm/io/eclipse/rst/connection.hpp>
#include <opm/io/eclipse/rst/segment.hpp>
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<int>& iseg,
const std::vector<double>& rseg);
std::string name;
std::array<int, 2> ij;
std::pair<int,int> 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<RstConnection> connections;
std::vector<RstSegment> segments;
};
}
}
#endif

View File

@ -34,7 +34,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
}; };
enum inj_index : std::vector<float>::size_type { enum inj_index : std::vector<float>::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 waterResRateLimit = 16, // Group's water reservoir volume injection rate target/limit
waterReinjectionLimit = 17, // Group's water reinjection fraction target/limit waterReinjectionLimit = 17, // Group's water reinjection fraction target/limit
waterVoidageLimit = 18, // Group's water voidage injection fraction target/limit waterVoidageLimit = 18, // Group's water voidage injection fraction target/limit

View File

@ -26,7 +26,7 @@ namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
namespace Opm { namespace Opm {
namespace RestartIO { 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]), insert_index(icon[VI::IConn::SeqIndex]),
ijk({icon[VI::IConn::CellI] - 1, icon[VI::IConn::CellJ] - 1, icon[VI::IConn::CellK] - 1}), ijk({icon[VI::IConn::CellI] - 1, icon[VI::IConn::CellJ] - 1, icon[VI::IConn::CellK] - 1}),
status(icon[VI::IConn::ConnStat]), status(icon[VI::IConn::ConnStat]),

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <opm/parser/eclipse/Utility/String.hpp>
#include <opm/io/eclipse/rst/header.hpp>
#include <opm/io/eclipse/rst/group.hpp>
#include <opm/output/eclipse/VectorItems/group.hpp>
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])
{
}
}
}

View File

@ -26,7 +26,7 @@ namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
namespace Opm { namespace Opm {
namespace RestartIO { namespace RestartIO {
Header::Header(const std::vector<int>& intehead, const std::vector<bool>& logihead, const std::vector<double>& doubhead) : RstHeader::RstHeader(const std::vector<int>& intehead, const std::vector<bool>& logihead, const std::vector<double>& doubhead) :
nx(intehead[VI::intehead::NX]), nx(intehead[VI::intehead::NX]),
ny(intehead[VI::intehead::NY]), ny(intehead[VI::intehead::NY]),
nz(intehead[VI::intehead::NZ]), nz(intehead[VI::intehead::NZ]),

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <opm/io/eclipse/rst/segment.hpp>
#include <opm/output/eclipse/VectorItems/msw.hpp>
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]);
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <opm/io/eclipse/rst/header.hpp>
#include <opm/io/eclipse/rst/connection.hpp>
#include <opm/io/eclipse/rst/well.hpp>
#include <opm/io/eclipse/rst/state.hpp>
#include <opm/output/eclipse/VectorItems/connection.hpp>
#include <opm/output/eclipse/VectorItems/well.hpp>
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
namespace Opm {
namespace RestartIO {
RstState::RstState(const std::vector<int>& intehead,
const std::vector<bool>& logihead,
const std::vector<double>& doubhead,
const std::vector<std::string>& zgrp,
const std::vector<int>& igrp,
const std::vector<float>& sgrp,
const std::vector<double>& xgrp,
const std::vector<std::string>& zwel,
const std::vector<int>& iwel,
const std::vector<float>& swel,
const std::vector<double>& xwel,
const std::vector<int>& icon,
const std::vector<float>& scon,
const std::vector<double>& 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<int>& intehead,
const std::vector<bool>& logihead,
const std::vector<double>& doubhead,
const std::vector<std::string>& zgrp,
const std::vector<int>& igrp,
const std::vector<float>& sgrp,
const std::vector<double>& xgrp,
const std::vector<std::string>& zwel,
const std::vector<int>& iwel,
const std::vector<float>& swel,
const std::vector<double>& xwel,
const std::vector<int>& icon,
const std::vector<float>& scon,
const std::vector<double>& xcon,
const std::vector<int>& iseg,
const std::vector<double>& 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<std::string>& zgrp,
const std::vector<int>& igrp,
const std::vector<float>& sgrp,
const std::vector<double>& 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<int>("INTEHEAD", report_step, 0);
const auto& logihead = rst_file.getRst<bool>("LOGIHEAD", report_step, 0);
const auto& doubhead = rst_file.getRst<double>("DOUBHEAD", report_step, 0);
const auto& zgrp = rst_file.getRst<std::string>("ZGRP", report_step, 0);
const auto& igrp = rst_file.getRst<int>("IGRP", report_step, 0);
const auto& sgrp = rst_file.getRst<float>("SGRP", report_step, 0);
const auto& xgrp = rst_file.getRst<double>("XGRP", report_step, 0);
const auto& zwel = rst_file.getRst<std::string>("ZWEL", report_step, 0);
const auto& iwel = rst_file.getRst<int>("IWEL", report_step, 0);
const auto& swel = rst_file.getRst<float>("SWEL", report_step, 0);
const auto& xwel = rst_file.getRst<double>("XWEL", report_step, 0);
const auto& icon = rst_file.getRst<int>("ICON", report_step, 0);
const auto& scon = rst_file.getRst<float>("SCON", report_step, 0);
const auto& xcon = rst_file.getRst<double>("XCON", report_step, 0);
if (rst_file.hasKey("ISEG")) {
const auto& iseg = rst_file.getRst<int>("ISEG", report_step, 0);
const auto& rseg = rst_file.getRst<double>("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);
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <opm/parser/eclipse/Utility/String.hpp>
#include <opm/io/eclipse/rst/header.hpp>
#include <opm/io/eclipse/rst/connection.hpp>
#include <opm/io/eclipse/rst/well.hpp>
#include <opm/output/eclipse/VectorItems/connection.hpp>
#include <opm/output/eclipse/VectorItems/msw.hpp>
#include <opm/output/eclipse/VectorItems/well.hpp>
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<int>& iseg,
const std::vector<double>& rseg) :
RstWell(header, zwel, iwel, swel, xwel, icon, scon, xcon)
{
if (this->msw_index) {
std::unordered_map<int, std::size_t> 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);
}
}
}
}
}
}

34
tests/rst_load.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <opm/io/eclipse/rst/state.hpp>
#include <opm/io/eclipse/ERst.hpp>
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);
}
}
}

View File

@ -803,7 +803,7 @@ BOOST_AUTO_TEST_CASE(TestRestartIOConnection) {
const auto ih = MockIH {static_cast<int>(simCase.sched.getWells(rptStep).size())}; const auto ih = MockIH {static_cast<int>(simCase.sched.getWells(rptStep).size())};
const Opm::data::WellRates wrc = wr(); 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}; auto conn = Opm::RestartIO::Helpers::AggregateConnectionData{ih.value};
conn.captureDeclaredConnData(simCase.sched, conn.captureDeclaredConnData(simCase.sched,
simCase.grid, simCase.grid,
@ -816,7 +816,7 @@ BOOST_AUTO_TEST_CASE(TestRestartIOConnection) {
const auto scon = conn.getSConn(); const auto scon = conn.getSConn();
const auto xcon = conn.getXConn(); const auto xcon = conn.getXConn();
std::vector<Opm::RestartIO::Connection> connections; std::vector<Opm::RestartIO::RstConnection> connections;
for (int iw = 0; iw < header.num_wells; iw++) { for (int iw = 0; iw < header.num_wells; iw++) {
for (int ic = 0; ic < header.ncwmax; ic++) { for (int ic = 0; ic < header.ncwmax; ic++) {
std::size_t icon_offset = header.niconz * (header.ncwmax * iw + ic); std::size_t icon_offset = header.niconz * (header.ncwmax * iw + ic);

View File

@ -29,6 +29,7 @@
#include <opm/output/data/Wells.hpp> #include <opm/output/data/Wells.hpp>
#include <opm/io/eclipse/rst/segment.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp> #include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp> #include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp> #include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
@ -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<int>(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() BOOST_AUTO_TEST_SUITE_END()

View File

@ -23,10 +23,15 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <opm/output/eclipse/AggregateWellData.hpp> #include <opm/output/eclipse/AggregateWellData.hpp>
#include <opm/output/eclipse/AggregateConnectionData.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/output/eclipse/VectorItems/intehead.hpp> #include <opm/output/eclipse/VectorItems/intehead.hpp>
#include <opm/output/eclipse/VectorItems/well.hpp> #include <opm/output/eclipse/VectorItems/well.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#include <opm/io/eclipse/rst/well.hpp>
#include <opm/io/eclipse/rst/header.hpp>
#include <opm/output/data/Wells.hpp> #include <opm/output/data/Wells.hpp>
@ -342,17 +347,21 @@ TSTEP -- 8
return xw; return xw;
} }
}
} // namespace
struct SimulationCase struct SimulationCase
{ {
explicit SimulationCase(const Opm::Deck& deck) explicit SimulationCase(const Opm::Deck& deck)
: es { deck } : es { deck }
, grid { deck }
, sched{ deck, es } , sched{ deck, es }
{} {}
// Order requirement: 'es' must be declared/initialised before 'sched'. // Order requirement: 'es' must be declared/initialised before 'sched'.
Opm::EclipseState es; Opm::EclipseState es;
Opm::EclipseGrid grid;
Opm::Schedule sched; 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<bool>(100), std::vector<double>(1000));
std::vector<Opm::RestartIO::RstWell> wells;
std::vector<std::string> 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() BOOST_AUTO_TEST_SUITE_END()

View File

@ -571,7 +571,7 @@ BOOST_AUTO_TEST_CASE(TestHeader) {
.regionDimensions({ntfip, nmfipr, 0,0,0}) .regionDimensions({ntfip, nmfipr, 0,0,0})
.ngroups({ngroup}); .ngroups({ngroup});
Opm::RestartIO::Header header(ih.data(), std::vector<bool>(100), std::vector<double>(1000)); Opm::RestartIO::RstHeader header(ih.data(), std::vector<bool>(100), std::vector<double>(1000));
BOOST_CHECK_EQUAL(header.nx, nx); BOOST_CHECK_EQUAL(header.nx, nx);
BOOST_CHECK_EQUAL(header.ny, ny); BOOST_CHECK_EQUAL(header.ny, ny);
BOOST_CHECK_EQUAL(header.nactive, nactive); BOOST_CHECK_EQUAL(header.nactive, nactive);

314
tests/test_rst.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#define BOOST_TEST_MODULE test_rst
#include <boost/test/unit_test.hpp>
#include <vector>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#include <opm/output/eclipse/AggregateWellData.hpp>
#include <opm/output/eclipse/AggregateConnectionData.hpp>
#include <opm/output/eclipse/AggregateGroupData.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/output/eclipse/VectorItems/intehead.hpp>
#include <opm/output/eclipse/VectorItems/well.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#include <opm/output/data/Wells.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/io/eclipse/rst/connection.hpp>
#include <opm/io/eclipse/rst/header.hpp>
#include <opm/io/eclipse/rst/group.hpp>
#include <opm/io/eclipse/rst/segment.hpp>
#include <opm/io/eclipse/rst/well.hpp>
#include <opm/io/eclipse/rst/state.hpp>
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<std::string> 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<std::string> zwel;
for (const auto& s8: zwel8)
zwel.push_back(s8.c_str());
std::vector<std::string> 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);
}