Summary/Restart: Get CTF From Simulator

This commit switches to getting the output files' connection
transmissibility factor from Opm::data::Connection instead of
Opm::Connection.  This is in preparation for implementing the WELPI
feature, in which the CTFs are occasionally adjusted based on the
dynamic simulation state.
This commit is contained in:
Bård Skaflestad 2020-10-04 15:48:21 +02:00
parent e92d6138f8
commit 4956e880a4
9 changed files with 95 additions and 64 deletions

View File

@ -137,6 +137,7 @@ namespace Opm {
double cell_saturation_water; double cell_saturation_water;
double cell_saturation_gas; double cell_saturation_gas;
double effective_Kh; double effective_Kh;
double trans_factor;
bool operator==(const Connection& conn2) const bool operator==(const Connection& conn2) const
{ {
@ -508,6 +509,7 @@ namespace Opm {
buffer.write(this->cell_saturation_water); buffer.write(this->cell_saturation_water);
buffer.write(this->cell_saturation_gas); buffer.write(this->cell_saturation_gas);
buffer.write(this->effective_Kh); buffer.write(this->effective_Kh);
buffer.write(this->trans_factor);
} }
template <class MessageBufferType> template <class MessageBufferType>
@ -589,6 +591,7 @@ namespace Opm {
buffer.read(this->cell_saturation_water); buffer.read(this->cell_saturation_water);
buffer.read(this->cell_saturation_gas); buffer.read(this->cell_saturation_gas);
buffer.read(this->effective_Kh); buffer.read(this->effective_Kh);
buffer.read(this->trans_factor);
} }
template <class MessageBufferType> template <class MessageBufferType>

View File

@ -199,6 +199,23 @@ namespace {
sConn[Ix::item31] = -1.0e+20f; sConn[Ix::item31] = -1.0e+20f;
sConn[Ix::CFInDeck] = (conn.ctfAssignedFromInput()) ? 1 : 0; sConn[Ix::CFInDeck] = (conn.ctfAssignedFromInput()) ? 1 : 0;
} }
template <class SConnArray>
void dynamicContrib(const Opm::data::Connection& xconn,
const Opm::UnitSystem& units,
SConnArray& sConn)
{
using M = ::Opm::UnitSystem::measure;
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SConn::index;
auto scprop = [&units](const M u, const double x) -> float
{
return static_cast<float>(units.from_si(u, x));
};
sConn[Ix::item12] = sConn[Ix::ConnTrans] =
scprop(M::transmissibility, xconn.trans_factor);
}
} // SConn } // SConn
namespace XConn { namespace XConn {
@ -298,7 +315,11 @@ captureDeclaredConnData(const Schedule& sched,
SConn::staticContrib(conn, units, sc); SConn::staticContrib(conn, units, sc);
if (dynConnRes != nullptr) { if (dynConnRes != nullptr) {
// Simulator provides dynamic connection results such as flow
// rates and PI-adjusted transmissibility factors.
auto xc = this->xConn_(wellID, connID); auto xc = this->xConn_(wellID, connID);
SConn::dynamicContrib(*dynConnRes, units, sc);
XConn::dynamicContrib(*dynConnRes, units, xc); XConn::dynamicContrib(*dynConnRes, units, xc);
} }
}); });

View File

@ -585,31 +585,32 @@ inline quantity srate( const fn_args& args ) {
} }
inline quantity trans_factors ( const fn_args& args ) { inline quantity trans_factors ( const fn_args& args ) {
const quantity zero = { 0, measure::transmissibility }; const quantity zero = { 0.0, measure::transmissibility };
if( args.schedule_wells.empty() ) return zero; if (args.schedule_wells.empty())
// Like completion rate we need to look // No wells. Before simulation starts?
// up a connection with offset 0. return zero;
auto xwPos = args.wells.find(args.schedule_wells.front().name());
if (xwPos == args.wells.end())
// No dynamic results for this well. Not open?
return zero;
// Like completion rate we need to look up a connection with offset 0.
const size_t global_index = args.num - 1; const size_t global_index = args.num - 1;
const auto& connections = xwPos->second.connections;
auto connPos = std::find_if(connections.begin(), connections.end(),
[global_index](const Opm::data::Connection& c)
{
return c.index == global_index;
});
const auto& well = args.schedule_wells.front(); if (connPos == connections.end())
const auto& name = well.name(); // No dynamic results for this connection.
if( args.wells.count( name ) == 0 ) return zero; return zero;
const auto& grid = args.grid; // Dynamic connection result's "trans_factor" includes PI-adjustment.
const auto& connections = well.getConnections(); return { connPos->trans_factor, measure::transmissibility };
const auto& connection = std::find_if(
connections.begin(),
connections.end(),
[=]( const Opm::Connection& c ) {
return grid.getGlobalIndex(c.getI(), c.getJ(), c.getK()) == global_index;
} );
if( connection == connections.end() ) return zero;
const auto& v = connection->CF();
return { v, measure::transmissibility };
} }
template <Opm::data::SegmentPressures::Value ix> template <Opm::data::SegmentPressures::Value ix>

