Merge pull request #51 from joakim-hove/rename-writeInit
Rename write init
This commit is contained in:
commit
e40e731b2c
@ -23,12 +23,21 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class SimulationDataContainer;
|
||||
|
||||
namespace data {
|
||||
|
||||
struct CellData {
|
||||
std::string name;
|
||||
UnitSystem::measure dim;
|
||||
std::vector<double> data;
|
||||
};
|
||||
|
||||
|
||||
struct Solution {
|
||||
/* data::Solution supports writing only some information,
|
||||
* distinguished by keys. When adding support for more values in
|
||||
|
@ -48,15 +48,19 @@ public:
|
||||
*/
|
||||
EclipseWriter(std::shared_ptr< const EclipseState >,
|
||||
int numCells,
|
||||
const int* compressedToCartesianCellIdx,
|
||||
const NNC& );
|
||||
const int* compressedToCartesianCellIdx);
|
||||
|
||||
/**
|
||||
* Write the static eclipse data (grid, PVT curves, etc) to disk.
|
||||
*
|
||||
* If NNC is given to the constructor, writes TRANNNC keyword.
|
||||
*/
|
||||
void writeInit();
|
||||
|
||||
|
||||
/// Write the static eclipse data (grid, PVT curves, etc) to disk.
|
||||
///
|
||||
/// - simProps contains a list of properties which must be
|
||||
/// 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.
|
||||
@ -79,6 +83,9 @@ public:
|
||||
~EclipseWriter();
|
||||
|
||||
private:
|
||||
void writeINITFile(const std::vector<data::CellData>& simProps, const NNC& nnc) const;
|
||||
void writeEGRIDFile( const NNC& nnc) const;
|
||||
|
||||
class Impl;
|
||||
std::unique_ptr< Impl > impl;
|
||||
|
||||
|
@ -59,23 +59,22 @@ namespace {
|
||||
|
||||
// throw away the data for all non-active cells and reorder to the Cartesian logic of
|
||||
// eclipse
|
||||
void restrictAndReorderToActiveCells(std::vector<double> &data,
|
||||
std::vector<double> restrictAndReorderToActiveCells(const std::vector<double> &flow_data,
|
||||
int numCells,
|
||||
const int* compressedToCartesianCellIdx)
|
||||
{
|
||||
if (!compressedToCartesianCellIdx)
|
||||
// if there is no active -> global mapping, all cells
|
||||
// are considered active
|
||||
return;
|
||||
|
||||
std::vector<double> eclData;
|
||||
eclData.reserve( numCells );
|
||||
eclData.resize( numCells );
|
||||
|
||||
if (!compressedToCartesianCellIdx || (flow_data.size() == static_cast<size_t>(numCells)))
|
||||
std::copy( flow_data.begin() , flow_data.end() , eclData.begin() );
|
||||
else {
|
||||
// activate those cells that are actually there
|
||||
for (int i = 0; i < numCells; ++i) {
|
||||
eclData.push_back( data[ compressedToCartesianCellIdx[i] ] );
|
||||
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,
|
||||
@ -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.
|
||||
*/
|
||||
@ -117,13 +130,29 @@ public:
|
||||
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:
|
||||
using fd = std::unique_ptr< char, decltype( std::free )* >;
|
||||
fd filename;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Restart {
|
||||
public:
|
||||
static const int NIWELZ = 11; //Number of data elements per well in IWEL array in restart file
|
||||
@ -160,8 +189,8 @@ public:
|
||||
ioConfig.getFMTOUT() ),
|
||||
rst_file(
|
||||
( writeStepIdx > 0 && ioConfig.getUNIFOUT() )
|
||||
? ecl_rst_file_open_append( filename.ertHandle() )
|
||||
: ecl_rst_file_open_write( filename.ertHandle() ) )
|
||||
? ecl_rst_file_open_append( filename.get() )
|
||||
: ecl_rst_file_open_write( filename.get() ) )
|
||||
{}
|
||||
|
||||
template< typename T >
|
||||
@ -248,72 +277,6 @@ private:
|
||||
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;
|
||||
|
||||
@ -355,7 +318,7 @@ RFT::RFT( const char* output_dir,
|
||||
size_t cart_size ) :
|
||||
global_to_active( cart_size, inactive_index ),
|
||||
fortio(
|
||||
FileName( output_dir, basename, ECL_RFT_FILE, format, 0 ).ertHandle(),
|
||||
FileName( output_dir, basename, ECL_RFT_FILE, format ).get(),
|
||||
std::ios_base::out
|
||||
)
|
||||
{
|
||||
@ -439,12 +402,10 @@ class EclipseWriter::Impl {
|
||||
public:
|
||||
Impl( std::shared_ptr< const EclipseState > es,
|
||||
int numCells,
|
||||
const int* comp_to_cart,
|
||||
const NNC& );
|
||||
const int* comp_to_cart);
|
||||
|
||||
std::shared_ptr< const EclipseState > es;
|
||||
EclipseGrid grid;
|
||||
const NNC& nnc;
|
||||
std::string outputDir;
|
||||
std::string baseName;
|
||||
out::Summary summary;
|
||||
@ -453,18 +414,16 @@ class EclipseWriter::Impl {
|
||||
int numCells;
|
||||
std::array< int, 3 > cartesianSize;
|
||||
const int* compressed_to_cartesian;
|
||||
std::vector< int > gridToEclipseIdx;
|
||||
std::vector< int > compressedToCartesian;
|
||||
bool output_enabled;
|
||||
int ert_phase_mask;
|
||||
};
|
||||
|
||||
EclipseWriter::Impl::Impl( std::shared_ptr< const EclipseState > eclipseState,
|
||||
int numCellsArg,
|
||||
const int* compressed_to_cart,
|
||||
const NNC& rnnc )
|
||||
const int* compressed_to_cart)
|
||||
: es( eclipseState )
|
||||
, grid( *eclipseState->getInputGrid() )
|
||||
, nnc( rnnc )
|
||||
, outputDir( eclipseState->getIOConfig()->getOutputDir() )
|
||||
, baseName( uppercase( eclipseState->getIOConfig()->getBaseName() ) )
|
||||
, summary( *eclipseState, eclipseState->getSummaryConfig() )
|
||||
@ -475,73 +434,147 @@ EclipseWriter::Impl::Impl( std::shared_ptr< const EclipseState > eclipseState,
|
||||
, sim_start_time( es->getSchedule()->posixStartTime() )
|
||||
, numCells( numCellsArg )
|
||||
, compressed_to_cartesian( compressed_to_cart )
|
||||
, gridToEclipseIdx( numCells, int(-1) )
|
||||
, compressedToCartesian( numCells , int(-1) )
|
||||
, output_enabled( eclipseState->getIOConfig()->getOutputEnabled() )
|
||||
, 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 )
|
||||
return;
|
||||
|
||||
{
|
||||
const auto& es = *this->impl->es;
|
||||
Init fortio( this->impl->outputDir,
|
||||
this->impl->baseName,
|
||||
/*stepIdx=*/0,
|
||||
*es.getIOConfigConst());
|
||||
|
||||
fortio.writeHeader( this->impl->numCells,
|
||||
this->impl->compressed_to_cartesian,
|
||||
this->impl->sim_start_time,
|
||||
es,
|
||||
this->impl->grid,
|
||||
this->impl->ert_phase_mask );
|
||||
|
||||
IOConfigConstPtr ioConfig = es.getIOConfigConst();
|
||||
const auto& props = es.get3DProperties();
|
||||
|
||||
if( !ioConfig->getWriteINITFile() ) return;
|
||||
if( ioConfig->getWriteINITFile() )
|
||||
writeINITFile( simProps , nnc );
|
||||
|
||||
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( ioConfig->getWriteEGRIDFile( ) )
|
||||
writeEGRIDFile( nnc );
|
||||
}
|
||||
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
|
||||
void EclipseWriter::writeTimeStep(int report_step,
|
||||
double secs_elapsed,
|
||||
@ -556,34 +589,29 @@ void EclipseWriter::writeTimeStep(int report_step,
|
||||
using dc = data::Solution::key;
|
||||
|
||||
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& grid = this->impl->grid;
|
||||
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();
|
||||
|
||||
|
||||
const auto days = units.from_si( UnitSystem::measure::time, secs_elapsed );
|
||||
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
|
||||
if(!isSubstep && ioConfig->getWriteRestartFile(report_step))
|
||||
{
|
||||
@ -648,26 +676,35 @@ void EclipseWriter::writeTimeStep(int report_step,
|
||||
restartHandle.add_kw( ERT::EclKW< int >( ICON_KW, icon_data ) );
|
||||
|
||||
|
||||
/*
|
||||
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:
|
||||
|
||||
1. All the cells[ ] vectors have size equal to the number
|
||||
of active cells, and they are already in eclipse
|
||||
ordering.
|
||||
|
||||
2. No unit transformatio applied to the saturation and
|
||||
RS/RV vectors.
|
||||
|
||||
*/
|
||||
{
|
||||
Solution sol(restartHandle);
|
||||
sol.add( ERT::EclKW<float>("PRESSURE", pressure) );
|
||||
|
||||
sol.add( ERT::EclKW<float>("PRESSURE", cells[ dc::PRESSURE ]));
|
||||
|
||||
// write the cell temperature
|
||||
auto& temperature = cells[ dc::TEMP ];
|
||||
convertFromSiTo( temperature,
|
||||
units,
|
||||
UnitSystem::measure::temperature );
|
||||
sol.add( ERT::EclKW<float>("TEMP", temperature) );
|
||||
if ( cells.has( dc::TEMP ))
|
||||
sol.add( ERT::EclKW<float>("TEMP", cells[ dc::TEMP ]) );
|
||||
|
||||
|
||||
if( cells.has( dc::SWAT ) ) {
|
||||
if( cells.has( dc::SWAT ) )
|
||||
sol.add( ERT::EclKW<float>( "SWAT", cells[ dc::SWAT ] ) );
|
||||
}
|
||||
|
||||
|
||||
if( cells.has( dc::SGAS ) ) {
|
||||
if( cells.has( dc::SGAS ) )
|
||||
sol.add( ERT::EclKW<float>( "SGAS", cells[ dc::SGAS ] ) );
|
||||
}
|
||||
|
||||
// Write RS - Dissolved GOR
|
||||
if( cells.has( dc::RS ) )
|
||||
@ -677,6 +714,7 @@ void EclipseWriter::writeTimeStep(int report_step,
|
||||
if( cells.has( dc::RV ) )
|
||||
sol.add( ERT::EclKW<float>("RV", cells[ dc::RV ] ) );
|
||||
}
|
||||
}
|
||||
|
||||
const auto unit_type = es.getDeckUnitSystem().getType();
|
||||
this->impl->rft.writeTimeStep( schedule.getWells( report_step ),
|
||||
@ -685,7 +723,7 @@ void EclipseWriter::writeTimeStep(int report_step,
|
||||
current_posix_time,
|
||||
days,
|
||||
to_ert_unit( unit_type ),
|
||||
pressure,
|
||||
cells[ dc::PRESSURE ],
|
||||
cells[ dc::SWAT ],
|
||||
cells[ dc::SGAS ] );
|
||||
|
||||
@ -700,51 +738,29 @@ void EclipseWriter::writeTimeStep(int report_step,
|
||||
|
||||
EclipseWriter::EclipseWriter( std::shared_ptr< const EclipseState > es,
|
||||
int numCells,
|
||||
const int* compressedToCartesianCellIdx,
|
||||
const NNC& nnc ) :
|
||||
impl( new Impl( es, numCells, compressedToCartesianCellIdx, nnc ) )
|
||||
const int* compressedToCartesianCellIdx) :
|
||||
|
||||
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
|
||||
auto& grid = this->impl->grid;
|
||||
{
|
||||
std::vector< int > actnumData( grid.getCartesianSize(), 1 );
|
||||
if ( compressedToCartesianCellIdx ) {
|
||||
actnumData.assign( actnumData.size(), 0 );
|
||||
|
||||
for( int cellIdx = 0; cellIdx < numCells; ++cellIdx )
|
||||
actnumData[ compressedToCartesianCellIdx[ cellIdx ] ] = 1;
|
||||
for( int active_index = 0; active_index < numCells; active_index++ ) {
|
||||
int global_index = compressedToCartesianCellIdx[ active_index ];
|
||||
actnumData[global_index] = 1;
|
||||
this->impl->compressedToCartesian[ active_index ] = global_index;
|
||||
}
|
||||
} else {
|
||||
for( int active_index = 0; active_index < numCells; active_index++ ) {
|
||||
int global_index = active_index;
|
||||
actnumData[global_index] = 1;
|
||||
this->impl->compressedToCartesian[ active_index ] = global_index;
|
||||
}
|
||||
}
|
||||
|
||||
grid.resetACTNUM( &actnumData[0] );
|
||||
|
||||
if( nnc.hasNNC() ) {
|
||||
int idx = 0;
|
||||
// const_cast is safe, since this is a copy of the input grid
|
||||
auto* ecl_grid = const_cast< ecl_grid_type* >( grid.c_ptr() );
|
||||
for( NNCdata n : nnc.nncdata() ) {
|
||||
ecl_grid_add_self_nnc( ecl_grid, n.cell1, n.cell2, idx++);
|
||||
}
|
||||
}
|
||||
|
||||
if( !this->impl->output_enabled ) return;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <opm/output/eclipse/EclipseWriter.hpp>
|
||||
#include <opm/output/Cells.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.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/IOConfig/IOConfig.hpp>
|
||||
#include <opm/parser/eclipse/Units/ConversionFactors.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
|
||||
// ERT stuff
|
||||
#include <ert/ecl/ecl_kw.h>
|
||||
#include <ert/ecl/ecl_endian_flip.h>
|
||||
#include <ert/ecl/fortio.h>
|
||||
#include <ert/util/test_work_area.h>
|
||||
#include <ert/ecl/ecl_file.h>
|
||||
#include <ert/util/ert_unique_ptr.hpp>
|
||||
#include <ert/util/TestArea.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
@ -141,11 +144,12 @@ void checkEgridFile( const EclipseGrid& eclGrid ) {
|
||||
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
|
||||
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));
|
||||
|
||||
if (keywordName == "PORO") {
|
||||
@ -165,11 +169,11 @@ void checkInitFile( const Deck& deck ) {
|
||||
|
||||
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 ) {
|
||||
@ -216,12 +220,8 @@ void checkRestartFile( int timeStepIdx ) {
|
||||
|
||||
BOOST_AUTO_TEST_CASE(EclipseWriterIntegration)
|
||||
{
|
||||
|
||||
test_work_area_type * test_area = test_work_area_alloc("TEST_EclipseWriterIntegration");
|
||||
|
||||
const char *deckString =
|
||||
"RUNSPEC\n"
|
||||
"INIT\n"
|
||||
"UNIFOUT\n"
|
||||
"OIL\n"
|
||||
"GAS\n"
|
||||
@ -230,6 +230,7 @@ BOOST_AUTO_TEST_CASE(EclipseWriterIntegration)
|
||||
"DIMENS\n"
|
||||
"3 3 3/\n"
|
||||
"GRID\n"
|
||||
"INIT\n"
|
||||
"DXV\n"
|
||||
"1.0 2.0 3.0 /\n"
|
||||
"DYV\n"
|
||||
@ -262,11 +263,21 @@ BOOST_AUTO_TEST_CASE(EclipseWriterIntegration)
|
||||
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 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;
|
||||
|
||||
@ -279,10 +290,7 @@ BOOST_AUTO_TEST_CASE(EclipseWriterIntegration)
|
||||
checkRestartFile( i );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
checkInitFile( *deck , simProps);
|
||||
checkEgridFile( eclGrid );
|
||||
checkInitFile( *deck );
|
||||
|
||||
test_work_area_free(test_area);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <ert/ecl/ecl_rft_file.h>
|
||||
#include <ert/util/test_work_area.h>
|
||||
#include <ert/util/util.h>
|
||||
#include <ert/util/TestArea.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -104,10 +105,8 @@ data::Solution createBlackoilState( int timeStepIdx, int numCells ) {
|
||||
BOOST_AUTO_TEST_CASE(test_RFT) {
|
||||
|
||||
std::string eclipse_data_filename = "testRFT.DATA";
|
||||
test_work_area_type * new_ptr = test_work_area_alloc("test_RFT");
|
||||
std::shared_ptr<test_work_area_type> test_area;
|
||||
test_area.reset(new_ptr, test_work_area_free);
|
||||
test_work_area_copy_file(test_area.get(), eclipse_data_filename.c_str());
|
||||
ERT::TestArea test_area("test_RFT");
|
||||
test_area.copyFile( 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.
|
||||
*/
|
||||
|
||||
const auto numCells = eclipseState->getInputGrid()->getNX()
|
||||
* eclipseState->getInputGrid()->getNY()
|
||||
* eclipseState->getInputGrid()->getNZ();
|
||||
const auto numCells = eclipseState->getInputGrid()->getCartesianSize( );
|
||||
|
||||
EclipseWriter eclipseWriter( eclipseState, numCells, nullptr, NNC() );
|
||||
EclipseWriter eclipseWriter( eclipseState, numCells, nullptr );
|
||||
time_t start_time = eclipseState->getSchedule()->posixStartTime();
|
||||
/* step time read from deck and hard-coded here */
|
||||
time_t step_time = util_make_datetime( 0, 0, 0, 10, 10, 2008 );
|
||||
eclipseWriter.writeInit();
|
||||
|
||||
Opm::data::Wells wells {
|
||||
{ { "OP_1", { {}, 1.0, 1.1, {} } },
|
||||
@ -143,7 +139,5 @@ BOOST_AUTO_TEST_CASE(test_RFT) {
|
||||
wells, false);
|
||||
}
|
||||
|
||||
std::string cwd(test_work_area_get_cwd(test_area.get()));
|
||||
std::string rft_filename = cwd + "/TESTRFT.RFT";
|
||||
verifyRFTFile(rft_filename);
|
||||
verifyRFTFile("TESTRFT.RFT");
|
||||
}
|
||||
|
@ -229,10 +229,9 @@ first_sim(test_work_area_type * test_area) {
|
||||
const auto& grid = *eclipseState->getInputGrid();
|
||||
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 first_step = util_make_datetime( 0, 0, 0, 10, 10, 2008 );
|
||||
eclWriter.writeInit();
|
||||
|
||||
auto sol = mkSolution( num_cells );
|
||||
auto wells = mkWells();
|
||||
|
@ -141,9 +141,7 @@ BOOST_AUTO_TEST_CASE(EclipseWriteRestartWellInfo) {
|
||||
auto es = Parser::parse( eclipse_data_filename, ParseContext() );
|
||||
auto eclipseState = std::make_shared< EclipseState >( es );
|
||||
const auto num_cells = eclipseState->getInputGrid()->getCartesianSize();
|
||||
EclipseWriter eclipseWriter( eclipseState, num_cells, nullptr, NNC() );
|
||||
|
||||
eclipseWriter.writeInit();
|
||||
EclipseWriter eclipseWriter( eclipseState, num_cells, nullptr );
|
||||
|
||||
int countTimeStep = eclipseState->getSchedule()->getTimeMap()->numTimesteps();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user