Merge pull request #51 from joakim-hove/rename-writeInit

Rename write init
This commit is contained in:
Joakim Hove 2016-07-01 13:56:47 +02:00 committed by GitHub
commit e40e731b2c
7 changed files with 308 additions and 277 deletions

View File

@ -23,12 +23,21 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
namespace Opm { namespace Opm {
class SimulationDataContainer; class SimulationDataContainer;
namespace data { namespace data {
struct CellData {
std::string name;
UnitSystem::measure dim;
std::vector<double> data;
};
struct Solution { struct Solution {
/* data::Solution supports writing only some information, /* data::Solution supports writing only some information,
* distinguished by keys. When adding support for more values in * distinguished by keys. When adding support for more values in

View File

@ -48,15 +48,19 @@ public:
*/ */
EclipseWriter(std::shared_ptr< const EclipseState >, EclipseWriter(std::shared_ptr< const EclipseState >,
int numCells, int numCells,
const int* compressedToCartesianCellIdx, const int* compressedToCartesianCellIdx);
const NNC& );
/**
* Write the static eclipse data (grid, PVT curves, etc) to disk.
* /// Write the static eclipse data (grid, PVT curves, etc) to disk.
* If NNC is given to the constructor, writes TRANNNC keyword. ///
*/ /// - simProps contains a list of properties which must be
void writeInit(); /// calculated by the simulator, e.g. the transmissibility
/// vectors TRANX, TRANY and TRANZ.
///
/// - The NNC argument is distributed between the EGRID and INIT
/// files.
void writeInitAndEgrid(const std::vector<data::CellData>& simProps = {}, const NNC& nnc = NNC());
/*! /*!
* \brief Write a reservoir state and summary information to disk. * \brief Write a reservoir state and summary information to disk.
@ -79,6 +83,9 @@ public:
~EclipseWriter(); ~EclipseWriter();
private: private:
void writeINITFile(const std::vector<data::CellData>& simProps, const NNC& nnc) const;
void writeEGRIDFile( const NNC& nnc) const;
class Impl; class Impl;
std::unique_ptr< Impl > impl; std::unique_ptr< Impl > impl;

View File

@ -59,23 +59,22 @@ namespace {
// throw away the data for all non-active cells and reorder to the Cartesian logic of // throw away the data for all non-active cells and reorder to the Cartesian logic of
// eclipse // eclipse
void restrictAndReorderToActiveCells(std::vector<double> &data, std::vector<double> restrictAndReorderToActiveCells(const std::vector<double> &flow_data,
int numCells, int numCells,
const int* compressedToCartesianCellIdx) const int* compressedToCartesianCellIdx)
{ {
if (!compressedToCartesianCellIdx)
// if there is no active -> global mapping, all cells
// are considered active
return;
std::vector<double> eclData; std::vector<double> eclData;
eclData.reserve( numCells ); eclData.resize( numCells );
// activate those cells that are actually there if (!compressedToCartesianCellIdx || (flow_data.size() == static_cast<size_t>(numCells)))
for (int i = 0; i < numCells; ++i) { std::copy( flow_data.begin() , flow_data.end() , eclData.begin() );
eclData.push_back( data[ compressedToCartesianCellIdx[i] ] ); else {
// activate those cells that are actually there
for (int i = 0; i < numCells; ++i)
eclData[i] = flow_data[ compressedToCartesianCellIdx[i] ];
} }
data.swap( eclData );
return eclData;
} }
inline void convertFromSiTo( std::vector< double >& siValues, inline void convertFromSiTo( std::vector< double >& siValues,
@ -98,6 +97,20 @@ inline int to_ert_welltype( const Well& well, size_t timestep ) {
} }
} }
/*
This function hardcodes the common assumption that properties which
are stored internally as double values in OPM should be stored as
float values in the ECLIPSE formatted binary files.
*/
void writeKeyword( ERT::FortIO& fortio ,
const std::string& keywordName,
const std::vector<double> &data ) {
ERT::EclKW< float > kw( keywordName, data );
kw.fwrite( fortio );
}
/** /**
* Pointer to memory that holds the name to an Eclipse output file. * Pointer to memory that holds the name to an Eclipse output file.
*/ */
@ -117,13 +130,29 @@ public:
std::free ) std::free )
{} {}
const char* ertHandle() const { return this->filename.get(); } FileName(const std::string& outputDir,
const std::string& baseName,
ecl_file_enum type,
bool formatted ) :
filename( ecl_util_alloc_filename(
outputDir.c_str(),
baseName.c_str(),
type,
formatted,
0 ),
std::free )
{}
const char* get() const { return this->filename.get(); }
private: private:
using fd = std::unique_ptr< char, decltype( std::free )* >; using fd = std::unique_ptr< char, decltype( std::free )* >;
fd filename; fd filename;
}; };
class Restart { class Restart {
public: public:
static const int NIWELZ = 11; //Number of data elements per well in IWEL array in restart file static const int NIWELZ = 11; //Number of data elements per well in IWEL array in restart file
@ -146,7 +175,7 @@ public:
* Observe that all of these values are our "current-best-guess" for how * Observe that all of these values are our "current-best-guess" for how
* many numbers are needed; there might very well be third party * many numbers are needed; there might very well be third party
* applications out there which have a hard expectation for these values. * applications out there which have a hard expectation for these values.
*/ */
Restart(const std::string& outputDir, Restart(const std::string& outputDir,
@ -160,8 +189,8 @@ public:
ioConfig.getFMTOUT() ), ioConfig.getFMTOUT() ),
rst_file( rst_file(
( writeStepIdx > 0 && ioConfig.getUNIFOUT() ) ( writeStepIdx > 0 && ioConfig.getUNIFOUT() )
? ecl_rst_file_open_append( filename.ertHandle() ) ? ecl_rst_file_open_append( filename.get() )
: ecl_rst_file_open_write( filename.ertHandle() ) ) : ecl_rst_file_open_write( filename.get() ) )
{} {}
template< typename T > template< typename T >
@ -248,72 +277,6 @@ private:
Restart& restart; Restart& restart;
}; };
/**
* Initialization file which contains static properties (such as
* porosity and permeability) for the simulation field.
*/
class Init {
public:
Init( const std::string& outputDir,
const std::string& baseName,
int writeStepIdx,
const IOConfig& ioConfig ) :
egrid( outputDir,
baseName,
ECL_EGRID_FILE,
writeStepIdx,
ioConfig.getFMTOUT() ),
init( FileName( outputDir,
baseName,
ECL_INIT_FILE,
writeStepIdx,
ioConfig.getFMTOUT() ).ertHandle(),
std::ios_base::out,
ioConfig.getFMTOUT(),
ECL_ENDIAN_FLIP )
{}
void writeHeader( int numCells,
const int* compressedToCartesianCellIdx,
time_t current_posix_time,
const EclipseState& es,
const EclipseGrid& eclGrid,
int ert_phase_mask )
{
auto dataField = es.get3DProperties().getDoubleGridProperty("PORO").getData();
restrictAndReorderToActiveCells( dataField, numCells, compressedToCartesianCellIdx );
// finally, write the grid to disk
const auto& ioConfig = *es.getIOConfig();
if( ioConfig.getWriteEGRIDFile() ) {
const bool is_metric =
es.getDeckUnitSystem().getType() == UnitSystem::UNIT_TYPE_METRIC;
eclGrid.fwriteEGRID( egrid.ertHandle(), is_metric );
}
if( ioConfig.getWriteINITFile() ) {
ERT::EclKW< float > poro_kw( "PORO", dataField );
ecl_init_file_fwrite_header( this->ertHandle(),
eclGrid.c_ptr(),
poro_kw.get(),
ert_phase_mask,
current_posix_time );
}
}
void writeKeyword( const std::string& keywordName,
const std::vector<double> &data ) {
ERT::EclKW< float > kw( keywordName, data );
ecl_kw_fwrite( kw.get(), this->ertHandle() );
}
fortio_type* ertHandle() { return this->init.get(); }
private:
FileName egrid;
ERT::FortIO init;
};
const int inactive_index = -1; const int inactive_index = -1;
@ -355,7 +318,7 @@ RFT::RFT( const char* output_dir,
size_t cart_size ) : size_t cart_size ) :
global_to_active( cart_size, inactive_index ), global_to_active( cart_size, inactive_index ),
fortio( fortio(
FileName( output_dir, basename, ECL_RFT_FILE, format, 0 ).ertHandle(), FileName( output_dir, basename, ECL_RFT_FILE, format ).get(),
std::ios_base::out std::ios_base::out
) )
{ {
@ -439,12 +402,10 @@ class EclipseWriter::Impl {
public: public:
Impl( std::shared_ptr< const EclipseState > es, Impl( std::shared_ptr< const EclipseState > es,
int numCells, int numCells,
const int* comp_to_cart, const int* comp_to_cart);
const NNC& );
std::shared_ptr< const EclipseState > es; std::shared_ptr< const EclipseState > es;
EclipseGrid grid; EclipseGrid grid;
const NNC& nnc;
std::string outputDir; std::string outputDir;
std::string baseName; std::string baseName;
out::Summary summary; out::Summary summary;
@ -453,18 +414,16 @@ class EclipseWriter::Impl {
int numCells; int numCells;
std::array< int, 3 > cartesianSize; std::array< int, 3 > cartesianSize;
const int* compressed_to_cartesian; const int* compressed_to_cartesian;
std::vector< int > gridToEclipseIdx; std::vector< int > compressedToCartesian;
bool output_enabled; bool output_enabled;
int ert_phase_mask; int ert_phase_mask;
}; };
EclipseWriter::Impl::Impl( std::shared_ptr< const EclipseState > eclipseState, EclipseWriter::Impl::Impl( std::shared_ptr< const EclipseState > eclipseState,
int numCellsArg, int numCellsArg,
const int* compressed_to_cart, const int* compressed_to_cart)
const NNC& rnnc )
: es( eclipseState ) : es( eclipseState )
, grid( *eclipseState->getInputGrid() ) , grid( *eclipseState->getInputGrid() )
, nnc( rnnc )
, outputDir( eclipseState->getIOConfig()->getOutputDir() ) , outputDir( eclipseState->getIOConfig()->getOutputDir() )
, baseName( uppercase( eclipseState->getIOConfig()->getBaseName() ) ) , baseName( uppercase( eclipseState->getIOConfig()->getBaseName() ) )
, summary( *eclipseState, eclipseState->getSummaryConfig() ) , summary( *eclipseState, eclipseState->getSummaryConfig() )
@ -475,73 +434,147 @@ EclipseWriter::Impl::Impl( std::shared_ptr< const EclipseState > eclipseState,
, sim_start_time( es->getSchedule()->posixStartTime() ) , sim_start_time( es->getSchedule()->posixStartTime() )
, numCells( numCellsArg ) , numCells( numCellsArg )
, compressed_to_cartesian( compressed_to_cart ) , compressed_to_cartesian( compressed_to_cart )
, gridToEclipseIdx( numCells, int(-1) ) , compressedToCartesian( numCells , int(-1) )
, output_enabled( eclipseState->getIOConfig()->getOutputEnabled() ) , output_enabled( eclipseState->getIOConfig()->getOutputEnabled() )
, ert_phase_mask( ertPhaseMask( eclipseState->getTableManager() ) ) , ert_phase_mask( ertPhaseMask( eclipseState->getTableManager() ) )
{} {}
void EclipseWriter::writeInit() {
void EclipseWriter::writeINITFile(const std::vector<data::CellData>& simProps, const NNC& nnc) const {
const auto& compressedToCartesian = this->impl->compressedToCartesian;
const auto& es = *this->impl->es;
const auto& units = es.getUnits();
std::shared_ptr<const IOConfig> ioConfig = es.getIOConfigConst();
FileName initFile( this->impl->outputDir,
this->impl->baseName,
ECL_INIT_FILE,
ioConfig->getFMTOUT() );
ERT::FortIO fortio( initFile.get() ,
std::ios_base::out,
ioConfig->getFMTOUT(),
ECL_ENDIAN_FLIP );
// Write INIT header. Observe that the PORV vector is treated
// specially; that is because for this particulat vector we write
// a total of nx*ny*nz values, where the PORV vector has been
// explicitly set to zero for inactive cells. The convention is
// that the active/inactive cell mapping can be inferred by
// reading the PORV vector.
{
const auto& opm_data = es.get3DProperties().getDoubleGridProperty("PORV").getData();
auto ecl_data = opm_data;
for (size_t global_index = 0; global_index < opm_data.size(); global_index++)
if (!this->impl->grid.cellActive( global_index ))
ecl_data[global_index] = 0;
ecl_init_file_fwrite_header( fortio.get(),
this->impl->grid.c_ptr(),
NULL,
this->impl->ert_phase_mask,
this->impl->sim_start_time);
convertFromSiTo( ecl_data,
units,
UnitSystem::measure::volume);
writeKeyword( fortio, "PORV" , ecl_data );
}
// Write properties from the input deck.
{
const auto& properties = es.get3DProperties();
using double_kw = std::pair<std::string, UnitSystem::measure>;
std::vector<double_kw> doubleKeywords = {{"PORO" , UnitSystem::measure::identity },
{"PERMX" , UnitSystem::measure::permeability },
{"PERMY" , UnitSystem::measure::permeability },
{"PERMZ" , UnitSystem::measure::permeability }};
for (const auto& kw_pair : doubleKeywords) {
const auto& opm_data = properties.getDoubleGridProperty(kw_pair.first).getData();
auto ecl_data = restrictAndReorderToActiveCells( opm_data , compressedToCartesian.size(), compressedToCartesian.data());
convertFromSiTo( ecl_data,
units,
kw_pair.second );
writeKeyword( fortio, kw_pair.first, ecl_data );
}
}
// Write properties which have been initialized by the simulator.
{
for (const auto& prop : simProps) {
const auto& opm_data = prop.data;
auto ecl_data = restrictAndReorderToActiveCells( opm_data, compressedToCartesian.size(), compressedToCartesian.data());
convertFromSiTo( ecl_data,
units,
prop.dim );
writeKeyword( fortio, prop.name, ecl_data );
}
}
// Write NNC transmissibilities
{
std::vector<double> tran;
for( const NNCdata& nd : nnc.nncdata() )
tran.push_back( nd.trans );
convertFromSiTo( tran, units, UnitSystem::measure::transmissibility );
writeKeyword( fortio, "TRANNNC" , tran );
}
}
void EclipseWriter::writeEGRIDFile( const NNC& nnc ) const {
const auto& es = *this->impl->es;
const auto& ioConfig = es.getIOConfig();
FileName egridFile( this->impl->outputDir,
this->impl->baseName,
ECL_EGRID_FILE,
ioConfig->getFMTOUT() );
const EclipseGrid& grid = this->impl->grid;
const bool is_metric = es.getDeckUnitSystem().getType() == UnitSystem::UNIT_TYPE_METRIC;
{
int idx = 0;
auto* ecl_grid = const_cast< ecl_grid_type* >( grid.c_ptr() );
for (const NNCdata& n : nnc.nncdata())
ecl_grid_add_self_nnc( ecl_grid, n.cell1, n.cell2, idx++);
}
grid.fwriteEGRID( egridFile.get() , is_metric );
}
void EclipseWriter::writeInitAndEgrid(const std::vector<data::CellData>& simProps, const NNC& nnc) {
if( !this->impl->output_enabled ) if( !this->impl->output_enabled )
return; return;
const auto& es = *this->impl->es; {
Init fortio( this->impl->outputDir, const auto& es = *this->impl->es;
this->impl->baseName, IOConfigConstPtr ioConfig = es.getIOConfigConst();
/*stepIdx=*/0,
*es.getIOConfigConst());
fortio.writeHeader( this->impl->numCells, if( ioConfig->getWriteINITFile() )
this->impl->compressed_to_cartesian, writeINITFile( simProps , nnc );
this->impl->sim_start_time,
es,
this->impl->grid,
this->impl->ert_phase_mask );
IOConfigConstPtr ioConfig = es.getIOConfigConst(); if( ioConfig->getWriteEGRIDFile( ) )
const auto& props = es.get3DProperties(); writeEGRIDFile( nnc );
if( !ioConfig->getWriteINITFile() ) return;
const auto& gridToEclipseIdx = this->impl->gridToEclipseIdx;
const auto& units = es.getUnits();
if (props.hasDeckDoubleGridProperty("PERMX")) {
auto data = props.getDoubleGridProperty("PERMX").getData();
convertFromSiTo( data,
units,
UnitSystem::measure::permeability );
restrictAndReorderToActiveCells(data, gridToEclipseIdx.size(), gridToEclipseIdx.data());
fortio.writeKeyword("PERMX", data);
} }
if (props.hasDeckDoubleGridProperty("PERMY")) {
auto data = props.getDoubleGridProperty("PERMY").getData();
convertFromSiTo( data,
units,
UnitSystem::measure::permeability );
restrictAndReorderToActiveCells(data, gridToEclipseIdx.size(), gridToEclipseIdx.data());
fortio.writeKeyword("PERMY", data);
}
if (props.hasDeckDoubleGridProperty("PERMZ")) {
auto data = props.getDoubleGridProperty("PERMZ").getData();
convertFromSiTo( data,
units,
UnitSystem::measure::permeability );
restrictAndReorderToActiveCells(data, gridToEclipseIdx.size(), gridToEclipseIdx.data());
fortio.writeKeyword("PERMZ", data);
}
if( !this->impl->nnc.hasNNC() ) return;
std::vector<double> tran;
for( NNCdata nd : this->impl->nnc.nncdata() ) {
tran.push_back( nd.trans );
}
convertFromSiTo( tran, units, UnitSystem::measure::transmissibility );
fortio.writeKeyword("TRANNNC", tran);
} }
// implementation of the writeTimeStep method // implementation of the writeTimeStep method
void EclipseWriter::writeTimeStep(int report_step, void EclipseWriter::writeTimeStep(int report_step,
double secs_elapsed, double secs_elapsed,
@ -556,34 +589,29 @@ void EclipseWriter::writeTimeStep(int report_step,
using dc = data::Solution::key; using dc = data::Solution::key;
time_t current_posix_time = this->impl->sim_start_time + secs_elapsed; time_t current_posix_time = this->impl->sim_start_time + secs_elapsed;
const auto& gridToEclipseIdx = this->impl->gridToEclipseIdx;
const auto& es = *this->impl->es; const auto& es = *this->impl->es;
const auto& grid = this->impl->grid; const auto& grid = this->impl->grid;
const auto& units = es.getUnits(); const auto& units = es.getUnits();
auto& pressure = cells[ dc::PRESSURE ];
convertFromSiTo( pressure,
units,
UnitSystem::measure::pressure );
restrictAndReorderToActiveCells(pressure, gridToEclipseIdx.size(), gridToEclipseIdx.data());
if( cells.has( dc::SWAT ) ) {
auto& saturation_water = cells[ dc::SWAT ];
restrictAndReorderToActiveCells(saturation_water, gridToEclipseIdx.size(), gridToEclipseIdx.data());
}
if( cells.has( dc::SGAS ) ) {
auto& saturation_gas = cells[ dc::SGAS ];
restrictAndReorderToActiveCells(saturation_gas, gridToEclipseIdx.size(), gridToEclipseIdx.data());
}
IOConfigConstPtr ioConfig = this->impl->es->getIOConfigConst(); IOConfigConstPtr ioConfig = this->impl->es->getIOConfigConst();
const auto days = units.from_si( UnitSystem::measure::time, secs_elapsed ); const auto days = units.from_si( UnitSystem::measure::time, secs_elapsed );
const auto& schedule = *es.getSchedule(); const auto& schedule = *es.getSchedule();
/*
This routine can optionally write RFT and/or restart file; to
be certain that the data correctly converted to output units
the conversion is done once here - and not closer to the actual
use-site.
*/
convertFromSiTo( cells[ dc::PRESSURE ], units, UnitSystem::measure::pressure );
if ( cells.has( dc::TEMP ))
convertFromSiTo( cells[ dc::TEMP ],
units,
UnitSystem::measure::temperature );
// Write restart file // Write restart file
if(!isSubstep && ioConfig->getWriteRestartFile(report_step)) if(!isSubstep && ioConfig->getWriteRestartFile(report_step))
{ {
@ -648,34 +676,44 @@ void EclipseWriter::writeTimeStep(int report_step,
restartHandle.add_kw( ERT::EclKW< int >( ICON_KW, icon_data ) ); restartHandle.add_kw( ERT::EclKW< int >( ICON_KW, icon_data ) );
Solution sol(restartHandle); /*
sol.add( ERT::EclKW<float>("PRESSURE", pressure) ); The code in the block below is in a state of flux, and not
very well tested. In particular there have been issues with
the mapping between active an inactive cells in the past -
there might be more those.
Currently the code hard-codes the following assumptions:
// write the cell temperature 1. All the cells[ ] vectors have size equal to the number
auto& temperature = cells[ dc::TEMP ]; of active cells, and they are already in eclipse
convertFromSiTo( temperature, ordering.
units,
UnitSystem::measure::temperature );
sol.add( ERT::EclKW<float>("TEMP", temperature) );
2. No unit transformatio applied to the saturation and
RS/RV vectors.
if( cells.has( dc::SWAT ) ) { */
sol.add( ERT::EclKW<float>( "SWAT", cells[ dc::SWAT ] ) ); {
Solution sol(restartHandle);
sol.add( ERT::EclKW<float>("PRESSURE", cells[ dc::PRESSURE ]));
if ( cells.has( dc::TEMP ))
sol.add( ERT::EclKW<float>("TEMP", cells[ dc::TEMP ]) );
if( cells.has( dc::SWAT ) )
sol.add( ERT::EclKW<float>( "SWAT", cells[ dc::SWAT ] ) );
if( cells.has( dc::SGAS ) )
sol.add( ERT::EclKW<float>( "SGAS", cells[ dc::SGAS ] ) );
// Write RS - Dissolved GOR
if( cells.has( dc::RS ) )
sol.add( ERT::EclKW<float>("RS", cells[ dc::RS ] ) );
// Write RV - Volatilized oil/gas ratio
if( cells.has( dc::RV ) )
sol.add( ERT::EclKW<float>("RV", cells[ dc::RV ] ) );
} }
if( cells.has( dc::SGAS ) ) {
sol.add( ERT::EclKW<float>( "SGAS", cells[ dc::SGAS ] ) );
}
// Write RS - Dissolved GOR
if( cells.has( dc::RS ) )
sol.add( ERT::EclKW<float>("RS", cells[ dc::RS ] ) );
// Write RV - Volatilized oil/gas ratio
if( cells.has( dc::RV ) )
sol.add( ERT::EclKW<float>("RV", cells[ dc::RV ] ) );
} }
const auto unit_type = es.getDeckUnitSystem().getType(); const auto unit_type = es.getDeckUnitSystem().getType();
@ -685,7 +723,7 @@ void EclipseWriter::writeTimeStep(int report_step,
current_posix_time, current_posix_time,
days, days,
to_ert_unit( unit_type ), to_ert_unit( unit_type ),
pressure, cells[ dc::PRESSURE ],
cells[ dc::SWAT ], cells[ dc::SWAT ],
cells[ dc::SGAS ] ); cells[ dc::SGAS ] );
@ -700,51 +738,29 @@ void EclipseWriter::writeTimeStep(int report_step,
EclipseWriter::EclipseWriter( std::shared_ptr< const EclipseState > es, EclipseWriter::EclipseWriter( std::shared_ptr< const EclipseState > es,
int numCells, int numCells,
const int* compressedToCartesianCellIdx, const int* compressedToCartesianCellIdx) :
const NNC& nnc ) :
impl( new Impl( es, numCells, compressedToCartesianCellIdx, nnc ) ) impl( new Impl( es, numCells, compressedToCartesianCellIdx) )
{ {
if( compressedToCartesianCellIdx ) {
// if compressedToCartesianCellIdx available then
// compute mapping to eclipse order
std::map< int , int > indexMap;
for (int cellIdx = 0; cellIdx < numCells; ++cellIdx) {
int cartesianCellIdx = compressedToCartesianCellIdx[cellIdx];
indexMap[ cartesianCellIdx ] = cellIdx;
}
int idx = 0;
for( auto it = indexMap.begin(), end = indexMap.end(); it != end; ++it ) {
this->impl->gridToEclipseIdx[ idx++ ] = (*it).second;
}
}
else {
// if not compressedToCartesianCellIdx was given use identity
for (int cellIdx = 0; cellIdx < numCells; ++cellIdx) {
this->impl->gridToEclipseIdx[ cellIdx ] = cellIdx;
}
}
auto& grid = this->impl->grid;
// update the ACTNUM array using the processed cornerpoint grid // update the ACTNUM array using the processed cornerpoint grid
std::vector< int > actnumData( grid.getCartesianSize(), 1 ); auto& grid = this->impl->grid;
if ( compressedToCartesianCellIdx ) { {
actnumData.assign( actnumData.size(), 0 ); std::vector< int > actnumData( grid.getCartesianSize(), 1 );
if ( compressedToCartesianCellIdx ) {
for( int cellIdx = 0; cellIdx < numCells; ++cellIdx ) actnumData.assign( actnumData.size(), 0 );
actnumData[ compressedToCartesianCellIdx[ cellIdx ] ] = 1; for( int active_index = 0; active_index < numCells; active_index++ ) {
} int global_index = compressedToCartesianCellIdx[ active_index ];
actnumData[global_index] = 1;
grid.resetACTNUM( &actnumData[0] ); this->impl->compressedToCartesian[ active_index ] = global_index;
}
if( nnc.hasNNC() ) { } else {
int idx = 0; for( int active_index = 0; active_index < numCells; active_index++ ) {
// const_cast is safe, since this is a copy of the input grid int global_index = active_index;
auto* ecl_grid = const_cast< ecl_grid_type* >( grid.c_ptr() ); actnumData[global_index] = 1;
for( NNCdata n : nnc.nncdata() ) { this->impl->compressedToCartesian[ active_index ] = global_index;
ecl_grid_add_self_nnc( ecl_grid, n.cell1, n.cell2, idx++); }
} }
grid.resetACTNUM( &actnumData[0] );
} }
if( !this->impl->output_enabled ) return; if( !this->impl->output_enabled ) return;

View File

@ -26,6 +26,7 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <opm/output/eclipse/EclipseWriter.hpp> #include <opm/output/eclipse/EclipseWriter.hpp>
#include <opm/output/Cells.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp> #include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp> #include <opm/parser/eclipse/Parser/Parser.hpp>
@ -36,12 +37,14 @@
#include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp> #include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp>
#include <opm/parser/eclipse/EclipseState/IOConfig/IOConfig.hpp> #include <opm/parser/eclipse/EclipseState/IOConfig/IOConfig.hpp>
#include <opm/parser/eclipse/Units/ConversionFactors.hpp> #include <opm/parser/eclipse/Units/ConversionFactors.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
// ERT stuff // ERT stuff
#include <ert/ecl/ecl_kw.h> #include <ert/ecl/ecl_kw.h>
#include <ert/ecl/ecl_endian_flip.h> #include <ert/ecl/ecl_endian_flip.h>
#include <ert/ecl/fortio.h> #include <ert/ecl/ecl_file.h>
#include <ert/util/test_work_area.h> #include <ert/util/ert_unique_ptr.hpp>
#include <ert/util/TestArea.hpp>
#include <memory> #include <memory>
@ -141,11 +144,12 @@ void checkEgridFile( const EclipseGrid& eclGrid ) {
fortio_fclose(egridFile); fortio_fclose(egridFile);
} }
void checkInitFile( const Deck& deck ) { void checkInitFile( const Deck& deck, const std::vector<data::CellData>& simProps) {
// use ERT directly to inspect the INIT file produced by EclipseWriter // use ERT directly to inspect the INIT file produced by EclipseWriter
auto initFile = fortio_open_reader("FOO.INIT", /*isFormated=*/0, ECL_ENDIAN_FLIP); ERT::ert_unique_ptr<ecl_file_type , ecl_file_close> initFile(ecl_file_open( "FOO.INIT" , 0 ));
while( auto* eclKeyword = ecl_kw_fread_alloc(initFile) ) { for (int i=0; i < ecl_file_get_size( initFile.get() ); i++) {
ecl_kw_type * eclKeyword = ecl_file_iget_kw( initFile.get( ) , i );
std::string keywordName(ecl_kw_get_header(eclKeyword)); std::string keywordName(ecl_kw_get_header(eclKeyword));
if (keywordName == "PORO") { if (keywordName == "PORO") {
@ -165,11 +169,11 @@ void checkInitFile( const Deck& deck ) {
compareErtData(sourceData, resultData, 1e-4); compareErtData(sourceData, resultData, 1e-4);
} }
ecl_kw_free(eclKeyword);
} }
fortio_fclose(initFile); for (const auto& prop : simProps) {
BOOST_CHECK( ecl_file_has_kw( initFile.get() , prop.name.c_str()) );
}
} }
void checkRestartFile( int timeStepIdx ) { void checkRestartFile( int timeStepIdx ) {
@ -216,12 +220,8 @@ void checkRestartFile( int timeStepIdx ) {
BOOST_AUTO_TEST_CASE(EclipseWriterIntegration) BOOST_AUTO_TEST_CASE(EclipseWriterIntegration)
{ {
test_work_area_type * test_area = test_work_area_alloc("TEST_EclipseWriterIntegration");
const char *deckString = const char *deckString =
"RUNSPEC\n" "RUNSPEC\n"
"INIT\n"
"UNIFOUT\n" "UNIFOUT\n"
"OIL\n" "OIL\n"
"GAS\n" "GAS\n"
@ -230,6 +230,7 @@ BOOST_AUTO_TEST_CASE(EclipseWriterIntegration)
"DIMENS\n" "DIMENS\n"
"3 3 3/\n" "3 3 3/\n"
"GRID\n" "GRID\n"
"INIT\n"
"DXV\n" "DXV\n"
"1.0 2.0 3.0 /\n" "1.0 2.0 3.0 /\n"
"DYV\n" "DYV\n"
@ -262,27 +263,34 @@ BOOST_AUTO_TEST_CASE(EclipseWriterIntegration)
auto& eclGrid = *es->getInputGrid(); auto& eclGrid = *es->getInputGrid();
{ {
EclipseWriter eclWriter( es, 3 * 3 * 3, nullptr, NNC()); ERT::TestArea ta("test_ecl_writer");
EclipseWriter eclWriter( es, 3 * 3 * 3, nullptr);
auto start_time = util_make_datetime( 0, 0, 0, 10, 10, 2008 ); auto start_time = util_make_datetime( 0, 0, 0, 10, 10, 2008 );
auto first_step = util_make_datetime( 0, 0, 0, 10, 11, 2008 ); auto first_step = util_make_datetime( 0, 0, 0, 10, 11, 2008 );
eclWriter.writeInit(); std::vector<double> tranx(3*3*3);
std::vector<double> trany(3*3*3);
std::vector<double> tranz(3*3*3);
std::vector<data::CellData> simProps{{"TRANX" , UnitSystem::measure::transmissibility, tranx},
{"TRANY" , UnitSystem::measure::transmissibility, trany},
{"TRANZ" , UnitSystem::measure::transmissibility, tranz}};
ta.setStore( true );
eclWriter.writeInitAndEgrid( );
eclWriter.writeInitAndEgrid( simProps );
data::Wells wells; data::Wells wells;
for( int i = 0; i < 5; ++i ) { for( int i = 0; i < 5; ++i ) {
eclWriter.writeTimeStep( i, eclWriter.writeTimeStep( i,
first_step - start_time, first_step - start_time,
createBlackoilState( i, 3 * 3 * 3 ), createBlackoilState( i, 3 * 3 * 3 ),
wells, false); wells, false);
checkRestartFile( i ); checkRestartFile( i );
} }
checkInitFile( *deck , simProps);
checkEgridFile( eclGrid );
} }
checkEgridFile( eclGrid );
checkInitFile( *deck );
test_work_area_free(test_area);
} }

View File

@ -40,6 +40,7 @@
#include <ert/ecl/ecl_rft_file.h> #include <ert/ecl/ecl_rft_file.h>
#include <ert/util/test_work_area.h> #include <ert/util/test_work_area.h>
#include <ert/util/util.h> #include <ert/util/util.h>
#include <ert/util/TestArea.hpp>
#include <vector> #include <vector>
@ -104,10 +105,8 @@ data::Solution createBlackoilState( int timeStepIdx, int numCells ) {
BOOST_AUTO_TEST_CASE(test_RFT) { BOOST_AUTO_TEST_CASE(test_RFT) {
std::string eclipse_data_filename = "testRFT.DATA"; std::string eclipse_data_filename = "testRFT.DATA";
test_work_area_type * new_ptr = test_work_area_alloc("test_RFT"); ERT::TestArea test_area("test_RFT");
std::shared_ptr<test_work_area_type> test_area; test_area.copyFile( eclipse_data_filename );
test_area.reset(new_ptr, test_work_area_free);
test_work_area_copy_file(test_area.get(), eclipse_data_filename.c_str());
auto eclipseState = std::make_shared< EclipseState >( Parser::parse( eclipse_data_filename ) ); auto eclipseState = std::make_shared< EclipseState >( Parser::parse( eclipse_data_filename ) );
{ {
@ -117,15 +116,12 @@ BOOST_AUTO_TEST_CASE(test_RFT) {
* written to disk and flushed. * written to disk and flushed.
*/ */
const auto numCells = eclipseState->getInputGrid()->getNX() const auto numCells = eclipseState->getInputGrid()->getCartesianSize( );
* eclipseState->getInputGrid()->getNY()
* eclipseState->getInputGrid()->getNZ();
EclipseWriter eclipseWriter( eclipseState, numCells, nullptr, NNC() ); EclipseWriter eclipseWriter( eclipseState, numCells, nullptr );
time_t start_time = eclipseState->getSchedule()->posixStartTime(); time_t start_time = eclipseState->getSchedule()->posixStartTime();
/* step time read from deck and hard-coded here */ /* step time read from deck and hard-coded here */
time_t step_time = util_make_datetime( 0, 0, 0, 10, 10, 2008 ); time_t step_time = util_make_datetime( 0, 0, 0, 10, 10, 2008 );
eclipseWriter.writeInit();
Opm::data::Wells wells { Opm::data::Wells wells {
{ { "OP_1", { {}, 1.0, 1.1, {} } }, { { "OP_1", { {}, 1.0, 1.1, {} } },
@ -143,7 +139,5 @@ BOOST_AUTO_TEST_CASE(test_RFT) {
wells, false); wells, false);
} }
std::string cwd(test_work_area_get_cwd(test_area.get())); verifyRFTFile("TESTRFT.RFT");
std::string rft_filename = cwd + "/TESTRFT.RFT";
verifyRFTFile(rft_filename);
} }

View File

@ -229,10 +229,9 @@ first_sim(test_work_area_type * test_area) {
const auto& grid = *eclipseState->getInputGrid(); const auto& grid = *eclipseState->getInputGrid();
auto num_cells = grid.getNX() * grid.getNY() * grid.getNZ(); auto num_cells = grid.getNX() * grid.getNY() * grid.getNZ();
EclipseWriter eclWriter( eclipseState, num_cells, nullptr, NNC() ); EclipseWriter eclWriter( eclipseState, num_cells, nullptr );
auto start_time = util_make_datetime( 0, 0, 0, 1, 11, 1979 ); auto start_time = util_make_datetime( 0, 0, 0, 1, 11, 1979 );
auto first_step = util_make_datetime( 0, 0, 0, 10, 10, 2008 ); auto first_step = util_make_datetime( 0, 0, 0, 10, 10, 2008 );
eclWriter.writeInit();
auto sol = mkSolution( num_cells ); auto sol = mkSolution( num_cells );
auto wells = mkWells(); auto wells = mkWells();

View File

@ -141,9 +141,7 @@ BOOST_AUTO_TEST_CASE(EclipseWriteRestartWellInfo) {
auto es = Parser::parse( eclipse_data_filename, ParseContext() ); auto es = Parser::parse( eclipse_data_filename, ParseContext() );
auto eclipseState = std::make_shared< EclipseState >( es ); auto eclipseState = std::make_shared< EclipseState >( es );
const auto num_cells = eclipseState->getInputGrid()->getCartesianSize(); const auto num_cells = eclipseState->getInputGrid()->getCartesianSize();
EclipseWriter eclipseWriter( eclipseState, num_cells, nullptr, NNC() ); EclipseWriter eclipseWriter( eclipseState, num_cells, nullptr );
eclipseWriter.writeInit();
int countTimeStep = eclipseState->getSchedule()->getTimeMap()->numTimesteps(); int countTimeStep = eclipseState->getSchedule()->getTimeMap()->numTimesteps();