Prefer named data members over vectors in OPM_XWEL

Change the structure used to populate OPM_XWEL to use a plain map of
data::Wells objects rather than dumping a series of vectors to
data::Wells. Tests are added for serialising and restoring wells.
This commit is contained in:
Jørgen Kvalsvik 2016-09-25 18:31:34 +02:00
parent 38f9103e43
commit b43461cb49
9 changed files with 334 additions and 168 deletions

View File

@ -83,41 +83,19 @@ namespace Opm {
using active_index = size_t;
active_index index;
Rates rates;
double pressure;
double reservoir_rate;
};
struct Well {
Rates rates;
double bhp;
double thp;
double temperature;
std::map< Completion::active_index, Completion > completions;
};
struct Wells {
using value_type = std::map< std::string, Well >::value_type;
using iterator = std::map< std::string, Well >::iterator;
inline Well& operator[]( const std::string& );
inline Well& at( const std::string& );
inline const Well& at( const std::string& ) const;
template< typename... Args >
inline std::pair< iterator, bool > emplace( Args&&... );
inline Wells() = default;
inline Wells( std::initializer_list< value_type > );
inline Wells( std::initializer_list< value_type >,
std::vector< double > bhp,
std::vector< double > temperature,
std::vector< double > wellrates,
std::vector< double > perf_pressure,
std::vector< double > perf_rates );
std::map< std::string, Well > wells;
std::vector< double > bhp;
std::vector< double > temperature;
std::vector< double > well_rate;
std::vector< double > perf_pressure;
std::vector< double > perf_rate;
};
using Wells = std::map< std::string, Well >;
/* IMPLEMENTATIONS */
@ -183,42 +161,6 @@ namespace Opm {
);
}
inline Well& Wells::operator[]( const std::string& k ) {
return this->wells[ k ];
}
inline Well& Wells::at( const std::string& k ) {
return this->wells.at( k );
}
inline const Well& Wells::at( const std::string& k ) const {
return this->wells.at( k );
}
template< typename... Args >
inline std::pair< Wells::iterator, bool > Wells::emplace( Args&&... args ) {
return this->wells.emplace( std::forward< Args >( args )... );
}
inline Wells::Wells( std::initializer_list< Wells::value_type > l ) :
wells( l )
{}
inline Wells::Wells( std::initializer_list< value_type > l,
std::vector< double > b,
std::vector< double > t,
std::vector< double > w,
std::vector< double > pp,
std::vector< double > pr ) :
wells( l ),
bhp( b ),
temperature( t ),
well_rate( w ),
perf_pressure( pp ),
perf_rate( pr ) {
// TODO: size asserts and sanity checks in debug mode
}
}
}

View File

