Added functionality to save results in ECLIPSE format from ERT libraries.
This commit is contained in:
parent
e8f1048b46
commit
bb066aa23b
15
Makefile.am
15
Makefile.am
@ -15,7 +15,7 @@ lib_LTLIBRARIES = libopmcore.la
|
||||
# ERT related settings
|
||||
#if HAVE_ERT
|
||||
ERT_LIB_PATH = $(ERT_ROOT)/lib
|
||||
ERT_LIBS = -leclxx -lecl -lgeometry -lutil -lpthread -lz -lgomp
|
||||
ERT_LIBS = -lecl -lgeometry -lutil -lpthread -lz -lgomp
|
||||
ERT_LDFLAGS = -L$(ERT_LIB_PATH) $(ERT_LIBS)
|
||||
ERT_INCLUDE_PATH = $(ERT_ROOT)/include
|
||||
ERT_CPPFLAGS = -I$(ERT_INCLUDE_PATH)
|
||||
@ -68,8 +68,6 @@ opm/core/grid/cornerpoint_grid.c \
|
||||
opm/core/grid/cpgpreprocess/facetopology.c \
|
||||
opm/core/grid/cpgpreprocess/geometry.c \
|
||||
opm/core/grid/cpgpreprocess/preprocess.c \
|
||||
opm/core/grid/cpgpreprocess/readvector.cpp \
|
||||
opm/core/grid/cpgpreprocess/sparsetable.c \
|
||||
opm/core/grid/cpgpreprocess/uniquepoints.c \
|
||||
opm/core/linalg/LinearSolverFactory.cpp \
|
||||
opm/core/linalg/LinearSolverInterface.cpp \
|
||||
@ -171,8 +169,6 @@ opm/core/grid/cpgpreprocess/facetopology.h \
|
||||
opm/core/grid/cpgpreprocess/geometry.h \
|
||||
opm/core/grid/cpgpreprocess/grdecl.h \
|
||||
opm/core/grid/cpgpreprocess/preprocess.h \
|
||||
opm/core/grid/cpgpreprocess/readvector.hpp \
|
||||
opm/core/grid/cpgpreprocess/sparsetable.h \
|
||||
opm/core/grid/cpgpreprocess/uniquepoints.h \
|
||||
opm/core/linalg/LinearSolverFactory.hpp \
|
||||
opm/core/linalg/LinearSolverInterface.hpp \
|
||||
@ -259,6 +255,7 @@ opm/core/utility/parameters/ParameterXML.hpp \
|
||||
opm/core/utility/parameters/tinyxml/tinystr.h \
|
||||
opm/core/utility/parameters/tinyxml/tinyxml.h \
|
||||
opm/core/utility/writeVtkData.hpp \
|
||||
opm/core/utility/DataMap.hpp \
|
||||
opm/core/vag_format/vag.hpp \
|
||||
opm/core/well.h \
|
||||
opm/core/wells/InjectionSpecification.hpp \
|
||||
@ -280,6 +277,14 @@ opm/core/linalg/call_umfpack.h \
|
||||
opm/core/linalg/LinearSolverUmfpack.hpp
|
||||
endif
|
||||
|
||||
if HAVE_ERT
|
||||
libopmcore_la_SOURCES += \
|
||||
opm/core/utility/writeECLData.cpp
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
opm/core/utility/writeECLData.hpp
|
||||
endif
|
||||
|
||||
|
||||
if DUNE_ISTL
|
||||
libopmcore_la_SOURCES += \
|
||||
|
@ -94,14 +94,19 @@
|
||||
#include <numeric>
|
||||
|
||||
|
||||
#ifdef HAVE_ERT
|
||||
#include <opm/core/utility/writeECLData.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static void outputState(const UnstructuredGrid& grid,
|
||||
const Opm::TwophaseState& state,
|
||||
const int step,
|
||||
const Opm::SimulatorTimer& simtimer,
|
||||
const std::string& output_dir)
|
||||
{
|
||||
// Write data in VTK format.
|
||||
int step = simtimer.currentStepNum();
|
||||
std::ostringstream vtkfilename;
|
||||
vtkfilename << output_dir << "/output-" << std::setw(3) << std::setfill('0') << step << ".vtu";
|
||||
std::ofstream vtkfile(vtkfilename.str().c_str());
|
||||
@ -115,6 +120,9 @@ static void outputState(const UnstructuredGrid& grid,
|
||||
Opm::estimateCellVelocity(grid, state.faceflux(), cell_velocity);
|
||||
dm["velocity"] = &cell_velocity;
|
||||
Opm::writeVtkData(grid, dm, vtkfile);
|
||||
#ifdef HAVE_ERT
|
||||
Opm::writeECLData(grid , dm , simtimer , output_dir , "OPM" );
|
||||
#endif
|
||||
|
||||
// Write data (not grid) in Matlab format
|
||||
for (Opm::DataMap::const_iterator it = dm.begin(); it != dm.end(); ++it) {
|
||||
@ -532,7 +540,7 @@ main(int argc, char** argv)
|
||||
// Report timestep and (optionally) write state to disk.
|
||||
simtimer.report(std::cout);
|
||||
if (output && (simtimer.currentStepNum() % output_interval == 0)) {
|
||||
outputState(*grid->c_grid(), state, simtimer.currentStepNum(), output_dir);
|
||||
outputState(*grid->c_grid(), state, simtimer , output_dir);
|
||||
}
|
||||
|
||||
// Solve pressure.
|
||||
@ -701,7 +709,7 @@ main(int argc, char** argv)
|
||||
<< "\n Transport time: " << ttime << std::endl;
|
||||
|
||||
if (output) {
|
||||
outputState(*grid->c_grid(), state, simtimer.currentStepNum(), output_dir);
|
||||
outputState(*grid->c_grid(), state, simtimer, output_dir);
|
||||
outputWaterCut(watercut, output_dir);
|
||||
if (wells->c_wells()) {
|
||||
outputWellReport(wellreport, output_dir);
|
||||
|
@ -33,36 +33,14 @@ namespace Opm
|
||||
/// Construct a 3d corner-point grid from a deck.
|
||||
GridManager::GridManager(const Opm::EclipseGridParser& deck)
|
||||
{
|
||||
// Extract data from deck.
|
||||
const std::vector<double>& zcorn = deck.getFloatingPointValue("ZCORN");
|
||||
const std::vector<double>& coord = deck.getFloatingPointValue("COORD");
|
||||
const int* actnum = 0;
|
||||
if (deck.hasField("ACTNUM")) {
|
||||
actnum = &(deck.getIntegerValue("ACTNUM")[0]);
|
||||
}
|
||||
std::vector<int> dims;
|
||||
if (deck.hasField("DIMENS")) {
|
||||
dims = deck.getIntegerValue("DIMENS");
|
||||
} else if (deck.hasField("SPECGRID")) {
|
||||
dims = deck.getSPECGRID().dimensions;
|
||||
} else {
|
||||
THROW("Deck must have either DIMENS or SPECGRID.");
|
||||
}
|
||||
|
||||
// Collect in input struct for preprocessing.
|
||||
struct grdecl grdecl;
|
||||
grdecl.zcorn = &zcorn[0];
|
||||
grdecl.coord = &coord[0];
|
||||
grdecl.actnum = actnum;
|
||||
grdecl.dims[0] = dims[0];
|
||||
grdecl.dims[1] = dims[1];
|
||||
grdecl.dims[2] = dims[2];
|
||||
|
||||
// Process grid.
|
||||
ug_ = create_grid_cornerpoint(&grdecl, 0.0);
|
||||
if (!ug_) {
|
||||
THROW("Failed to construct grid.");
|
||||
}
|
||||
// Collect in input struct for preprocessing.
|
||||
struct grdecl grdecl = deck.get_grdecl();
|
||||
|
||||
// Process grid.
|
||||
ug_ = create_grid_cornerpoint(&grdecl, 0.0);
|
||||
if (!ug_) {
|
||||
THROW("Failed to construct grid.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -71,10 +49,10 @@ namespace Opm
|
||||
/// Construct a 2d cartesian grid with cells of unit size.
|
||||
GridManager::GridManager(int nx, int ny)
|
||||
{
|
||||
ug_ = create_grid_cart2d(nx, ny);
|
||||
if (!ug_) {
|
||||
THROW("Failed to construct grid.");
|
||||
}
|
||||
ug_ = create_grid_cart2d(nx, ny);
|
||||
if (!ug_) {
|
||||
THROW("Failed to construct grid.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -83,10 +61,10 @@ namespace Opm
|
||||
/// Construct a 3d cartesian grid with cells of unit size.
|
||||
GridManager::GridManager(int nx, int ny, int nz)
|
||||
{
|
||||
ug_ = create_grid_cart3d(nx, ny, nz);
|
||||
if (!ug_) {
|
||||
THROW("Failed to construct grid.");
|
||||
}
|
||||
ug_ = create_grid_cart3d(nx, ny, nz);
|
||||
if (!ug_) {
|
||||
THROW("Failed to construct grid.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -96,10 +74,10 @@ namespace Opm
|
||||
GridManager::GridManager(int nx, int ny, int nz,
|
||||
double dx, double dy, double dz)
|
||||
{
|
||||
ug_ = create_grid_hexa3d(nx, ny, nz, dx, dy, dz);
|
||||
if (!ug_) {
|
||||
THROW("Failed to construct grid.");
|
||||
}
|
||||
ug_ = create_grid_hexa3d(nx, ny, nz, dx, dy, dz);
|
||||
if (!ug_) {
|
||||
THROW("Failed to construct grid.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -108,7 +86,7 @@ namespace Opm
|
||||
/// Destructor.
|
||||
GridManager::~GridManager()
|
||||
{
|
||||
destroy_grid(ug_);
|
||||
destroy_grid(ug_);
|
||||
}
|
||||
|
||||
|
||||
@ -119,7 +97,7 @@ namespace Opm
|
||||
/// to make it clear that we are returning a C-compatible struct.
|
||||
const UnstructuredGrid* GridManager::c_grid() const
|
||||
{
|
||||
return ug_;
|
||||
return ug_;
|
||||
}
|
||||
|
||||
|
||||
|
@ -47,8 +47,18 @@
|
||||
#include <opm/core/eclipse/EclipseGridParserHelpers.hpp>
|
||||
#include <opm/core/eclipse/SpecialEclipseFields.hpp>
|
||||
#include <opm/core/utility/ErrorMacros.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <opm/core/utility/Units.hpp>
|
||||
#include <opm/core/grid/cpgpreprocess/preprocess.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#ifdef HAVE_ERT
|
||||
#include <fortio.h>
|
||||
#include <ecl_grid.h>
|
||||
#include <ecl_kw_magic.h>
|
||||
#include <ecl_kw.h>
|
||||
#include <ecl_util.h>
|
||||
#include <ecl_init_file.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -86,7 +96,7 @@ namespace EclipseKeywords
|
||||
string("MULTPV"), string("PRESSURE"), string("SGAS"),
|
||||
string("SWAT"), string("SOIL"), string("RS"),
|
||||
string("DXV"), string("DYV"), string("DZV"),
|
||||
string("DEPTHZ")
|
||||
string("DEPTHZ"), string("MAPAXES")
|
||||
};
|
||||
const int num_floating_fields = sizeof(floating_fields) / sizeof(floating_fields[0]);
|
||||
|
||||
@ -114,7 +124,7 @@ namespace EclipseKeywords
|
||||
const int num_special_fields = sizeof(special_fields) / sizeof(special_fields[0]);
|
||||
|
||||
string ignore_with_data[] =
|
||||
{ string("MAPUNITS"), string("MAPAXES"), string("GRIDUNIT"),
|
||||
{ string("MAPUNITS"), string("GRIDUNIT"),
|
||||
string("NTG"), string("REGDIMS"), string("WELLDIMS"),
|
||||
string("NSTACK"), string("SATNUM"),
|
||||
string("RPTRST"), string("ROIP"), string("RWIP"),
|
||||
@ -814,5 +824,248 @@ void EclipseGridParser::computeUnits()
|
||||
THROW("Unknown unit family " << unit_family);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct grdecl EclipseGridParser::get_grdecl() const {
|
||||
struct grdecl grdecl;
|
||||
|
||||
// Extract data from deck.
|
||||
const std::vector<double>& zcorn = getFloatingPointValue("ZCORN");
|
||||
const std::vector<double>& coord = getFloatingPointValue("COORD");
|
||||
const int* actnum = NULL;
|
||||
if (hasField("ACTNUM")) {
|
||||
actnum = &(getIntegerValue("ACTNUM")[0]);
|
||||
}
|
||||
|
||||
std::vector<int> dims;
|
||||
if (hasField("DIMENS")) {
|
||||
dims = getIntegerValue("DIMENS");
|
||||
} else if (hasField("SPECGRID")) {
|
||||
dims = getSPECGRID().dimensions;
|
||||
} else {
|
||||
THROW("Deck must have either DIMENS or SPECGRID.");
|
||||
}
|
||||
|
||||
// Collect in input struct for preprocessing.
|
||||
|
||||
grdecl.zcorn = &zcorn[0];
|
||||
grdecl.coord = &coord[0];
|
||||
grdecl.actnum = actnum;
|
||||
grdecl.dims[0] = dims[0];
|
||||
grdecl.dims[1] = dims[1];
|
||||
grdecl.dims[2] = dims[2];
|
||||
|
||||
if (hasField("MAPAXES")) {
|
||||
const std::vector<double> &mapaxes = getFloatingPointValue("MAPAXES");
|
||||
grdecl.mapaxes = &mapaxes[0];
|
||||
} else
|
||||
grdecl.mapaxes = NULL;
|
||||
|
||||
|
||||
return grdecl;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ERT
|
||||
/*
|
||||
This function will create a ecl_kw instance filled with the data
|
||||
from input argument @keyword. The ecl_kw will get it's own copy of
|
||||
the data.
|
||||
|
||||
If the input type ecl_type == ECL_INT_TYPE the function will use the
|
||||
getIntegerValue() method to get the keyword data, if ecl_type ==
|
||||
ECL_DOUBLE_TYPE || ECL_FLOAT_TYPE the getFloatingPointValue()
|
||||
function is invoked. If ecl_type == ECL_FLOAT_TYPE the data will be
|
||||
converted to when inserting into the ecl_kw.
|
||||
|
||||
When the ecl_kw instance is no longer needed it should be discarded
|
||||
with a call to ecl_kw_free( ).
|
||||
|
||||
If you are asking for a non-existent field the function will return NULL
|
||||
*/
|
||||
|
||||
ecl_kw_type * EclipseGridParser::newEclKW(const std::string &keyword , ecl_type_enum ecl_type) const {
|
||||
ecl_kw_type * ecl_kw = NULL;
|
||||
if (hasField(keyword)) {
|
||||
if (ecl_type == ECL_INT_TYPE) {
|
||||
std::vector<int> data = getIntegerValue( keyword );
|
||||
ecl_kw = ecl_kw_alloc( keyword.c_str() , data.size() , ecl_type );
|
||||
ecl_kw_set_memcpy_data( ecl_kw , &data[0]);
|
||||
} else {
|
||||
std::vector<double> data = getFloatingPointValue( keyword );
|
||||
if (ecl_type == ECL_DOUBLE_TYPE) {
|
||||
ecl_kw = ecl_kw_alloc( keyword.c_str() , data.size() , ecl_type );
|
||||
ecl_kw_set_memcpy_data( ecl_kw , &data[0]);
|
||||
} else if (ecl_type == ECL_FLOAT_TYPE) {
|
||||
ecl_kw = ecl_kw_alloc( keyword.c_str() , data.size() , ecl_type );
|
||||
for (int i=0; i < data.size(); i++)
|
||||
ecl_kw_iset_float( ecl_kw , i , data[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
return ecl_kw;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This function will extract the COORD, ZCORN, ACTNUM and optionaly
|
||||
MAPAXES keywords from the eclipse deck and create an ecl_grid
|
||||
instance.
|
||||
|
||||
When you are finished working with the ecl_grid instance it should
|
||||
be disposed with ecl_grid_free( ).
|
||||
*/
|
||||
|
||||
ecl_grid_type * EclipseGridParser::newGrid( ) {
|
||||
struct grdecl grdecl = get_grdecl();
|
||||
ecl_kw_type * coord_kw = newEclKW( COORD_KW , ECL_FLOAT_TYPE );
|
||||
ecl_kw_type * zcorn_kw = newEclKW( ZCORN_KW , ECL_FLOAT_TYPE );
|
||||
ecl_kw_type * actnum_kw = newEclKW( ACTNUM_KW , ECL_INT_TYPE );
|
||||
ecl_kw_type * mapaxes_kw = NULL;
|
||||
|
||||
ecl_grid_type * grid ;
|
||||
if (grdecl.mapaxes != NULL)
|
||||
mapaxes_kw = newEclKW( MAPAXES_KW , ECL_FLOAT_TYPE );
|
||||
|
||||
grid = ecl_grid_alloc_GRDECL_kw( grdecl.dims[0] , grdecl.dims[1] , grdecl.dims[2] , zcorn_kw , coord_kw , actnum_kw , mapaxes_kw );
|
||||
|
||||
ecl_kw_free( coord_kw );
|
||||
ecl_kw_free( zcorn_kw );
|
||||
ecl_kw_free( actnum_kw );
|
||||
if (mapaxes_kw != NULL)
|
||||
ecl_kw_free( mapaxes_kw );
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
This function will save an EGRID file based on the COORD, ZCORN,
|
||||
ACTNUM and optionally MAPAXES keywords included in the deck.
|
||||
|
||||
This function creates the EGRID file without going through a
|
||||
ecl_grid instance; this is obviously somewhat faster and less
|
||||
memory demanding. Alternatively you can create a ecl_grid instance
|
||||
and then subsequently store that grid as an EGRID file:
|
||||
|
||||
{
|
||||
ecl_grid_type * grid = newGRID( );
|
||||
ecl_grid_fwrite_EGRID( grid , filename );
|
||||
ecl_grid_free( grid );
|
||||
}
|
||||
*/
|
||||
|
||||
void EclipseGridParser::saveEGRID( const std::string & filename) {
|
||||
bool endian_flip = true;//ECL_ENDIAN_FLIP;
|
||||
bool fmt_file = ecl_util_fmt_file( filename.c_str() );
|
||||
struct grdecl grdecl = get_grdecl();
|
||||
fortio_type * fortio = fortio_open_writer( filename.c_str() , fmt_file , endian_flip );
|
||||
{
|
||||
float * mapaxes = NULL;
|
||||
if (grdecl.mapaxes != NULL) {
|
||||
mapaxes = new float[6];
|
||||
for (int i=0; i < 6; i++)
|
||||
mapaxes[i]= grdecl.mapaxes[i];
|
||||
}
|
||||
|
||||
ecl_grid_fwrite_EGRID_header( grdecl.dims , mapaxes , fortio );
|
||||
|
||||
if (grdecl.mapaxes != NULL)
|
||||
delete[] mapaxes;
|
||||
}
|
||||
{
|
||||
ecl_kw_type * coord_kw = newEclKW( COORD_KW , ECL_FLOAT_TYPE );
|
||||
ecl_kw_type * zcorn_kw = newEclKW( ZCORN_KW , ECL_FLOAT_TYPE );
|
||||
ecl_kw_type * actnum_kw = newEclKW( ACTNUM_KW , ECL_INT_TYPE );
|
||||
ecl_kw_type * endgrid_kw = ecl_kw_alloc( ENDGRID_KW , 0 , ECL_INT_TYPE );
|
||||
|
||||
ecl_kw_fwrite( coord_kw , fortio );
|
||||
ecl_kw_fwrite( zcorn_kw , fortio );
|
||||
ecl_kw_fwrite( actnum_kw , fortio );
|
||||
ecl_kw_fwrite( endgrid_kw , fortio );
|
||||
|
||||
ecl_kw_free( coord_kw );
|
||||
ecl_kw_free( zcorn_kw );
|
||||
ecl_kw_free( actnum_kw );
|
||||
ecl_kw_free( endgrid_kw );
|
||||
}
|
||||
fortio_fclose( fortio );
|
||||
}
|
||||
|
||||
/**
|
||||
Will query the deck for keyword @kw; and save it to the @fortio
|
||||
instance if the keyword can be found.
|
||||
*/
|
||||
void EclipseGridParser::save_kw( fortio_type * fortio , const std::string & kw , ecl_type_enum ecl_type) {
|
||||
ecl_kw_type * ecl_kw = newEclKW( kw , ecl_type );
|
||||
if (ecl_kw != NULL) {
|
||||
ecl_kw_fwrite( ecl_kw , fortio );
|
||||
ecl_kw_free( ecl_kw );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Will save an ECLIPSE INIT file to @filename. Observe that the main
|
||||
focus of this function is to store grid properties like PERMX and
|
||||
PORO, various tabular properties like e.g. relperm tables and
|
||||
thermodynamic properties are ignored.
|
||||
*/
|
||||
|
||||
void EclipseGridParser::saveINIT( const std::string & filename , const ecl_grid_type * ecl_grid) {
|
||||
int phases = ECL_OIL_PHASE + ECL_WATER_PHASE;
|
||||
bool fmt_file = ecl_util_fmt_file( filename.c_str() );
|
||||
bool endian_flip = true;//ECL_ENDIAN_FLIP;
|
||||
fortio_type * fortio = fortio_open_writer( filename.c_str() , fmt_file , endian_flip );
|
||||
{
|
||||
ecl_kw_type * poro_kw = newEclKW( PORO_KW , ECL_FLOAT_TYPE );
|
||||
time_t start_date;
|
||||
|
||||
{
|
||||
tm td_tm = to_tm( start_date_ );
|
||||
start_date = mktime( &td_tm );
|
||||
}
|
||||
|
||||
ecl_init_file_fwrite_header( fortio , ecl_grid , poro_kw , phases , start_date );
|
||||
ecl_kw_free( poro_kw );
|
||||
}
|
||||
|
||||
/* This collection of keywords is somewhat arbitrary and random. */
|
||||
save_kw( fortio , "PERMX" , ECL_FLOAT_TYPE);
|
||||
save_kw( fortio , "PERMY" , ECL_FLOAT_TYPE);
|
||||
save_kw( fortio , "PERMZ" , ECL_FLOAT_TYPE);
|
||||
|
||||
save_kw( fortio , "FIPNUM" , ECL_INT_TYPE);
|
||||
save_kw( fortio , "SATNUM" , ECL_INT_TYPE);
|
||||
save_kw( fortio , "EQLNUM" , ECL_INT_TYPE);
|
||||
|
||||
fortio_fclose( fortio );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This is the main function used to save the state of the ECLIPSE
|
||||
deck in ECLIPSE format. The function will save an INIT file and an
|
||||
EGRID file.
|
||||
|
||||
The input arguments are the output directory to store files in, and
|
||||
the basename to use for the files; the function will build up a
|
||||
ECLIPSE standard filename internally.
|
||||
*/
|
||||
|
||||
void EclipseGridParser::saveEGRID_INIT( const std::string& output_dir , const std::string& basename, bool fmt_file) {
|
||||
ecl_grid_type * ecl_grid = newGrid();
|
||||
char * egrid_file = ecl_util_alloc_filename( output_dir.c_str() , basename.c_str() , ECL_EGRID_FILE , fmt_file , 0);
|
||||
char * init_file = ecl_util_alloc_filename( output_dir.c_str() , basename.c_str() , ECL_INIT_FILE , fmt_file , 0);
|
||||
|
||||
ecl_grid_fwrite_EGRID( ecl_grid , egrid_file );
|
||||
saveINIT( init_file , ecl_grid );
|
||||
|
||||
free( init_file );
|
||||
free( egrid_file );
|
||||
ecl_grid_free( ecl_grid );
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Opm
|
||||
|
@ -45,6 +45,13 @@ along with OpenRS. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <opm/core/eclipse/EclipseUnits.hpp>
|
||||
#include <opm/core/utility/Factory.hpp>
|
||||
|
||||
#include <opm/core/grid/cornerpoint_grid.h>
|
||||
#ifdef HAVE_ERT
|
||||
#include <ecl_kw.h>
|
||||
#include <ecl_grid.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
@ -191,7 +198,23 @@ public:
|
||||
/// The units specified by the eclipse file read.
|
||||
const EclipseUnits& units() const;
|
||||
|
||||
struct grdecl get_grdecl() const;
|
||||
|
||||
#ifdef HAVE_ERT
|
||||
void saveEGRID_INIT( const std::string& output_dir , const std::string& basename, bool fmt_file = false);
|
||||
void saveEGRID( const std::string & filename );
|
||||
void saveINIT( const std::string & filename , const ecl_grid_type * ecl_grid);
|
||||
ecl_grid_type * newGrid( );
|
||||
#endif
|
||||
|
||||
|
||||
private:
|
||||
|
||||
#ifdef HAVE_ERT
|
||||
ecl_kw_type * newEclKW(const std::string &keyword , ecl_type_enum ecl_type) const;
|
||||
void save_kw( fortio_type * fortio , const std::string & kw , ecl_type_enum ecl_type);
|
||||
#endif
|
||||
|
||||
SpecialFieldPtr createSpecialField(std::istream& is, const std::string& fieldname);
|
||||
SpecialFieldPtr cloneSpecialField(const std::string& fieldname,
|
||||
const std::tr1::shared_ptr<SpecialBase> original);
|
||||
|
@ -46,6 +46,7 @@ extern "C" {
|
||||
const double *coord;
|
||||
const double *zcorn;
|
||||
const int *actnum;
|
||||
const double *mapaxes; /* 6 Element rotation vector - can be NULL. */
|
||||
};
|
||||
|
||||
/* Constant: I J K */
|
||||
|
98
opm/core/utility/writeECLData.cpp
Normal file
98
opm/core/utility/writeECLData.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
||||
Copyright 2012 Statoil ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <opm/core/grid.h>
|
||||
#include <opm/core/simulator/SimulatorTimer.hpp>
|
||||
#include <opm/core/utility/writeECLData.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include <ecl_grid.h>
|
||||
#include <ecl_util.h>
|
||||
#include <ecl_rst_file.h>
|
||||
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
static ecl_kw_type * ecl_kw_wrapper( const UnstructuredGrid& grid,
|
||||
const std::string& kw_name ,
|
||||
const std::vector<double> * data ,
|
||||
int offset ,
|
||||
int stride ) {
|
||||
|
||||
ecl_kw_type * ecl_kw = ecl_kw_alloc( kw_name.c_str() , data->size() / stride , ECL_FLOAT_TYPE );
|
||||
if (grid.global_cell == NULL) {
|
||||
for (int i=0; i < grid.number_of_cells; i++)
|
||||
ecl_kw_iset_float( ecl_kw , i , (*data)[i*stride + offset]);
|
||||
} else {
|
||||
for (int i=0; i < grid.number_of_cells; i++)
|
||||
ecl_kw_iset_float( ecl_kw , grid.global_cell[i] , (*data)[i*stride + offset]);
|
||||
}
|
||||
return ecl_kw;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void writeECLData(const UnstructuredGrid& grid,
|
||||
DataMap& data,
|
||||
const SimulatorTimer& simtimer,
|
||||
const std::string& output_dir,
|
||||
const std::string& base_name) {
|
||||
|
||||
int step = simtimer.currentStepNum();
|
||||
ecl_file_enum file_type = ECL_UNIFIED_RESTART_FILE;
|
||||
char * filename = ecl_util_alloc_filename(output_dir.c_str() , base_name.c_str() , file_type , true , step );
|
||||
int phases = ECL_OIL_PHASE + ECL_WATER_PHASE;
|
||||
double days = simtimer.currentTime() / 86400;
|
||||
time_t date = 0;
|
||||
int nx = grid.cartdims[0];
|
||||
int ny = grid.cartdims[1];
|
||||
int nz = grid.cartdims[2];
|
||||
int nactive = grid.number_of_cells;
|
||||
ecl_rst_file_type * rst_file;
|
||||
|
||||
if (step > 0 && file_type == ECL_UNIFIED_RESTART_FILE)
|
||||
rst_file = ecl_rst_file_open_append( filename );
|
||||
else
|
||||
rst_file = ecl_rst_file_open_write( filename );
|
||||
|
||||
ecl_rst_file_fwrite_header( rst_file , step , date , days , nx , ny , nz , nactive , phases );
|
||||
ecl_rst_file_start_solution( rst_file );
|
||||
|
||||
{
|
||||
ecl_kw_type * pressure_kw = ecl_kw_wrapper( grid , "PRESSURE" , data["pressure"] , 0 , 1);
|
||||
ecl_rst_file_add_kw( rst_file , pressure_kw );
|
||||
ecl_kw_free( pressure_kw );
|
||||
}
|
||||
|
||||
{
|
||||
ecl_kw_type * swat_kw = ecl_kw_wrapper( grid , "SWAT" , data["saturation"] , 0 , 2);
|
||||
ecl_rst_file_add_kw( rst_file , swat_kw );
|
||||
ecl_kw_free( swat_kw );
|
||||
}
|
||||
|
||||
ecl_rst_file_end_solution( rst_file );
|
||||
ecl_rst_file_close( rst_file );
|
||||
free(filename);
|
||||
}
|
||||
}
|
||||
|
47
opm/core/utility/writeECLData.hpp
Normal file
47
opm/core/utility/writeECLData.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2012 SINTEF ICT, Applied Mathematics.
|
||||
Copyright 2012 Statoil ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_WRITEECLDATA_HEADER_INCLUDED
|
||||
#define OPM_WRITEECLDATA_HEADER_INCLUDED
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <tr1/array>
|
||||
#include <iosfwd>
|
||||
#include <opm/core/utility/DataMap.hpp>
|
||||
#include <opm/core/simulator/SimulatorTimer.hpp>
|
||||
|
||||
struct UnstructuredGrid;
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
// ECLIPSE output for general grids.
|
||||
void writeECLData(const UnstructuredGrid& grid,
|
||||
const DataMap& data,
|
||||
const SimulatorTimer& simtimer,
|
||||
const std::string& output_dir,
|
||||
const std::string& base_name);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -22,7 +22,6 @@ test_column_extract \
|
||||
test_lapack \
|
||||
test_read_vag \
|
||||
test_readpolymer \
|
||||
test_readvector \
|
||||
test_sf2p \
|
||||
test_writeVtkData \
|
||||
unit_test
|
||||
|
Loading…
Reference in New Issue
Block a user