View File

@ -471,9 +471,7 @@ END
return Opm::Parser{}.parseString(input); return Opm::Parser{}.parseString(input);
} }
Opm::data::WellRates wr(const Opm::Schedule& sched)
Opm::data::WellRates
wr(const Opm::Schedule& sched)
{ {
using o = ::Opm::data::Rates::opt; using o = ::Opm::data::Rates::opt;
@ -497,12 +495,15 @@ END
.set(o::gas, qg * (float(i) + 1.)); .set(o::gas, qg * (float(i) + 1.));
c.pressure = 215.; c.pressure = 215.;
c.index = connections[i].global_index(); c.index = connections[i].global_index();
c.trans_factor = connections[i].CF();
} }
auto seg = Opm::data::Segment {}; auto seg = Opm::data::Segment {};
for (std::size_t i = 1; i < 5; i++) { for (std::size_t i = 1; i < 5; i++) {
xw["PROD"].segments.insert(std::pair<std::size_t, Opm::data::Segment>(i, seg)); xw["PROD"].segments.insert(std::pair<std::size_t, Opm::data::Segment>(i, seg));
} }
} }
{ {
const auto& well = sched.getWell("WINJ", 0); const auto& well = sched.getWell("WINJ", 0);
const auto& connections = well.getConnections(); const auto& connections = well.getConnections();
@ -519,34 +520,32 @@ END
c.rates.set(o::wat, qw * (float(i) + 1.)).set(o::oil, 0.).set(o::gas, 0.); c.rates.set(o::wat, qw * (float(i) + 1.)).set(o::oil, 0.).set(o::gas, 0.);
c.pressure = 218.; c.pressure = 218.;
c.index = connections[i].global_index(); c.index = connections[i].global_index();
c.trans_factor = connections[i].CF();
} }
} }
} }
return xw; return xw;
} }
} // namespace } // namespace
struct SimulationCase { struct SimulationCase {
explicit SimulationCase(const Opm::Deck& deck) explicit SimulationCase(const Opm::Deck& deck)
: es(deck) : es (deck)
, python(std::make_shared<Opm::Python>()) , grid (deck)
, grid(deck) , sched(deck, es, std::make_shared<Opm::Python>())
, sched(deck, es, python) {}
{
}
// Order requirement: 'es' must be declared/initialised before 'sched'. // Order requirement: 'es' must be declared/initialised before 'sched'.
Opm::EclipseState es; Opm::EclipseState es;
std::shared_ptr<Opm::Python> python; Opm::EclipseGrid grid;
Opm::EclipseGrid grid; Opm::Schedule sched;
Opm::Schedule sched; };
};
// ===================================================================== // =====================================================================
BOOST_AUTO_TEST_SUITE(Aggregate_ConnData) BOOST_AUTO_TEST_SUITE(Aggregate_ConnData)
// test dimensions of Connection data // test dimensions of Connection data
BOOST_AUTO_TEST_CASE (Constructor) BOOST_AUTO_TEST_CASE (Constructor)
{ {
@ -559,7 +558,6 @@ BOOST_AUTO_TEST_CASE (Constructor)
BOOST_CHECK_EQUAL(amconn.getXConn().size(), ih.nwells * ih.ncwmax * ih.nxconz); BOOST_CHECK_EQUAL(amconn.getXConn().size(), ih.nwells * ih.ncwmax * ih.nxconz);
} }
BOOST_AUTO_TEST_CASE(Declared_Connection_Data) BOOST_AUTO_TEST_CASE(Declared_Connection_Data)
{ {
const auto simCase = SimulationCase {first_sim()}; const auto simCase = SimulationCase {first_sim()};
@ -730,7 +728,6 @@ BOOST_AUTO_TEST_CASE(Declared_Connection_Data)
} }
} }
BOOST_AUTO_TEST_CASE(InactiveCell) { BOOST_AUTO_TEST_CASE(InactiveCell) {
auto simCase = SimulationCase{first_sim()}; auto simCase = SimulationCase{first_sim()};
const auto rptStep = std::size_t{1}; const auto rptStep = std::size_t{1};

View File

@ -291,12 +291,12 @@ BOOST_AUTO_TEST_CASE(test_RFT)
std::vector<Opm::data::Connection> well1_comps(9); std::vector<Opm::data::Connection> well1_comps(9);
for (size_t i = 0; i < 9; ++i) { for (size_t i = 0; i < 9; ++i) {
Opm::data::Connection well_comp { grid.getGlobalIndex(8,8,i) ,r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i, 1.2e3}; Opm::data::Connection well_comp { grid.getGlobalIndex(8,8,i) ,r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i, 1.2e3, 4.321};
well1_comps[i] = std::move(well_comp); well1_comps[i] = std::move(well_comp);
} }
std::vector<Opm::data::Connection> well2_comps(6); std::vector<Opm::data::Connection> well2_comps(6);
for (size_t i = 0; i < 6; ++i) { for (size_t i = 0; i < 6; ++i) {
Opm::data::Connection well_comp { grid.getGlobalIndex(3,3,i+3) ,r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2, 0.15}; Opm::data::Connection well_comp { grid.getGlobalIndex(3,3,i+3) ,r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2, 0.15, 0.54321};
well2_comps[i] = std::move(well_comp); well2_comps[i] = std::move(well_comp);
} }
@ -420,12 +420,12 @@ BOOST_AUTO_TEST_CASE(test_RFT2)
std::vector<Opm::data::Connection> well1_comps(9); std::vector<Opm::data::Connection> well1_comps(9);
for (size_t i = 0; i < 9; ++i) { for (size_t i = 0; i < 9; ++i) {
Opm::data::Connection well_comp { grid.getGlobalIndex(8,8,i) ,r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i, 3.14e5}; Opm::data::Connection well_comp { grid.getGlobalIndex(8,8,i) ,r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i, 3.14e5, 0.1234};
well1_comps[i] = std::move(well_comp); well1_comps[i] = std::move(well_comp);
} }
std::vector<Opm::data::Connection> well2_comps(6); std::vector<Opm::data::Connection> well2_comps(6);
for (size_t i = 0; i < 6; ++i) { for (size_t i = 0; i < 6; ++i) {
Opm::data::Connection well_comp { grid.getGlobalIndex(3,3,i+3) ,r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2, 355.113}; Opm::data::Connection well_comp { grid.getGlobalIndex(3,3,i+3) ,r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2, 355.113, 0.9876};
well2_comps[i] = std::move(well_comp); well2_comps[i] = std::move(well_comp);
} }
@ -493,6 +493,7 @@ namespace {
c.cell_saturation_gas = 0.15; c.cell_saturation_gas = 0.15;
c.cell_saturation_water = 0.3 + con/20.0; c.cell_saturation_water = 0.3 + con/20.0;
c.trans_factor = 0.98765;
} }
return xcon; return xcon;
@ -522,6 +523,7 @@ namespace {
c.cell_saturation_gas = 0.6 - con/20.0; c.cell_saturation_gas = 0.6 - con/20.0;
c.cell_saturation_water = 0.25; c.cell_saturation_water = 0.25;
c.trans_factor = 0.12345;
} }
return xcon; return xcon;

