From bb066aa23beb8eea7c3c8e1560b1631f015a89eb Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Wed, 27 Jun 2012 20:20:05 +0200 Subject: [PATCH] Added functionality to save results in ECLIPSE format from ERT libraries. --- Makefile.am | 15 +- examples/spu_2p.cpp | 14 +- opm/core/GridManager.cpp | 66 ++---- opm/core/eclipse/EclipseGridParser.cpp | 259 ++++++++++++++++++++++- opm/core/eclipse/EclipseGridParser.hpp | 23 ++ opm/core/grid/cpgpreprocess/preprocess.h | 1 + opm/core/utility/writeECLData.cpp | 98 +++++++++ opm/core/utility/writeECLData.hpp | 47 ++++ tests/Makefile.am | 1 - 9 files changed, 468 insertions(+), 56 deletions(-) create mode 100644 opm/core/utility/writeECLData.cpp create mode 100644 opm/core/utility/writeECLData.hpp diff --git a/Makefile.am b/Makefile.am index 583e67ff..06e98c1d 100644 --- a/Makefile.am +++ b/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 += \ diff --git a/examples/spu_2p.cpp b/examples/spu_2p.cpp index 69697378..ca05b424 100644 --- a/examples/spu_2p.cpp +++ b/examples/spu_2p.cpp @@ -94,14 +94,19 @@ #include +#ifdef HAVE_ERT +#include +#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); diff --git a/opm/core/GridManager.cpp b/opm/core/GridManager.cpp index 16140a07..f84692ee 100644 --- a/opm/core/GridManager.cpp +++ b/opm/core/GridManager.cpp @@ -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& zcorn = deck.getFloatingPointValue("ZCORN"); - const std::vector& coord = deck.getFloatingPointValue("COORD"); - const int* actnum = 0; - if (deck.hasField("ACTNUM")) { - actnum = &(deck.getIntegerValue("ACTNUM")[0]); - } - std::vector 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_; } diff --git a/opm/core/eclipse/EclipseGridParser.cpp b/opm/core/eclipse/EclipseGridParser.cpp index fd5f5ef5..d582a996 100644 --- a/opm/core/eclipse/EclipseGridParser.cpp +++ b/opm/core/eclipse/EclipseGridParser.cpp @@ -47,8 +47,18 @@ #include #include #include -#include #include +#include +#include + +#ifdef HAVE_ERT +#include +#include +#include +#include +#include +#include +#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& zcorn = getFloatingPointValue("ZCORN"); + const std::vector& coord = getFloatingPointValue("COORD"); + const int* actnum = NULL; + if (hasField("ACTNUM")) { + actnum = &(getIntegerValue("ACTNUM")[0]); + } + + std::vector 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 &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 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 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 diff --git a/opm/core/eclipse/EclipseGridParser.hpp b/opm/core/eclipse/EclipseGridParser.hpp index 56e9ee4f..31195e77 100644 --- a/opm/core/eclipse/EclipseGridParser.hpp +++ b/opm/core/eclipse/EclipseGridParser.hpp @@ -45,6 +45,13 @@ along with OpenRS. If not, see . #include #include +#include +#ifdef HAVE_ERT +#include +#include +#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 original); diff --git a/opm/core/grid/cpgpreprocess/preprocess.h b/opm/core/grid/cpgpreprocess/preprocess.h index 9592ce92..4ee9be52 100644 --- a/opm/core/grid/cpgpreprocess/preprocess.h +++ b/opm/core/grid/cpgpreprocess/preprocess.h @@ -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 */ diff --git a/opm/core/utility/writeECLData.cpp b/opm/core/utility/writeECLData.cpp new file mode 100644 index 00000000..ef7eb1fd --- /dev/null +++ b/opm/core/utility/writeECLData.cpp @@ -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 . +*/ + + + +#include +#include +#include +#include + +#include +#include +#include + + +namespace Opm +{ + + static ecl_kw_type * ecl_kw_wrapper( const UnstructuredGrid& grid, + const std::string& kw_name , + const std::vector * 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); + } +} + diff --git a/opm/core/utility/writeECLData.hpp b/opm/core/utility/writeECLData.hpp new file mode 100644 index 00000000..1c963c0d --- /dev/null +++ b/opm/core/utility/writeECLData.hpp @@ -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 . +*/ + +#ifndef OPM_WRITEECLDATA_HEADER_INCLUDED +#define OPM_WRITEECLDATA_HEADER_INCLUDED + + +#include +#include +#include +#include +#include +#include +#include + +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 diff --git a/tests/Makefile.am b/tests/Makefile.am index 1ec5dd26..d4b23705 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -22,7 +22,6 @@ test_column_extract \ test_lapack \ test_read_vag \ test_readpolymer \ -test_readvector \ test_sf2p \ test_writeVtkData \ unit_test