Merge pull request #250 from totto82/MoveWell

Some more cleaning in the output code  in opm-output, ewoms and opm-simulator
This commit is contained in:
Atgeirr Flø Rasmussen 2018-02-19 15:05:24 +01:00 committed by GitHub
commit 05c904a04e
6 changed files with 251 additions and 38 deletions

View File

@ -77,6 +77,11 @@ namespace Opm {
/// true if any option is set; false otherwise
inline bool any() const noexcept;
template <class MessageBufferType>
void write(MessageBufferType& buffer) const;
template <class MessageBufferType>
void read(MessageBufferType& buffer);
private:
double& get_ref( opt );
const double& get_ref( opt ) const;
@ -97,13 +102,21 @@ namespace Opm {
};
struct Completion {
using active_index = size_t;
using global_index = size_t;
static const constexpr int restart_size = 2;
active_index index;
global_index index;
Rates rates;
double pressure;
double reservoir_rate;
double cell_pressure;
double cell_saturation_water;
double cell_saturation_gas;
template <class MessageBufferType>
void write(MessageBufferType& buffer) const;
template <class MessageBufferType>
void read(MessageBufferType& buffer);
};
struct Well {
@ -115,6 +128,10 @@ namespace Opm {
std::vector< Completion > completions;
inline bool flowing() const noexcept;
template <class MessageBufferType>
void write(MessageBufferType& buffer) const;
template <class MessageBufferType>
void read(MessageBufferType& buffer);
};
@ -129,7 +146,7 @@ namespace Opm {
}
double get(const std::string& well_name , Completion::active_index completion_grid_index, Rates::opt m) const {
double get(const std::string& well_name , Completion::global_index completion_grid_index, Rates::opt m) const {
const auto& witr = this->find( well_name );
if( witr == this->end() ) return 0.0;
@ -145,10 +162,36 @@ namespace Opm {
return completion->rates.get( m, 0.0 );
}
template <class MessageBufferType>
void write(MessageBufferType& buffer) const {
unsigned int size = this->size();
buffer.write(size);
for (const auto& witr : *this) {
const std::string& name = witr.first;
buffer.write(name);
const Well& well = witr.second;
well.write(buffer);
}
}
template <class MessageBufferType>
void read(MessageBufferType& buffer) {
unsigned int size;
buffer.read(size);
for (size_t i = 0; i < size; ++i) {
std::string name;
buffer.read(name);
Well well;
well.read(buffer);
this->emplace(name, well);
}
}
};
using Wells = WellRates;
/* IMPLEMENTATIONS */
inline bool Rates::has( opt m ) const {
@ -228,7 +271,91 @@ namespace Opm {
return this->rates.any();
}
template <class MessageBufferType>
void Rates::write(MessageBufferType& buffer) const {
buffer.write(this->mask);
buffer.write(this->wat);
buffer.write(this->oil);
buffer.write(this->gas);
buffer.write(this->polymer);
buffer.write(this->solvent);
buffer.write(this->energy);
buffer.write(this->dissolved_gas);
buffer.write(this->vaporized_oil);
buffer.write(this->reservoir_water);
buffer.write(this->reservoir_oil);
buffer.write(this->reservoir_gas);
}
template <class MessageBufferType>
void Completion::write(MessageBufferType& buffer) const {
buffer.write(this->index);
this->rates.write(buffer);
buffer.write(this->pressure);
buffer.write(this->reservoir_rate);
buffer.write(this->cell_pressure);
buffer.write(this->cell_saturation_water);
buffer.write(this->cell_saturation_gas);
}
template <class MessageBufferType>
void Well::write(MessageBufferType& buffer) const {
this->rates.write(buffer);
buffer.write(this->bhp);
buffer.write(this->thp);
buffer.write(this->temperature);
buffer.write(this->control);
unsigned int size = this->completions.size();
buffer.write(size);
for (const Completion& comp : this->completions)
comp.write(buffer);
}
template <class MessageBufferType>
void Rates::read(MessageBufferType& buffer) {
buffer.read(this->mask);
buffer.read(this->wat);
buffer.read(this->oil);
buffer.read(this->gas);
buffer.read(this->polymer);
buffer.read(this->solvent);
buffer.read(this->energy);
buffer.read(this->dissolved_gas);
buffer.read(this->vaporized_oil);
buffer.read(this->reservoir_water);
buffer.read(this->reservoir_oil);
buffer.read(this->reservoir_gas);
}
template <class MessageBufferType>
void Completion::read(MessageBufferType& buffer) {
buffer.read(this->index);
this->rates.read(buffer);
buffer.read(this->pressure);
buffer.read(this->reservoir_rate);
buffer.read(this->cell_pressure);
buffer.read(this->cell_saturation_water);
buffer.read(this->cell_saturation_gas);
}
template <class MessageBufferType>
void Well::read(MessageBufferType& buffer) {
this->rates.read(buffer);
buffer.read(this->bhp);
buffer.read(this->thp);
buffer.read(this->temperature);
buffer.read(this->control);
unsigned int size = 0.0; //this->completions.size();
buffer.read(size);
this->completions.resize(size);
for (size_t i = 0; i < size; ++i)
{
auto& comp = this->completions[ i ];
comp.read(buffer);
}
}
}
}
#endif //OPM_OUTPUT_WELLS_HPP

View File

@ -108,7 +108,7 @@ class RFT {
time_t current_time,
double days,
const UnitSystem& units,
data::Solution cells);
data::Wells wellData);
private:
std::string filename;
bool fmt_file;
@ -129,11 +129,9 @@ void RFT::writeTimeStep( std::vector< const Well* > wells,
time_t current_time,
double days,
const UnitSystem& units,
data::Solution cells) {
data::Wells wellDatas) {
using rft = ERT::ert_unique_ptr< ecl_rft_node_type, ecl_rft_node_free >;
const std::vector<double>& pressure = cells.data("PRESSURE");
const std::vector<double>& swat = cells.data("SWAT");
const std::vector<double>& sgas = cells.has("SGAS") ? cells.data("SGAS") : std::vector<double>( pressure.size() , 0 );
fortio_type * fortio;
int first_report_step = report_step;
@ -145,7 +143,6 @@ void RFT::writeTimeStep( std::vector< const Well* > wells,
else
fortio = fortio_open_writer( filename.c_str() , fmt_file , ECL_ENDIAN_FLIP );
cells.convertFromSI( units );
for ( const auto& well : wells ) {
if( !( well->getRFTActive( report_step )
|| well->getPLTActive( report_step ) ) )
@ -154,18 +151,32 @@ void RFT::writeTimeStep( std::vector< const Well* > wells,
auto* rft_node = ecl_rft_node_alloc_new( well->name().c_str(), "RFT",
current_time, days );
const auto& wellData = wellDatas.at(well->name());
if (wellData.completions.empty())
continue;
for( const auto& completion : well->getCompletions( report_step ) ) {
const size_t i = size_t( completion.getI() );
const size_t j = size_t( completion.getJ() );
const size_t k = size_t( completion.getK() );
if( !grid.cellActive( i, j, k ) ) continue;
const auto index = grid.activeIndex( i, j, k );
const auto index = grid.getGlobalIndex( i, j, k );
const double depth = grid.getCellDepth( i, j, k );
const double press = pressure[ index ];
const double satwat = swat[ index ];
const double satgas = sgas[ index ];
const auto& completionData = std::find_if( wellData.completions.begin(),
wellData.completions.end(),
[=]( const data::Completion& c ) {
return c.index == index;
} );
const double press = units.from_si(UnitSystem::measure::pressure,completionData->cell_pressure);
const double satwat = units.from_si(UnitSystem::measure::identity, completionData->cell_saturation_water);
const double satgas = units.from_si(UnitSystem::measure::identity, completionData->cell_saturation_gas);
auto* cell = ecl_rft_cell_alloc_RFT(
i, j, k, depth, press, satwat, satgas );
@ -478,7 +489,7 @@ void EclipseIO::writeTimeStep(int report_step,
secs_elapsed + this->impl->schedule.posixStartTime(),
units.from_si( UnitSystem::measure::time, secs_elapsed ),
units,
cells );
wells );
}
}

View File

@ -364,13 +364,13 @@ std::vector< double > serialize_OPM_XWEL( const data::Wells& wells,
std::vector< double > xwel;
for( const auto* sched_well : sched_wells ) {
if( wells.count( sched_well->name() ) == 0 ) {
if( wells.count( sched_well->name() ) == 0 || sched_well->getStatus(report_step) == Opm::WellCommon::SHUT) {
const auto elems = (sched_well->getCompletions( report_step ).size()
* (phases.size() + data::Completion::restart_size))
+ 2 /* bhp, temperature */
+ phases.size();
// write zeros if no well data is provided
// write zeros if no well data is provided or it is shut
xwel.insert( xwel.end(), elems, 0.0 );
continue;
}

View File

@ -225,8 +225,7 @@ inline quantity crate( const fn_args& args ) {
// NUMS array in the eclispe SMSPEC file; the values in this array
// are offset 1 - whereas we need to use this index here to look
// up a completion with offset 0.
const auto global_index = args.num - 1;
const auto active_index = args.grid.activeIndex( global_index );
const size_t global_index = args.num - 1;
if( args.schedule_wells.empty() ) return zero;
const auto& name = args.schedule_wells.front()->name();
@ -236,7 +235,7 @@ inline quantity crate( const fn_args& args ) {
const auto& completion = std::find_if( well.completions.begin(),
well.completions.end(),
[=]( const data::Completion& c ) {
return c.index == active_index;
return c.index == global_index;
} );
if( completion == well.completions.end() ) return zero;

View File

@ -62,21 +62,22 @@ void verifyRFTFile(const std::string& rft_filename) {
const ecl_rft_cell_type * ecl_rft_cell2 = ecl_rft_node_lookup_ijk(ecl_rft_node, 8, 8, 1);
const ecl_rft_cell_type * ecl_rft_cell3 = ecl_rft_node_lookup_ijk(ecl_rft_node, 8, 8, 2);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_pressure(ecl_rft_cell1), 210088*0.00001, 0.00001);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_pressure(ecl_rft_cell2), 210188*0.00001, 0.00001);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_pressure(ecl_rft_cell3), 210288*0.00001, 0.00001);
double tol = 0.00001;
BOOST_CHECK_CLOSE(ecl_rft_cell_get_pressure(ecl_rft_cell1), 0.00000, tol);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_pressure(ecl_rft_cell2), 0.00001, tol);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_pressure(ecl_rft_cell3), 0.00002, tol);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_sgas(ecl_rft_cell1), 0.0);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_sgas(ecl_rft_cell2), 0.0);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_sgas(ecl_rft_cell3), 0.0);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_sgas(ecl_rft_cell1), 0.0, tol);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_sgas(ecl_rft_cell2), 0.2, tol);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_sgas(ecl_rft_cell3), 0.4, tol);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_swat(ecl_rft_cell1), 0.0);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_swat(ecl_rft_cell2), 0.0);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_swat(ecl_rft_cell3), 0.0);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_swat(ecl_rft_cell1), 0.0, tol);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_swat(ecl_rft_cell2), 0.1, tol);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_swat(ecl_rft_cell3), 0.2, tol);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_soil(ecl_rft_cell1), 1.0);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_soil(ecl_rft_cell2), 1.0);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_soil(ecl_rft_cell3), 1.0);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_soil(ecl_rft_cell1), 1.0, tol);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_soil(ecl_rft_cell2), 0.7, tol);
BOOST_CHECK_CLOSE(ecl_rft_cell_get_soil(ecl_rft_cell3), 0.4, tol);
BOOST_CHECK_EQUAL(ecl_rft_cell_get_depth(ecl_rft_cell1), (0.250 + (0.250/2)));
BOOST_CHECK_EQUAL(ecl_rft_cell_get_depth(ecl_rft_cell2), (2*0.250 + (0.250/2)));
@ -132,9 +133,21 @@ BOOST_AUTO_TEST_CASE(test_RFT) {
r2.set( data::Rates::opt::oil, 4.22 );
r2.set( data::Rates::opt::gas, 4.23 );
std::vector<Opm::data::Completion> well1_comps(9);
for (size_t i = 0; i < 9; ++i) {
Opm::data::Completion well_comp { grid.getGlobalIndex(8,8,i) ,r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i};
well1_comps[i] = well_comp;
}
std::vector<Opm::data::Completion> well2_comps(6);
for (size_t i = 0; i < 6; ++i) {
Opm::data::Completion well_comp { grid.getGlobalIndex(3,3,i+3) ,r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2};
well2_comps[i] = well_comp;
}
Opm::data::Wells wells;
wells["OP_1"] = { r1, 1.0, 1.1, 3.1, 1, {} };
wells["OP_2"] = { r2, 1.0, 1.1, 3.2, 1, {} };
wells["OP_1"] = { r1, 1.0, 1.1, 3.1, 1, well1_comps };
wells["OP_2"] = { r2, 1.0, 1.1, 3.2, 1, well2_comps };
eclipseWriter.writeTimeStep( 2,
false,
@ -210,9 +223,20 @@ BOOST_AUTO_TEST_CASE(test_RFT2) {
r2.set( data::Rates::opt::oil, 4.22 );
r2.set( data::Rates::opt::gas, 4.23 );
std::vector<Opm::data::Completion> well1_comps(9);
for (size_t i = 0; i < 9; ++i) {
Opm::data::Completion well_comp { grid.getGlobalIndex(8,8,i) ,r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i};
well1_comps[i] = well_comp;
}
std::vector<Opm::data::Completion> well2_comps(6);
for (size_t i = 0; i < 6; ++i) {
Opm::data::Completion well_comp { grid.getGlobalIndex(3,3,i+3) ,r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2};
well2_comps[i] = well_comp;
}
Opm::data::Wells wells;
wells["OP_1"] = { r1, 1.0, 1.1, 3.1, 1, {} };
wells["OP_2"] = { r2, 1.0, 1.1, 3.2, 1, {} };
wells["OP_1"] = { r1, 1.0, 1.1, 3.1, 1, well1_comps };
wells["OP_2"] = { r2, 1.0, 1.1, 3.2, 1, well2_comps };
eclipseWriter.writeTimeStep( step,
false,

View File

@ -140,8 +140,8 @@ static data::Wells result_wells() {
crates2.set( rt::reservoir_gas, 300.8 / day );
/*
The active index assigned to the completion must be manually
syncronized with the active index in the COMPDAT keyword in the
The global index assigned to the completion must be manually
syncronized with the global index in the COMPDAT keyword in the
input deck.
*/
data::Completion well1_comp1 { 0 , crates1, 1.9 , 123.4};
@ -1098,3 +1098,55 @@ BOOST_AUTO_TEST_CASE(EXTRA) {
/* Override a NOT MISC variable - ignored. */
BOOST_CHECK( ecl_sum_get_general_var( resp , 4 , "FOPR") > 0.0 );
}
struct MessageBuffer
{
std::stringstream str_;
template <class T>
void read( T& value )
{
str_.read( (char *) &value, sizeof(value) );
}
template <class T>
void write( const T& value )
{
str_.write( (char *) &value, sizeof(value) );
}
void write( const std::string& str)
{
int size = str.size();
write(size);
for (int k = 0; k < size; ++k) {
write(str[k]);
}
}
void read( std::string& str)
{
int size = 0;
read(size);
str.resize(size);
for (int k = 0; k < size; ++k) {
read(str[k]);
}
}
};
BOOST_AUTO_TEST_CASE(READ_WRITE_WELLDATA) {
Opm::data::Wells wellRates = result_wells();
MessageBuffer buffer;
wellRates.write(buffer);
Opm::data::Wells wellRatesCopy;
wellRatesCopy.read(buffer);
BOOST_CHECK_CLOSE( wellRatesCopy.get( "W_1" , rt::wat) , wellRates.get( "W_1" , rt::wat), 1e-16);
BOOST_CHECK_CLOSE( wellRatesCopy.get( "W_2" , 101 , rt::wat) , wellRates.get( "W_2" , 101 , rt::wat), 1e-16);
}