View File

@ -174,15 +174,15 @@ data::Wells mkWells() {
* the completion keys (active indices) and well names correspond to the * the completion keys (active indices) and well names correspond to the
* input deck. All other entries in the well structures are arbitrary. * input deck. All other entries in the well structures are arbitrary.
*/ */
w1.connections.push_back( { 88, rc1, 30.45, 123.4, 543.21, 0.62, 0.15, 1.0e3 } ); w1.connections.push_back( { 88, rc1, 30.45, 123.4, 543.21, 0.62, 0.15, 1.0e3, 1.234 } );
w1.connections.push_back( { 288, rc2, 33.19, 123.4, 432.1, 0.26, 0.45, 2.56 } ); w1.connections.push_back( { 288, rc2, 33.19, 123.4, 432.1, 0.26, 0.45, 2.56, 2.345 } );
w2.rates = r2; w2.rates = r2;
w2.thp = 2.0; w2.thp = 2.0;
w2.bhp = 2.34; w2.bhp = 2.34;
w2.temperature = 4.56; w2.temperature = 4.56;
w2.control = 2; w2.control = 2;
w2.connections.push_back( { 188, rc3, 36.22, 123.4, 256.1, 0.55, 0.0125, 314.15 } ); w2.connections.push_back( { 188, rc3, 36.22, 123.4, 256.1, 0.55, 0.0125, 314.15, 3.456 } );
{ {
data::Wells wellRates; data::Wells wellRates;

View File

@ -63,6 +63,12 @@ namespace {
return unit::cubic(unit::meter) / unit::day; return unit::cubic(unit::meter) / unit::day;
} }
double cp_rm3_per_db()
{
return prefix::centi*unit::Poise * unit::cubic(unit::meter)
/ (unit::day * unit::barsa);
}
std::string toupper(std::string input) std::string toupper(std::string input)
{ {
for (auto& c : input) { for (auto& c : input) {
@ -247,11 +253,12 @@ data::Wells result_wells(const bool w3_injector = true)
syncronized with the global index in the COMPDAT keyword in the syncronized with the global index in the COMPDAT keyword in the
input deck. input deck.
*/ */
data::Connection well1_comp1 { 0 , crates1, 1.9 , 123.4, 314.15, 0.35, 0.25, 2.718e2}; data::Connection well1_comp1 { 0 , crates1, 1.9 , 123.4, 314.15, 0.35 , 0.25, 2.718e2, 111.222*cp_rm3_per_db() };
data::Connection well2_comp1 { 1 , crates2, 1.10 , 123.4, 212.1, 0.78, 0.0, 12.34}; data::Connection well2_comp1 { 1 , crates2, 1.10 , 123.4, 212.1 , 0.78 , 0.0 , 12.34 , 222.333*cp_rm3_per_db() };
data::Connection well2_comp2 { 101, crates3, 1.11 , 123.4, 150.6, 0.001, 0.89, 100.0}; data::Connection well2_comp2 { 101, crates3, 1.11 , 123.4, 150.6 , 0.001, 0.89, 100.0 , 333.444*cp_rm3_per_db() };
data::Connection well3_comp1 { 2 , crates3, 1.11 , 123.4, 456.78, 0.0, 0.15, 432.1}; data::Connection well3_comp1 { 2 , crates3, 1.11 , 123.4, 456.78, 0.0 , 0.15, 432.1 , 444.555*cp_rm3_per_db() };
data::Connection well6_comp1 { 5 , crates6, 6.11 , 623.4, 656.78, 0.0, 0.65, 632.1}; data::Connection well6_comp1 { 5 , crates6, 6.11 , 623.4, 656.78, 0.0 , 0.65, 632.1 , 555.666*cp_rm3_per_db() };
/* /*
The completions The completions
*/ */
@ -1477,13 +1484,13 @@ BOOST_AUTO_TEST_CASE(BLOCK_VARIABLES) {
BOOST_CHECK_CLOSE( 31.0 , units.to_si( UnitSystem::measure::viscosity , ecl_sum_get_general_var( resp, 1, "BVOIL:1,1,1")) , 1e-5); BOOST_CHECK_CLOSE( 31.0 , units.to_si( UnitSystem::measure::viscosity , ecl_sum_get_general_var( resp, 1, "BVOIL:1,1,1")) , 1e-5);
BOOST_CHECK_CLOSE( 33.0 , units.to_si( UnitSystem::measure::viscosity , ecl_sum_get_general_var( resp, 1, "BOVIS:1,1,1")) , 1e-5); BOOST_CHECK_CLOSE( 33.0 , units.to_si( UnitSystem::measure::viscosity , ecl_sum_get_general_var( resp, 1, "BOVIS:1,1,1")) , 1e-5);
BOOST_CHECK_CLOSE( 100 , ecl_sum_get_well_completion_var( resp, 1, "W_1", "CTFAC", 1, 1, 1), 1e-5); BOOST_CHECK_CLOSE( 111.222 , ecl_sum_get_well_completion_var( resp, 1, "W_1", "CTFAC", 1, 1, 1), 1e-5);
BOOST_CHECK_CLOSE( 2.1430730819702148 , ecl_sum_get_well_completion_var( resp, 1, "W_2", "CTFAC", 2, 1, 1), 1e-5); BOOST_CHECK_CLOSE( 222.333 , ecl_sum_get_well_completion_var( resp, 1, "W_2", "CTFAC", 2, 1, 1), 1e-5);
BOOST_CHECK_CLOSE( 2.6788413524627686 , ecl_sum_get_well_completion_var( resp, 1, "W_2", "CTFAC", 2, 1, 2), 1e-5); BOOST_CHECK_CLOSE( 333.444 , ecl_sum_get_well_completion_var( resp, 1, "W_2", "CTFAC", 2, 1, 2), 1e-5);
BOOST_CHECK_CLOSE( 2.7855057716369629 , ecl_sum_get_well_completion_var( resp, 1, "W_3", "CTFAC", 3, 1, 1), 1e-5); BOOST_CHECK_CLOSE( 444.555 , ecl_sum_get_well_completion_var( resp, 1, "W_3", "CTFAC", 3, 1, 1), 1e-5);
BOOST_CHECK_CLOSE( 50 , ecl_sum_get_well_completion_var( resp, 3, "W_1", "CTFAC", 1, 1, 1), 1e-5); BOOST_CHECK_CLOSE( 111.222 , ecl_sum_get_well_completion_var( resp, 3, "W_1", "CTFAC", 1, 1, 1), 1e-5);
BOOST_CHECK_CLOSE( 25 , ecl_sum_get_well_completion_var( resp, 4, "W_1", "CTFAC", 1, 1, 1), 1e-5); BOOST_CHECK_CLOSE( 111.222 , ecl_sum_get_well_completion_var( resp, 4, "W_1", "CTFAC", 1, 1, 1), 1e-5);
// Cell is not active // Cell is not active
BOOST_CHECK( !ecl_sum_has_general_var( resp , "BPR:2,1,10")); BOOST_CHECK( !ecl_sum_has_general_var( resp , "BPR:2,1,10"));

View File

@ -169,7 +169,7 @@ static data::Wells result_wells() {
syncronized with the global index in the COMPDAT keyword in the syncronized with the global index in the COMPDAT keyword in the
input deck. input deck.
*/ */
data::Connection well1_comp1 { 0 , crates1, 1.9 , 123.4, 314.15, 0.35, 0.25, 2.718e2}; data::Connection well1_comp1 { 0 , crates1, 1.9 , 123.4, 314.15, 0.35, 0.25, 2.718e2, 0.12345};
/* /*
The completions The completions

View File

@ -103,14 +103,14 @@ BOOST_AUTO_TEST_CASE(get_completions) {
* the completion keys (active indices) and well names correspond to the * the completion keys (active indices) and well names correspond to the
* input deck. All other entries in the well structures are arbitrary. * input deck. All other entries in the well structures are arbitrary.
*/ */
w1.connections.push_back( { 88, rc1, 30.45, 123.45, 543.21, 0.123, 0.5, 17.29 } ); w1.connections.push_back( { 88, rc1, 30.45, 123.45, 543.21, 0.123, 0.5, 17.29, 0.1729 } );
w1.connections.push_back( { 288, rc2, 33.19, 67.89, 98.76, 0.5, 0.125, 355.113 } ); w1.connections.push_back( { 288, rc2, 33.19, 67.89, 98.76, 0.5, 0.125, 355.113, 0.355113 } );
w2.rates = r2; w2.rates = r2;
w2.bhp = 2.34; w2.bhp = 2.34;
w2.temperature = 4.56; w2.temperature = 4.56;
w2.control = 2; w2.control = 2;
w2.connections.push_back( { 188, rc3, 36.22, 19.28, 28.91, 0.125, 0.125, 3.141 } ); w2.connections.push_back( { 188, rc3, 36.22, 19.28, 28.91, 0.125, 0.125, 3.141, 0.31415 } );
data::Wells wellRates; data::Wells wellRates;