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:
parent
e92d6138f8
commit
4956e880a4
@ -137,6 +137,7 @@ namespace Opm {
|
||||
double cell_saturation_water;
|
||||
double cell_saturation_gas;
|
||||
double effective_Kh;
|
||||
double trans_factor;
|
||||
|
||||
bool operator==(const Connection& conn2) const
|
||||
{
|
||||
@ -508,6 +509,7 @@ namespace Opm {
|
||||
buffer.write(this->cell_saturation_water);
|
||||
buffer.write(this->cell_saturation_gas);
|
||||
buffer.write(this->effective_Kh);
|
||||
buffer.write(this->trans_factor);
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
@ -589,6 +591,7 @@ namespace Opm {
|
||||
buffer.read(this->cell_saturation_water);
|
||||
buffer.read(this->cell_saturation_gas);
|
||||
buffer.read(this->effective_Kh);
|
||||
buffer.read(this->trans_factor);
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
|
@ -199,6 +199,23 @@ namespace {
|
||||
sConn[Ix::item31] = -1.0e+20f;
|
||||
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
|
||||
|
||||
namespace XConn {
|
||||
@ -298,7 +315,11 @@ captureDeclaredConnData(const Schedule& sched,
|
||||
SConn::staticContrib(conn, units, sc);
|
||||
|
||||
if (dynConnRes != nullptr) {
|
||||
// Simulator provides dynamic connection results such as flow
|
||||
// rates and PI-adjusted transmissibility factors.
|
||||
auto xc = this->xConn_(wellID, connID);
|
||||
|
||||
SConn::dynamicContrib(*dynConnRes, units, sc);
|
||||
XConn::dynamicContrib(*dynConnRes, units, xc);
|
||||
}
|
||||
});
|
||||
|
@ -585,31 +585,32 @@ inline quantity srate( 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;
|
||||
// Like completion rate we need to look
|
||||
// up a connection with offset 0.
|
||||
if (args.schedule_wells.empty())
|
||||
// No wells. Before simulation starts?
|
||||
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 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();
|
||||
const auto& name = well.name();
|
||||
if( args.wells.count( name ) == 0 ) return zero;
|
||||
if (connPos == connections.end())
|
||||
// No dynamic results for this connection.
|
||||
return zero;
|
||||
|
||||
const auto& grid = args.grid;
|
||||
const auto& connections = well.getConnections();
|
||||
|
||||
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 };
|
||||
// Dynamic connection result's "trans_factor" includes PI-adjustment.
|
||||
return { connPos->trans_factor, measure::transmissibility };
|
||||
}
|
||||
|
||||
template <Opm::data::SegmentPressures::Value ix>
|
||||
|
@ -471,9 +471,7 @@ END
|
||||
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;
|
||||
|
||||
@ -497,12 +495,15 @@ END
|
||||
.set(o::gas, qg * (float(i) + 1.));
|
||||
c.pressure = 215.;
|
||||
c.index = connections[i].global_index();
|
||||
c.trans_factor = connections[i].CF();
|
||||
}
|
||||
|
||||
auto seg = Opm::data::Segment {};
|
||||
for (std::size_t i = 1; i < 5; i++) {
|
||||
xw["PROD"].segments.insert(std::pair<std::size_t, Opm::data::Segment>(i, seg));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const auto& well = sched.getWell("WINJ", 0);
|
||||
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.pressure = 218.;
|
||||
c.index = connections[i].global_index();
|
||||
c.trans_factor = connections[i].CF();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xw;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
struct SimulationCase {
|
||||
explicit SimulationCase(const Opm::Deck& deck)
|
||||
: es(deck)
|
||||
, python(std::make_shared<Opm::Python>())
|
||||
, grid(deck)
|
||||
, sched(deck, es, python)
|
||||
{
|
||||
}
|
||||
struct SimulationCase {
|
||||
explicit SimulationCase(const Opm::Deck& deck)
|
||||
: es (deck)
|
||||
, grid (deck)
|
||||
, sched(deck, es, std::make_shared<Opm::Python>())
|
||||
{}
|
||||
|
||||
// Order requirement: 'es' must be declared/initialised before 'sched'.
|
||||
Opm::EclipseState es;
|
||||
std::shared_ptr<Opm::Python> python;
|
||||
Opm::EclipseGrid grid;
|
||||
Opm::Schedule sched;
|
||||
};
|
||||
// Order requirement: 'es' must be declared/initialised before 'sched'.
|
||||
Opm::EclipseState es;
|
||||
Opm::EclipseGrid grid;
|
||||
Opm::Schedule sched;
|
||||
};
|
||||
|
||||
// =====================================================================
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Aggregate_ConnData)
|
||||
|
||||
|
||||
// test dimensions of Connection data
|
||||
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_AUTO_TEST_CASE(Declared_Connection_Data)
|
||||
{
|
||||
const auto simCase = SimulationCase {first_sim()};
|
||||
@ -730,7 +728,6 @@ BOOST_AUTO_TEST_CASE(Declared_Connection_Data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(InactiveCell) {
|
||||
auto simCase = SimulationCase{first_sim()};
|
||||
const auto rptStep = std::size_t{1};
|
||||
|
@ -291,12 +291,12 @@ BOOST_AUTO_TEST_CASE(test_RFT)
|
||||
|
||||
std::vector<Opm::data::Connection> well1_comps(9);
|
||||
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);
|
||||
}
|
||||
std::vector<Opm::data::Connection> well2_comps(6);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -420,12 +420,12 @@ BOOST_AUTO_TEST_CASE(test_RFT2)
|
||||
|
||||
std::vector<Opm::data::Connection> well1_comps(9);
|
||||
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);
|
||||
}
|
||||
std::vector<Opm::data::Connection> well2_comps(6);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -493,6 +493,7 @@ namespace {
|
||||
|
||||
c.cell_saturation_gas = 0.15;
|
||||
c.cell_saturation_water = 0.3 + con/20.0;
|
||||
c.trans_factor = 0.98765;
|
||||
}
|
||||
|
||||
return xcon;
|
||||
@ -522,6 +523,7 @@ namespace {
|
||||
|
||||
c.cell_saturation_gas = 0.6 - con/20.0;
|
||||
c.cell_saturation_water = 0.25;
|
||||
c.trans_factor = 0.12345;
|
||||
}
|
||||
|
||||
return xcon;
|
||||
|
@ -174,15 +174,15 @@ data::Wells mkWells() {
|
||||
* the completion keys (active indices) and well names correspond to the
|
||||
* 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( { 288, rc2, 33.19, 123.4, 432.1, 0.26, 0.45, 2.56 } );
|
||||
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, 2.345 } );
|
||||
|
||||
w2.rates = r2;
|
||||
w2.thp = 2.0;
|
||||
w2.bhp = 2.34;
|
||||
w2.temperature = 4.56;
|
||||
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;
|
||||
|
@ -63,6 +63,12 @@ namespace {
|
||||
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)
|
||||
{
|
||||
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
|
||||
input deck.
|
||||
*/
|
||||
data::Connection well1_comp1 { 0 , crates1, 1.9 , 123.4, 314.15, 0.35, 0.25, 2.718e2};
|
||||
data::Connection well2_comp1 { 1 , crates2, 1.10 , 123.4, 212.1, 0.78, 0.0, 12.34};
|
||||
data::Connection well2_comp2 { 101, crates3, 1.11 , 123.4, 150.6, 0.001, 0.89, 100.0};
|
||||
data::Connection well3_comp1 { 2 , crates3, 1.11 , 123.4, 456.78, 0.0, 0.15, 432.1};
|
||||
data::Connection well6_comp1 { 5 , crates6, 6.11 , 623.4, 656.78, 0.0, 0.65, 632.1};
|
||||
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 , 222.333*cp_rm3_per_db() };
|
||||
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 , 444.555*cp_rm3_per_db() };
|
||||
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
|
||||
*/
|
||||
@ -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( 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( 2.1430730819702148 , 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( 2.7855057716369629 , ecl_sum_get_well_completion_var( resp, 1, "W_3", "CTFAC", 3, 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( 222.333 , ecl_sum_get_well_completion_var( resp, 1, "W_2", "CTFAC", 2, 1, 1), 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( 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( 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, 3, "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
|
||||
BOOST_CHECK( !ecl_sum_has_general_var( resp , "BPR:2,1,10"));
|
||||
|
@ -169,7 +169,7 @@ static data::Wells result_wells() {
|
||||
syncronized with the global index in the COMPDAT keyword in the
|
||||
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
|
||||
|
@ -103,14 +103,14 @@ BOOST_AUTO_TEST_CASE(get_completions) {
|
||||
* the completion keys (active indices) and well names correspond to the
|
||||
* 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( { 288, rc2, 33.19, 67.89, 98.76, 0.5, 0.125, 355.113 } );
|
||||
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, 0.355113 } );
|
||||
|
||||
w2.rates = r2;
|
||||
w2.bhp = 2.34;
|
||||
w2.temperature = 4.56;
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user