Added small class RegionCache.

This commit is contained in:
Joakim Hove 2016-10-11 14:39:15 +02:00
parent 2f411b208e
commit a8d82221a8
8 changed files with 211 additions and 54 deletions

View File

@ -0,0 +1,43 @@
/*
Copyright 2016 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_REGION_CACHE_HPP
#define OPM_REGION_CACHE_HPP
#include <vector>
namespace Opm {
class EclipseState;
class EclipseGrid;
namespace out {
class RegionCache {
public:
RegionCache() = default;
RegionCache(const EclipseState& state, const EclipseGrid& grid);
const std::vector<size_t>& cells( int region_id ) const;
private:
std::vector<size_t> empty;
std::map<int , std::vector<size_t> > cell_map;
};
}
}
#endif

View File

@ -32,6 +32,7 @@
#include <opm/output/data/Wells.hpp>
#include <opm/output/data/Cells.hpp>
#include <opm/output/data/Solution.hpp>
#include <opm/output/eclipse/RegionCache.hpp>
namespace Opm {
@ -41,6 +42,8 @@ namespace Opm {
namespace out {
class RegionCache;
class Summary {
public:
Summary( const EclipseState&, const SummaryConfig& );
@ -49,9 +52,9 @@ class Summary {
void add_timestep( int report_step,
double secs_elapsed,
const EclipseGrid& grid,
const EclipseGrid& grid,
const EclipseState& es,
const std::unordered_map<int, std::vector<size_t>>& regionCells,
const RegionCache& regionCache,
const data::Wells&,
const data::Solution& );
void write();

View File

@ -39,6 +39,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
#include <opm/parser/eclipse/Utility/Functional.hpp>
#include <opm/output/eclipse/Summary.hpp>
#include <opm/output/eclipse/RegionCache.hpp>
#include <cstdlib>
#include <memory> // unique_ptr
@ -400,7 +401,7 @@ class EclipseWriter::Impl {
const EclipseState& es;
EclipseGrid grid;
std::unordered_map<int , std::vector<size_t>> regionCells;
out::RegionCache regionCache;
std::string outputDir;
std::string baseName;
out::Summary summary;
@ -416,6 +417,7 @@ EclipseWriter::Impl::Impl( const EclipseState& eclipseState,
EclipseGrid grid_)
: es( eclipseState )
, grid( std::move( grid_ ) )
, regionCache( *es , grid )
, outputDir( eclipseState.getIOConfig().getOutputDir() )
, baseName( uppercase( eclipseState.getIOConfig().getBaseName() ) )
, summary( eclipseState, eclipseState.getSummaryConfig() )
@ -425,6 +427,8 @@ EclipseWriter::Impl::Impl( const EclipseState& eclipseState,
, ert_phase_mask( ertPhaseMask( eclipseState.getTableManager() ) )
{}
void EclipseWriter::Impl::writeINITFile( const data::Solution& simProps, const NNC& nnc) const {
const auto& units = this->es.getUnits();
const IOConfig& ioConfig = this->es.cfg().io();
@ -802,7 +806,7 @@ void EclipseWriter::writeTimeStep(int report_step,
secs_elapsed,
this->impl->grid,
this->impl->es,
this->impl->regionCells,
this->impl->regionCache,
wells ,
cells );
this->impl->summary.write();
@ -828,20 +832,6 @@ EclipseWriter::EclipseWriter( const EclipseState& es, EclipseGrid grid)
+ outputDir + "' is not a directory");
}
}
/*
Precalculate the cell - region distribution for faster
evaluation of region properties.
*/
{
const auto& properties = this->impl->es.get3DProperties();
const auto& fipnum = properties.getIntGridProperty("FIPNUM");
const auto& region_values = properties.getRegions( "FIPNUM" );
for (auto region_id : region_values)
this->impl->regionCells.emplace( region_id , fipnum.cellsEqual( region_id , this->impl->grid ));
}
}
EclipseWriter::~EclipseWriter() {}

View File

