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:
commit
05c904a04e
@ -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
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user