FOE support
Field efficiency: (OIP(initial) - OIP(now)) / OIP(initial). The initial OIP is cached, and FOIP is reused for OIP(now). Adds the operator-(double,quantity) to make the formula obvious from the FOE function.
This commit is contained in:
parent
0253d1675d
commit
fc789d489a
@ -53,7 +53,8 @@ public:
|
||||
|
||||
|
||||
|
||||
/// Write the static eclipse data (grid, PVT curves, etc) to disk.
|
||||
/// Write the static eclipse data (grid, PVT curves, etc) to disk, and set
|
||||
/// up additional initial properties
|
||||
///
|
||||
/// - simProps contains a list of properties which must be
|
||||
/// calculated by the simulator, e.g. the transmissibility
|
||||
@ -61,7 +62,10 @@ public:
|
||||
///
|
||||
/// - The NNC argument is distributed between the EGRID and INIT
|
||||
/// files.
|
||||
void writeInitAndEgrid(data::Solution simProps = data::Solution( ), const NNC& nnc = NNC());
|
||||
///
|
||||
/// If you want FOE in the SUMMARY section, you must pass the initial
|
||||
/// oil-in-place "OIP" key in Solution
|
||||
void writeInitial( data::Solution = data::Solution(), const NNC& = NNC());
|
||||
|
||||
/*!
|
||||
* \brief Write a reservoir state and summary information to disk.
|
||||
|
@ -57,6 +57,8 @@ class Summary {
|
||||
const RegionCache& regionCache,
|
||||
const data::Wells&,
|
||||
const data::Solution& );
|
||||
|
||||
void set_initial( const data::Solution& );
|
||||
void write();
|
||||
|
||||
~Summary();
|
||||
@ -69,6 +71,7 @@ class Summary {
|
||||
std::unique_ptr< keyword_handlers > handlers;
|
||||
const ecl_sum_tstep_type* prev_tstep = nullptr;
|
||||
double prev_time_elapsed = 0;
|
||||
double initial_oip = 0.0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -559,7 +559,7 @@ void EclipseWriter::Impl::writeEGRIDFile( const NNC& nnc ) const {
|
||||
}
|
||||
|
||||
|
||||
void EclipseWriter::writeInitAndEgrid(data::Solution simProps, const NNC& nnc) {
|
||||
void EclipseWriter::writeInitial( data::Solution simProps, const NNC& nnc) {
|
||||
if( !this->impl->output_enabled )
|
||||
return;
|
||||
|
||||
@ -574,6 +574,8 @@ void EclipseWriter::writeInitAndEgrid(data::Solution simProps, const NNC& nnc) {
|
||||
if( ioConfig.getWriteEGRIDFile( ) )
|
||||
this->impl->writeEGRIDFile( nnc );
|
||||
}
|
||||
|
||||
this->impl->summary.set_initial( simProps );
|
||||
}
|
||||
|
||||
std::vector< double > serialize_XWEL( const data::Wells& wells,
|
||||
@ -656,7 +658,6 @@ std::vector< int > serialize_IWEL( const data::Wells& wells,
|
||||
return iwel;
|
||||
}
|
||||
|
||||
|
||||
// implementation of the writeTimeStep method
|
||||
void EclipseWriter::writeTimeStep(int report_step,
|
||||
bool isSubstep,
|
||||
|
@ -134,6 +134,10 @@ struct quantity {
|
||||
}
|
||||
};
|
||||
|
||||
quantity operator-( double lhs, const quantity& rhs ) {
|
||||
return { lhs - rhs.value, rhs.unit };
|
||||
}
|
||||
|
||||
/*
|
||||
* All functions must have the same parameters, so they're gathered in a struct
|
||||
* and functions use whatever information they care about.
|
||||
@ -150,6 +154,7 @@ struct fn_args {
|
||||
const data::Solution& state;
|
||||
const out::RegionCache& regionCache;
|
||||
const EclipseGrid& grid;
|
||||
double initial_oip;
|
||||
};
|
||||
|
||||
/* Since there are several enums in opm scattered about more-or-less
|
||||
@ -411,7 +416,10 @@ quantity foip( const fn_args& args ) {
|
||||
measure::volume };
|
||||
}
|
||||
|
||||
|
||||
quantity foe( const fn_args& args ) {
|
||||
const quantity val = { foip( args ).value, measure::identity };
|
||||
return (args.initial_oip - val) / args.initial_oip;
|
||||
}
|
||||
|
||||
template< typename F, typename G >
|
||||
auto mul( F f, G g ) -> bin_op< F, G, std::multiplies< quantity > >
|
||||
@ -598,6 +606,7 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
|
||||
{ "FOIP", foip },
|
||||
{ "FGIP", fgip },
|
||||
{ "FOE", foe },
|
||||
|
||||
{ "FWPRH", production_history< Phase::WATER > },
|
||||
{ "FOPRH", production_history< Phase::OIL > },
|
||||
@ -758,7 +767,8 @@ Summary::Summary( const EclipseState& st,
|
||||
{}, // Well results - data::Wells
|
||||
{}, // EclipseState
|
||||
{}, // Region <-> cell mappings.
|
||||
this->grid };
|
||||
this->grid,
|
||||
this->initial_oip };
|
||||
|
||||
const auto val = handle( no_args );
|
||||
const auto* unit = st.getUnits().name( val.unit );
|
||||
@ -787,7 +797,15 @@ void Summary::add_timestep( int report_step,
|
||||
const auto* genkey = smspec_node_get_gen_key1( f.first );
|
||||
|
||||
const auto schedule_wells = find_wells( schedule, f.first, timestep );
|
||||
const auto val = f.second( { schedule_wells, duration, timestep, num, wells , state , regionCache , this->grid} );
|
||||
const auto val = f.second( { schedule_wells,
|
||||
duration,
|
||||
timestep,
|
||||
num,
|
||||
wells,
|
||||
state,
|
||||
regionCache,
|
||||
this->grid,
|
||||
this->initial_oip } );
|
||||
|
||||
const auto unit_applied_val = es.getUnits().from_si( val.unit, val.value );
|
||||
const auto res = smspec_node_is_total( f.first ) && prev_tstep
|
||||
@ -801,6 +819,13 @@ void Summary::add_timestep( int report_step,
|
||||
this->prev_time_elapsed = secs_elapsed;
|
||||
}
|
||||
|
||||
void Summary::set_initial( const data::Solution& sol ) {
|
||||
if( !sol.has( "OIP" ) ) return;
|
||||
|
||||
const auto& cells = sol.at( "OIP" ).data;
|
||||
this->initial_oip = std::accumulate( cells.begin(), cells.end(), 0.0 );
|
||||
}
|
||||
|
||||
void Summary::write() {
|
||||
ecl_sum_fwrite( this->ecl_sum.get() );
|
||||
}
|
||||
|
@ -291,8 +291,8 @@ BOOST_AUTO_TEST_CASE(EclipseWriterIntegration) {
|
||||
};
|
||||
|
||||
|
||||
eclWriter.writeInitAndEgrid( );
|
||||
eclWriter.writeInitAndEgrid( eGridProps );
|
||||
eclWriter.writeInitial( );
|
||||
eclWriter.writeInitial( eGridProps );
|
||||
|
||||
data::Wells wells;
|
||||
|
||||
|
@ -602,6 +602,32 @@ BOOST_AUTO_TEST_CASE(field_keywords) {
|
||||
UnitSystem units( UnitSystem::UnitType::UNIT_TYPE_METRIC );
|
||||
const double fpr = units.from_si( UnitSystem::measure::pressure, 5.5 );
|
||||
BOOST_CHECK_CLOSE( fpr, ecl_sum_get_field_var( resp, 1, "FPR" ), 1e-5 );
|
||||
|
||||
/* in this test, the initial OIP wasn't set */
|
||||
BOOST_CHECK_EQUAL( 0.0, ecl_sum_get_field_var( resp, 1, "FOE" ) );
|
||||
BOOST_CHECK_EQUAL( 0.0, ecl_sum_get_field_var( resp, 2, "FOE" ) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(foe_test) {
|
||||
setup cfg( "foe" );
|
||||
|
||||
std::vector< double > oip( cfg.grid.getCartesianSize(), 12.0 );
|
||||
data::Solution sol;
|
||||
sol.insert( "OIP", UnitSystem::measure::volume, oip, data::TargetType::RESTART_AUXILLARY );
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.name );
|
||||
writer.set_initial( sol );
|
||||
writer.add_timestep( 1, 2 * day, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
|
||||
writer.add_timestep( 1, 5 * day, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
|
||||
writer.add_timestep( 2, 10 * day, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
|
||||
writer.write();
|
||||
|
||||
auto res = readsum( cfg.name );
|
||||
const auto* resp = res.get();
|
||||
|
||||
const double foe = (12000.0 - 11000.0) / 12000.0;
|
||||
BOOST_CHECK_CLOSE( foe, ecl_sum_get_field_var( resp, 1, "FOE" ), 1e-5 );
|
||||
BOOST_CHECK_CLOSE( foe, ecl_sum_get_field_var( resp, 2, "FOE" ), 1e-5 );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(report_steps_time) {
|
||||
|
Loading…
Reference in New Issue
Block a user