@ -26,6 +26,8 @@
#include <opm/output/data/Cells.hpp>
#include <opm/output/data/Wells.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/CompletionSet.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
#include <opm/parser/eclipse/EclipseState/InitConfig/InitConfig.hpp>
#include <opm/parser/eclipse/EclipseState/IOConfig/IOConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
@ -33,6 +35,7 @@
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
#include <algorithm>
#include <numeric>
namespace Opm {
namespace {
@ -115,41 +118,64 @@ namespace {
return sol;
}
}
using rt = data::Rates::opt;
data::Wells restoreOPM_XWEL( const double* xwel_data,
size_t xwel_data_size,
int restart_step,
const std::vector< const Well* > sched_wells,
const std::vector< rt >& phases,
const EclipseGrid& grid ) {
const auto well_size = [&]( size_t acc, const Well* w ) {
return acc
+ 2 + phases.size()
+ (w->getCompletions( restart_step )->size() * (phases.size() + 2));
};
inline data::Wells restoreOPM_XWEL( ecl_file_type* file,
int num_wells,
int num_phases ) {
const char* keyword = "OPM_XWEL";
const auto expected_xwel_size = std::accumulate( sched_wells.begin(),
sched_wells.end(),
size_t( 0 ),
well_size );
ecl_kw_type* xwel = ecl_file_iget_named_kw( file, keyword, 0 );
const double* xwel_data = ecl_kw_get_double_ptr(xwel);
const double* xwel_end = xwel_data + ecl_kw_get_size( xwel );
const double* bhp_begin = xwel_data;
const double* bhp_end = bhp_begin + num_wells;
const double* temp_begin = bhp_end;
const double* temp_end = temp_begin + num_wells;
const double* wellrate_begin = temp_end;
const double* wellrate_end = wellrate_begin + (num_wells * num_phases);
const auto remaining = std::distance( wellrate_end, xwel_end );
const auto perf_elems = remaining / 2;
const double* perfpres_begin = wellrate_end;
const double* perfpres_end = perfpres_begin + perf_elems;
const double* perfrate_begin = perfpres_end;
const double* perfrate_end = perfrate_begin + perf_elems;
return { {},
{ bhp_begin, bhp_end },
{ temp_begin, temp_end },
{ wellrate_begin, wellrate_end },
{ perfpres_begin, perfpres_end },
{ perfrate_begin, perfrate_end }
};
if( xwel_data_size != expected_xwel_size ) {
throw std::runtime_error( "Mismatch between OPM_XWEL and deck; "
"too many elements in OPM_XWEL. "
"Was " + std::to_string( xwel_data_size ) +
", expected " + std::to_string( expected_xwel_size ) );
}
data::Wells wells;
for( const auto* sched_well : sched_wells ) {
data::Well& well = wells[ sched_well->name() ];
well.bhp = *xwel_data++;
well.temperature = *xwel_data++;
for( auto phase : phases )
well.rates.set( phase, *xwel_data++ );
auto completions = sched_well->getCompletions( restart_step );
for( const auto& sc : *completions ) {
const auto i = sc->getI(), j = sc->getJ(), k = sc->getK();
if( !grid.cellActive( i, j, k ) ) {
xwel_data += 2 + phases.size();
continue;
}
const auto active_index = grid.activeIndex( i, j, k );
auto& completion = well.completions[ active_index ];
completion.index = active_index;
completion.pressure = *xwel_data++;
completion.reservoir_rate = *xwel_data++;
for( auto phase : phases )
completion.rates.set( phase, *xwel_data++ );
}
}
return wells;
}
std::pair< data::Solution, data::Wells >
@ -166,7 +192,12 @@ init_from_restart_file( const EclipseState& es, int numcells ) {
output);
const bool unified = ioConfig.getUNIFIN();
const int num_wells = es.getSchedule().numWells( restart_step );
const int num_phases = es.getTableManager().getNumPhases();
std::vector< rt > phases;
const auto& tm = es.getTableManager();
if( tm.hasPhase( Phase::PhaseEnum::WATER ) ) phases.push_back( rt::wat );
if( tm.hasPhase( Phase::PhaseEnum::OIL ) ) phases.push_back( rt::oil );
if( tm.hasPhase( Phase::PhaseEnum::GAS ) ) phases.push_back( rt::gas );
using ft = ERT::ert_unique_ptr< ecl_file_type, ecl_file_close >;
ft file( ecl_file_open( filename.c_str(), 0 ) );
@ -181,9 +212,14 @@ init_from_restart_file( const EclipseState& es, int numcells ) {
+ std::to_string( restart_step ) + "!" );
}
const char* keyword = "OPM_XWEL";
ecl_kw_type* xwel = ecl_file_iget_named_kw( file.get(), keyword, 0 );
const double* xwel_data = ecl_kw_get_double_ptr( xwel );
const auto size = ecl_kw_get_size( xwel );
return {
restoreSOLUTION( file.get(), numcells, es.getUnits() ),
restoreOPM_XWEL( file.get(), num_wells, num_phases )
restoreOPM_XWEL( xwel_data, size, restart_step, sched_wells, phases, *es.getInputGrid() )
};
}

View File