@ -0,0 +1,49 @@
/*
Copyright 2016 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/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Eclipse3DProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/GridProperty.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/output/eclipse/RegionCache.hpp>
namespace Opm {
namespace out {
RegionCache::RegionCache(const EclipseState& state, const EclipseGrid& grid) {
const auto& properties = state.get3DProperties();
const auto& fipnum = properties.getIntGridProperty("FIPNUM");
const auto& region_values = properties.getRegions( "FIPNUM" );
for (auto region_id : region_values)
this->cell_map.emplace( region_id , fipnum.cellsEqual( region_id , grid ));
}
const std::vector<size_t>& RegionCache::cells( int region_id ) const {
const auto iter = this->cell_map.find( region_id );
if (iter == this->cell_map.end())
return this->empty;
else
return iter->second;
}
}
}

View File

@ -17,7 +17,6 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <opm/output/eclipse/Summary.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/IOConfig/IOConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
@ -30,6 +29,9 @@
#include <opm/parser/eclipse/EclipseState/Grid/GridProperty.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
#include <opm/output/eclipse/Summary.hpp>
#include <opm/output/eclipse/RegionCache.hpp>
/*
* This class takes simulator state and parser-provided information and
* orchestrates ert to write simulation results as requested by the SUMMARY
@ -125,7 +127,7 @@ struct fn_args {
int num;
const data::Wells& wells;
const data::Solution& state;
const std::unordered_map<int , std::vector<size_t>>& regionCells;
const out::RegionCache& regionCache;
const GridDims& grid;
};
@ -283,14 +285,13 @@ inline quantity duration( const fn_args& args ) {
}
quantity rpr(const fn_args& args) {
const auto& pair = args.regionCells.find( args.num );
if (pair == args.regionCells.end())
const auto& cells = args.regionCache.cells( args.num );
if (cells.size() == 0)
return { 0.0 , measure::pressure };
double RPR = 0;
const std::vector<double>& pressure = args.state.data( "PRESSURE" );
const auto& cells = pair->second;
for (auto cell_index : cells)
RPR += pressure[cell_index];
@ -586,9 +587,8 @@ Summary::Summary( const EclipseState& st,
/* get unit strings by calling each function with dummy input */
const auto handle = funs.find( keyword )->second;
const std::vector< const Well* > dummy_wells;
const std::unordered_map<int,std::vector<size_t>> dummy_cells;
GridDims dummy_grid(1,1,1);
const fn_args no_args{ dummy_wells, 0, 0, 0, {} , {}, dummy_cells , dummy_grid };
const fn_args no_args{ dummy_wells, 0, 0, 0, {} , {}, {} , dummy_grid };
const auto val = handle( no_args );
const auto* unit = st.getUnits().name( val.unit );
@ -603,7 +603,7 @@ void Summary::add_timestep( int report_step,
double secs_elapsed,
const EclipseGrid& grid,
const EclipseState& es,
const std::unordered_map<int, std::vector<size_t>>& regionCells,
const RegionCache& regionCache,
const data::Wells& wells ,
const data::Solution& state) {
@ -618,7 +618,7 @@ void Summary::add_timestep( int report_step,
const auto* genkey = smspec_node_get_gen_key1( f.first );
const auto schedule_wells = find_wells( schedule, f.first, timestep );
const auto val = f.second( { schedule_wells, duration, timestep, num, wells , state , regionCells , grid} );
const auto val = f.second( { schedule_wells, duration, timestep, num, wells , state , regionCache , grid} );
const auto unit_applied_val = es.getUnits().from_si( val.unit, val.value );
const auto res = smspec_node_is_total( f.first ) && prev_tstep

View File

@ -161,6 +161,7 @@ struct setup {
EclipseState es;
SummaryConfig config;
const EclipseGrid& grid;
const out::RegionCache regionCache;
data::Wells wells;
std::string name;
ERT::TestArea ta;
@ -175,17 +176,13 @@ struct setup {
es( deck, ParseContext() ),
config( deck, es, parseContext ),
grid( es.getInputGrid() ),
regionCache( es , grid ),
wells( result_wells() ),
name( fname ),
ta( ERT::TestArea("test_summary") ),
solution( make_solution( es.getInputGrid() ) )
{
const auto& properties = es.get3DProperties();
const auto& fipnum = properties.getIntGridProperty("FIPNUM");
const auto& region_values = properties.getRegions( "FIPNUM" );
for (auto region_id : region_values)
cells.emplace( region_id , fipnum.cellsEqual( region_id , grid ));
solution = make_solution( *es.getInputGrid());
}
};
@ -203,9 +200,9 @@ BOOST_AUTO_TEST_CASE(well_keywords) {
cfg.name = "PATH/CASE";
out::Summary writer( cfg.es, cfg.config, cfg.name );
writer.add_timestep( 0, 0 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 1, 1 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 2, 2 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 0, 0 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 1, 1 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 2, 2 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.write();
auto res = readsum( cfg.name );
@ -339,9 +336,9 @@ BOOST_AUTO_TEST_CASE(group_keywords) {
setup cfg( "test_Summary_group" );
out::Summary writer( cfg.es, cfg.config, cfg.name );
writer.add_timestep( 0, 0 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 1, 1 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 2, 2 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 0, 0 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 1, 1 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 2, 2 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.write();
auto res = readsum( cfg.name );
@ -417,9 +414,9 @@ BOOST_AUTO_TEST_CASE(completion_kewords) {
setup cfg( "test_Summary_completion" );
out::Summary writer( cfg.es, cfg.config, cfg.name );
writer.add_timestep( 0, 0 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 1, 1 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 2, 2 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 0, 0 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 1, 1 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 2, 2 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.write();
auto res = readsum( cfg.name );
@ -466,9 +463,9 @@ BOOST_AUTO_TEST_CASE(field_keywords) {
setup cfg( "test_Summary_field" );
out::Summary writer( cfg.es, cfg.config, cfg.name );
writer.add_timestep( 0, 0 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 1, 1 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 2, 2 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 0, 0 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 1, 1 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 2, 2 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.write();
auto res = readsum( cfg.name );
@ -543,9 +540,9 @@ BOOST_AUTO_TEST_CASE(report_steps_time) {
setup cfg( "test_Summary_report_steps_time" );
out::Summary writer( cfg.es, cfg.config, cfg.name );
writer.add_timestep( 1, 2 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 1, 5 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 2, 10 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 1, 2 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 1, 5 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 2, 10 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.write();
auto res = readsum( cfg.name );
@ -565,9 +562,9 @@ BOOST_AUTO_TEST_CASE(skip_unknown_var) {
setup cfg( "test_Summary_skip_unknown_var" );
out::Summary writer( cfg.es, cfg.config, cfg.name );
writer.add_timestep( 1, 2 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 1, 5 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 2, 10 * day, cfg.grid, cfg.es, cfg.cells, cfg.wells , cfg.solution);
writer.add_timestep( 1, 2 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 1, 5 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.add_timestep( 2, 10 * day, cfg.grid, cfg.es, cfg.regionCache, cfg.wells , cfg.solution);
writer.write();
auto res = readsum( cfg.name );
@ -585,9 +582,9 @@ BOOST_AUTO_TEST_CASE(region_vars) {
{
out::Summary writer( cfg.es, cfg.config, cfg.name );
writer.add_timestep( 1, 2 * day, cfg.grid , cfg.es, cfg.cells, cfg.wells, cfg.solution);
writer.add_timestep( 1, 5 * day, cfg.grid , cfg.es, cfg.cells, cfg.wells, cfg.solution);
writer.add_timestep( 2, 10 * day, cfg.grid , cfg.es, cfg.cells, cfg.wells, cfg.solution);
writer.add_timestep( 1, 2 * day, cfg.grid , cfg.es, cfg.regionCache, cfg.wells, cfg.solution);
writer.add_timestep( 1, 5 * day, cfg.grid , cfg.es, cfg.regionCache, cfg.wells, cfg.solution);
writer.add_timestep( 2, 10 * day, cfg.grid , cfg.es, cfg.regionCache, cfg.wells, cfg.solution);
writer.write();
}

View File

@ -72,3 +72,5 @@ BOOST_AUTO_TEST_CASE(get_wrong) {
BOOST_CHECK_EQUAL( def, rates.get( rt::oil, def ) );
BOOST_CHECK_THROW( rates.get( rt::oil ), std::invalid_argument );
}

View File

@ -0,0 +1,73 @@
/*
Copyright 2016 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 "config.h"
#if HAVE_DYNAMIC_BOOST_TEST
#define BOOST_TEST_DYN_LINK
#endif
#define BOOST_TEST_MODULE RegionCache
#include <boost/test/unit_test.hpp>
#include <stdexcept>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/output/eclipse/RegionCache.hpp>
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/output/eclipse/RegionCache.hpp>
using namespace Opm;
const char* path = "summary_deck.DATA";
BOOST_AUTO_TEST_CASE(create) {
ParseContext parseContext;
Parser parser;
std::shared_ptr<Deck> deck( parser.parseFile( path, parseContext ));
EclipseState es(*deck , parseContext );
const EclipseGrid& grid = *es.getInputGrid();
out::RegionCache rc(es , grid);
const auto& c1 = rc.cells( 1 );
BOOST_CHECK_EQUAL( c1.size() , 100 );
const auto& c = rc.cells( 100 );
BOOST_CHECK_EQUAL( c.size() , 0 );
{
const auto& empty = rc.completions( 3 );
BOOST_CHECK_EQUAL( empty.size() , 0 );
}
{
const auto& top_layer = rc.completions( 1 );
BOOST_CHECK_EQUAL( top_layer.size() , 3 );
{
auto pair = top_layer[0];
BOOST_CHECK_EQUAL( pair.first , "W_1");
BOOST_CHECK_EQUAL( pair.second , grid.activeIndex( 0,0,0));
}
}
}