@ -575,6 +575,66 @@ void EclipseWriter::writeInitAndEgrid(data::Solution simProps, const NNC& nnc) {
}
}
std::vector< double > serialize_wells( const data::Wells& wells,
int report_step,
const std::vector< const Well* > sched_wells,
const TableManager& tm,
const EclipseGrid& grid ) {
using rt = data::Rates::opt;
std::vector< rt > phases;
if( tm.hasPhase( Phase::PhaseEnum::WATER ) ) phases.push_back( rt::wat );
if( tm.hasPhase( Phase::PhaseEnum::OIL ) ) phases.push_back( rt::oil );
if( tm.hasPhase( Phase::PhaseEnum::GAS ) ) phases.push_back( rt::gas );
std::vector< double > xwel;
for( const auto* sched_well : sched_wells ) {
if( wells.count( sched_well->name() ) == 0 ) {
const auto elems =
sched_well->getCompletions( report_step ).size() * (phases.size() + 2)
+ 2 /* bhp, temperature */
+ phases.size();
// write zeros if no well data is provided
xwel.insert( xwel.end(), elems, 0.0 );
continue;
}
const auto& well = wells.at( sched_well->name() );
xwel.push_back( well.bhp );
xwel.push_back( well.temperature );
for( auto phase : phases )
xwel.push_back( well.rates.get( phase ) );
for( const auto& sc : sched_well->getCompletions( report_step ) ) {
const auto i = sc.getI(), j = sc.getJ(), k = sc.getK();
if( !grid.cellActive( i, j, k ) ) {
xwel.insert( xwel.end(), phases.size() + 2, 0.0 );
continue;
}
const auto active_index = grid.activeIndex( i, j, k );
if( well.completions.count( active_index ) == 0 ) {
xwel.insert( xwel.end(), phases.size() + 2, 0.0 );
continue;
}
const auto& completion = well.completions.at( active_index );
xwel.push_back( completion.pressure );
xwel.push_back( completion.reservoir_rate );
for( auto phase : phases )
xwel.push_back( completion.rates.get( phase ) );
}
}
return xwel;
};
// implementation of the writeTimeStep method
void EclipseWriter::writeTimeStep(int report_step,
@ -659,15 +719,9 @@ void EclipseWriter::writeTimeStep(int report_step,
restartHandle.writeHeader( report_step, &rsthead_data);
}
const auto sz = wells.bhp.size() + wells.perf_pressure.size()
+ wells.perf_rate.size() + wells.temperature.size()
+ wells.well_rate.size();
std::vector< double > xwel;
xwel.reserve( sz );
for( const auto& vec : { wells.bhp, wells.temperature, wells.well_rate,
wells.perf_pressure, wells.perf_rate } )
xwel.insert( xwel.end(), vec.begin(), vec.end() );
const auto& tm = es.getTableManager();
const auto& sched_wells = schedule.getWells( report_step );
const auto xwel = serialize_wells( wells, report_step, sched_wells, tm, grid );
restartHandle.add_kw( ERT::EclKW< int >(IWEL_KW, iwell_data) );
restartHandle.add_kw( ERT::EclKW< const char* >(ZWEL_KW, zwell_data ) );

View File

@ -153,7 +153,7 @@ inline quantity rate( const fn_args& args ) {
for( const auto* sched_well : args.schedule_wells ) {
const auto& name = sched_well->name();
if( args.wells.wells.count( name ) == 0 ) continue;
if( args.wells.count( name ) == 0 ) continue;
const auto v = args.wells.at( name ).rates.get( phase, 0.0 );
if( ( v > 0 ) == injection )
sum += v;
@ -171,7 +171,7 @@ inline quantity crate( const fn_args& args ) {
if( args.schedule_wells.empty() ) return zero;
const auto& name = args.schedule_wells.front()->name();
if( args.wells.wells.count( name ) == 0 ) return zero;
if( args.wells.count( name ) == 0 ) return zero;
const auto& well = args.wells.at( name );
if( well.completions.count( index ) == 0 ) return zero;
@ -198,8 +198,8 @@ inline quantity bhp( const fn_args& args ) {
const quantity zero = { 0, measure::pressure };
if( args.schedule_wells.empty() ) return zero;
const auto p = args.wells.wells.find( args.schedule_wells.front()->name() );
if( p == args.wells.wells.end() ) return zero;
const auto p = args.wells.find( args.schedule_wells.front()->name() );
if( p == args.wells.end() ) return zero;
return { p->second.bhp, measure::pressure };
}
@ -208,8 +208,8 @@ inline quantity thp( const fn_args& args ) {
const quantity zero = { 0, measure::pressure };
if( args.schedule_wells.empty() ) return zero;
const auto p = args.wells.wells.find( args.schedule_wells.front()->name() );
if( p == args.wells.wells.end() ) return zero;
const auto p = args.wells.find( args.schedule_wells.front()->name() );
if( p == args.wells.end() ) return zero;
return { p->second.thp, measure::pressure };
}

View File

@ -355,3 +355,6 @@ BOOST_AUTO_TEST_CASE(EclipseWriterIntegration) {
*/
BOOST_CHECK_EQUAL( file_size, write_and_check( 3, 5 ) );
}
BOOST_AUTO_TEST_CASE(OPM_XWEL) {
}

View File

@ -125,14 +125,18 @@ BOOST_AUTO_TEST_CASE(test_RFT) {
/* step time read from deck and hard-coded here */
time_t step_time = ecl_util_make_date(10, 10, 2008 );
data::Rates r1, r2;
r1.set( data::Rates::opt::wat, 4.11 );
r1.set( data::Rates::opt::oil, 4.12 );
r1.set( data::Rates::opt::gas, 4.13 );
r2.set( data::Rates::opt::wat, 4.21 );
r2.set( data::Rates::opt::oil, 4.22 );
r2.set( data::Rates::opt::gas, 4.23 );
Opm::data::Wells wells {
{ { "OP_1", { {}, 1.0, 1.1, {} } },
{ "OP_2", { {}, 1.0, 1.1, {} } } },
{ 2.1, 2.2 },
{ 3.1, 3.2 },
{ 4.11, 4.12, 4.13, 4.21, 4.22, 4.23 },
{ },
{ }
{ { "OP_1", { r1, 1.0, 1.1, 3.1, {} } },
{ "OP_2", { r2, 1.0, 1.1, 3.2, {} } } },
};
eclipseWriter.writeTimeStep( 2,

View File

@ -49,7 +49,8 @@
using namespace Opm;
std::string input =
inline std::string input( const std::string& rst_name = "FIRST_SIM" ) {
return std::string(
"RUNSPEC\n"
"OIL\n"
"GAS\n"
@ -74,7 +75,8 @@ std::string input =
"SOLUTION\n"
"RESTART\n"
"FIRST_SIM 1/\n"
) + rst_name + std::string(
" 1/\n"
"\n"
"START -- 0 \n"
@ -173,27 +175,151 @@ std::string input =
"/\n"
"TSTEP -- 8\n"
"10 /"
"/\n";
"/\n"
);
}
namespace Opm {
namespace data {
/*
* Some test specific equivalence definitions and pretty-printing. Not fit as a
* general purpose implementation, but does its job for testing and
* pretty-pringing for debugging purposes.
*/
std::ostream& operator<<( std::ostream& stream, const Rates& r ) {
return stream << "{ "
<< "wat: " << r.get( Rates::opt::wat, 0.0 ) << ", "
<< "oil: " << r.get( Rates::opt::oil, 0.0 ) << ", "
<< "gas: " << r.get( Rates::opt::gas, 0.0 ) << " "
<< "}";
}
std::ostream& operator<<( std::ostream& stream, const Completion& c ) {
return stream << "{ index: "
<< c.index << ", "
<< c.rates << ", "
<< c.pressure << " }";
}
std::ostream& operator<<( std::ostream& stream,
const std::map< std::string, Well >& m ) {
stream << "\n";
for( const auto& p : m ) {
stream << p.first << ": \n"
<< "\t" << "bhp: " << p.second.bhp << "\n"
<< "\t" << "temp: " << p.second.temperature << "\n"
<< "\t" << "rates: " << p.second.rates << "\n"
<< "\t" << "completions: [\n";
for( const auto& c : p.second.completions )
stream << c.second << " ";
stream << "]\n";
}
return stream;
}
bool operator==( const Rates& lhs, const Rates& rhs ) {
using rt = Rates::opt;
BOOST_CHECK_EQUAL( lhs.has( rt::wat ), rhs.has( rt::wat ) );
BOOST_CHECK_EQUAL( lhs.has( rt::oil ), rhs.has( rt::oil ) );
BOOST_CHECK_EQUAL( lhs.has( rt::gas ), rhs.has( rt::gas ) );
BOOST_CHECK_EQUAL( lhs.has( rt::polymer ), rhs.has( rt::polymer ) );
BOOST_CHECK_EQUAL( lhs.get( rt::wat, 0.0 ), rhs.get( rt::wat, 0.0 ) );
BOOST_CHECK_EQUAL( lhs.get( rt::oil, 0.0 ), rhs.get( rt::oil, 0.0 ) );
BOOST_CHECK_EQUAL( lhs.get( rt::gas, 0.0 ), rhs.get( rt::gas, 0.0 ) );
BOOST_CHECK_EQUAL( lhs.get( rt::polymer, 0.0 ), rhs.get( rt::polymer, 0.0 ) );
return true;
}
bool operator==( const Completion& lhs, const Completion& rhs ) {
BOOST_CHECK_EQUAL( lhs.index, rhs.index );
BOOST_CHECK_EQUAL( lhs.rates, rhs.rates );
BOOST_CHECK_EQUAL( lhs.pressure, rhs.pressure );
BOOST_CHECK_EQUAL( lhs.reservoir_rate, rhs.reservoir_rate );
return true;
}
bool operator==( const Well& lhs, const Well& rhs ) {
BOOST_CHECK_EQUAL( lhs.rates, rhs.rates );
BOOST_CHECK_EQUAL( lhs.bhp, rhs.bhp );
BOOST_CHECK_EQUAL( lhs.temperature, rhs.temperature );
for( const auto& p : lhs.completions )
BOOST_CHECK_EQUAL( p.second, rhs.completions.at( p.first ) );
return true;
}
}
/*
* forward declarations of internal functions that we want to expose to tests
* but not to users.
*/
std::vector< double > serialize_wells( const data::Wells& wells,
int report_step,
const std::vector< const Well* > sched_wells,
const TableManager& tm,
const EclipseGrid& );
data::Wells restoreOPM_XWEL( const double* xwel_data,
size_t xwel_data_size,
int restart_step,
const std::vector< const Well* > sched_wells,
const std::vector< data::Rates::opt >& phases,
const EclipseGrid& grid );
}
data::Wells mkWells() {
std::vector< double > bhp = { 1.23, 2.34 };
std::vector< double > temp = { 3.45, 4.56 };
std::vector< double > well_rates =
{ 5.67, 6.78, 7.89, 8.90, 9.01, 10.12 };
data::Rates r1, r2, rc1, rc2, rc3;
r1.set( data::Rates::opt::wat, 5.67 );
r1.set( data::Rates::opt::oil, 6.78 );
r1.set( data::Rates::opt::gas, 7.89 );
std::vector< double > perf_press = {
20.41, 21.19, 22.41,
23.19, 24.41, 25.19,
26.41, 27.19, 28.41
};
r2.set( data::Rates::opt::wat, 8.90 );
r2.set( data::Rates::opt::oil, 9.01 );
r2.set( data::Rates::opt::gas, 10.12 );
std::vector< double > perf_rate = {
30.45, 31.19, 32.45,
33.19, 34.45, 35.19,
36.45, 37.19, 38.45,
};
rc1.set( data::Rates::opt::wat, 20.41 );
rc1.set( data::Rates::opt::oil, 21.19 );
rc1.set( data::Rates::opt::gas, 22.41 );
return { {}, bhp, temp, well_rates, perf_press, perf_rate };
rc2.set( data::Rates::opt::wat, 23.19 );
rc2.set( data::Rates::opt::oil, 24.41 );
rc2.set( data::Rates::opt::gas, 25.19 );
rc3.set( data::Rates::opt::wat, 26.41 );
rc3.set( data::Rates::opt::oil, 27.19 );
rc3.set( data::Rates::opt::gas, 28.41 );
data::Well w1, w2;
w1.rates = r1;
w1.bhp = 1.23;
w1.temperature = 3.45;
/*
* the completion keys (active indices) and well names correspond to the
* input deck. All other entries in the well structures are arbitrary.
*/
w1.completions[ 88 ] = { 88, rc1, 30.45 };
w1.completions[ 288 ] = { 288, rc2, 33.19 };
w2.rates = r2;
w2.bhp = 2.34;
w2.temperature = 4.56;
w2.completions[ 188 ] = { 188, rc3, 36.22 };
return { { "OP_1", w1 },
{ "OP_2", w2 } };
}
data::Solution mkSolution( int numCells ) {
@ -250,7 +376,7 @@ first_sim(test_work_area_type * test_area) {
}
std::pair< data::Solution, data::Wells > second_sim() {
auto eclipseState = Parser::parseData( input );
auto eclipseState = Parser::parseData( input() );
const auto& grid = eclipseState.getInputGrid();
auto num_cells = grid.getNX() * grid.getNY() * grid.getNZ();
@ -271,26 +397,7 @@ void compare( std::pair< data::Solution, data::Wells > fst,
BOOST_CHECK_CLOSE( *first, *second, 0.00001 );
}
BOOST_CHECK_EQUAL_COLLECTIONS(
fst.second.bhp.begin(), fst.second.bhp.end(),
snd.second.bhp.begin(), snd.second.bhp.end()
);
BOOST_CHECK_EQUAL_COLLECTIONS(
fst.second.temperature.begin(), fst.second.temperature.end(),
snd.second.temperature.begin(), snd.second.temperature.end()
);
BOOST_CHECK_EQUAL_COLLECTIONS(
fst.second.well_rate.begin(), fst.second.well_rate.end(),
snd.second.well_rate.begin(), snd.second.well_rate.end()
);
BOOST_CHECK_EQUAL_COLLECTIONS(
fst.second.perf_pressure.begin(), fst.second.perf_pressure.end(),
snd.second.perf_pressure.begin(), snd.second.perf_pressure.end()
);
BOOST_CHECK_EQUAL_COLLECTIONS(
fst.second.perf_rate.begin(), fst.second.perf_rate.end(),
snd.second.perf_rate.begin(), snd.second.perf_rate.end()
);
BOOST_CHECK_EQUAL( fst.second, snd.second );
}
BOOST_AUTO_TEST_CASE(EclipseReadWriteWellStateData) {
@ -302,3 +409,29 @@ BOOST_AUTO_TEST_CASE(EclipseReadWriteWellStateData) {
test_work_area_free(test_area);
}
BOOST_AUTO_TEST_CASE(OPM_XWEL) {
auto es = Parser::parseData( input( "XWEL" ) );
const auto& sched = es.getSchedule();
const auto& grid = es.getInputGrid();
const auto& tm = es.getTableManager();
std::vector< data::Rates::opt > phases {
data::Rates::opt::wat,
data::Rates::opt::oil,
data::Rates::opt::gas,
};
const auto wells = mkWells();
const auto& sched_wells = sched.getWells( 1 );
const auto xwel = serialize_wells( wells, 1, sched_wells, tm, grid );
const auto restored_wells = restoreOPM_XWEL( xwel.data(),
xwel.size(),
1,
sched.getWells( 1 ),
phases,
grid );
BOOST_CHECK_EQUAL( wells, restored_wells );
}

View File

@ -139,13 +139,13 @@ static data::Wells result_wells() {
crates3.set( rt::gas, 300.2 / day );
crates3.set( rt::solvent, 300.3 / day );
data::Completion comp1 { 1, crates1 };
data::Completion comp2 { 1, crates2 };
data::Completion comp3 { 3, crates3 };
data::Completion comp1 { 1, crates1, 1.9 };
data::Completion comp2 { 1, crates2, 1.10 };
data::Completion comp3 { 3, crates3, 1.11 };
data::Well well1 { rates1, 0.1 * ps, 0.2 * ps, { {1, comp1} } };
data::Well well2 { rates2, 1.1 * ps, 1.2 * ps, { {1, comp2} } };
data::Well well3 { rates3, 2.1 * ps, 2.2 * ps, { {3, comp3} } };
data::Well well1 { rates1, 0.1 * ps, 0.2 * ps, 0.3 * ps, { {1, comp1} } };
data::Well well2 { rates2, 1.1 * ps, 1.2 * ps, 1.3 * ps, { {1, comp2} } };
data::Well well3 { rates3, 2.1 * ps, 2.2 * ps, 2.3 * ps, { {3, comp3} } };
return { { "W_1", well1 }, { "W_2", well2 }, { "W_3", well3 } };
}

View File

@ -148,13 +148,7 @@ BOOST_AUTO_TEST_CASE(EclipseWriteRestartWellInfo) {
solution.insert( "PRESSURE",UnitSystem::measure::pressure , std::vector< double >( num_cells, 1 ) , data::TargetType::RESTART_SOLUTION);
solution.insert( "SWAT" ,UnitSystem::measure::identity , std::vector< double >( num_cells, 1 ) , data::TargetType::RESTART_SOLUTION);
solution.insert( "SGAS" ,UnitSystem::measure::identity , std::vector< double >( num_cells, 1 ) , data::TargetType::RESTART_SOLUTION);
data::Wells wells { {},
{ 1.1, 1.2, 1.3 },
{ 2.1, 2.2, 2.3 },
{ 3.11, 3.12, 3.13, 3.21, 3.22, 3.23, 3.31, 3.32, 3.33 },
{ 4.1, 4.2, 4.3, 4.4 },
{ 4.1, 4.2, 4.3, 4.4 }
};
data::Wells wells;
for(int timestep = 0; timestep <= countTimeStep; ++timestep){
eclipseWriter.writeTimeStep( timestep,