diff --git a/examples/sim_fibo_ad.cpp b/examples/sim_fibo_ad.cpp index 5b3f740e7..354c04652 100644 --- a/examples/sim_fibo_ad.cpp +++ b/examples/sim_fibo_ad.cpp @@ -33,7 +33,6 @@ #include #include -#include #include #include #include @@ -132,11 +131,10 @@ try grid.reset(new GridManager(eclipseState->getEclipseGrid(), porv)); auto &cGrid = *grid->c_grid(); const PhaseUsage pu = Opm::phaseUsageFromDeck(deck); - Opm::EclipseWriter outputWriter(param, - eclipseState, - pu, - cGrid.number_of_cells, - cGrid.global_cell); + Opm::BlackoilOutputWriter outputWriter(cGrid, + param, + eclipseState, + pu ); // Rock and fluid init props.reset(new BlackoilPropertiesFromDeck(deck, eclipseState, *grid->c_grid(), param)); diff --git a/examples/sim_fibo_ad_cp.cpp b/examples/sim_fibo_ad_cp.cpp index c750a8cb2..c16f6a684 100644 --- a/examples/sim_fibo_ad_cp.cpp +++ b/examples/sim_fibo_ad_cp.cpp @@ -54,7 +54,6 @@ #include #include // Note: the GridHelpers must be included before this (to make overloads available). \TODO: Fix. -#include #include #include #include @@ -68,6 +67,7 @@ #include #include + #include #include @@ -132,7 +132,6 @@ try Opm::ParserPtr parser(new Opm::Parser() ); Opm::LoggerPtr logger(new Opm::Logger()); - bool strict_parsing = param.getDefault("strict_parsing", true); Opm::DeckConstPtr deck; std::shared_ptr eclipseState; try { @@ -160,9 +159,7 @@ try grid->processEclipseFormat(deck, false, false, false, porv); const PhaseUsage pu = Opm::phaseUsageFromDeck(deck); - Opm::EclipseWriter outputWriter(param, eclipseState, pu, - Opm::UgGridHelpers::numCells(*grid), - Opm::UgGridHelpers::globalCell(*grid)); + Opm::BlackoilOutputWriter outputWriter(*grid, param, eclipseState, pu ); // Rock and fluid init props.reset(new BlackoilPropertiesFromDeck(deck, eclipseState, diff --git a/opm/autodiff/SimulatorFullyImplicitBlackoil.hpp b/opm/autodiff/SimulatorFullyImplicitBlackoil.hpp index a33356424..731d75eb5 100644 --- a/opm/autodiff/SimulatorFullyImplicitBlackoil.hpp +++ b/opm/autodiff/SimulatorFullyImplicitBlackoil.hpp @@ -38,7 +38,7 @@ namespace Opm class BlackoilState; class WellStateFullyImplicitBlackoil; class EclipseState; - class EclipseWriter; + class BlackoilOutputWriter; struct SimulatorReport; /// Class collecting all necessary components for a two-phase simulation. @@ -85,7 +85,7 @@ namespace Opm const bool disgas, const bool vapoil, std::shared_ptr eclipse_state, - EclipseWriter& output_writer, + BlackoilOutputWriter& output_writer, const std::vector& threshold_pressures_by_face); /// Run the simulation. diff --git a/opm/autodiff/SimulatorFullyImplicitBlackoilOutput.cpp b/opm/autodiff/SimulatorFullyImplicitBlackoilOutput.cpp index 5b2c49aa7..2d3abd9fe 100644 --- a/opm/autodiff/SimulatorFullyImplicitBlackoilOutput.cpp +++ b/opm/autodiff/SimulatorFullyImplicitBlackoilOutput.cpp @@ -1,3 +1,22 @@ +/* + Copyright (c) 2014 SINTEF ICT, Applied Mathematics. + Copyright (c) 2015 IRIS AS + + 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 "config.h" #include "SimulatorFullyImplicitBlackoilOutput.hpp" @@ -26,7 +45,7 @@ namespace Opm void outputStateVtk(const UnstructuredGrid& grid, - const Opm::BlackoilState& state, + const SimulatorState& state, const int step, const std::string& output_dir) { @@ -163,7 +182,7 @@ namespace Opm #ifdef HAVE_DUNE_CORNERPOINT void outputStateVtk(const Dune::CpGrid& grid, - const Opm::BlackoilState& state, + const Opm::SimulatorState& state, const int step, const std::string& output_dir) { @@ -187,7 +206,7 @@ namespace Opm #endif writer.addCellData(state.saturation(), "saturation", state.numPhases()); writer.addCellData(state.pressure(), "pressure", 1); - + std::vector cell_velocity; Opm::estimateCellVelocity(AutoDiffGrid::numCells(grid), AutoDiffGrid::numFaces(grid), @@ -202,4 +221,32 @@ namespace Opm } #endif + void + BlackoilOutputWriter:: + writeInit(const SimulatorTimerInterface& timer) + { + if( eclWriter_ ) { + eclWriter_->writeInit(timer); + } + } + + void + BlackoilOutputWriter:: + writeTimeStep(const SimulatorTimerInterface& timer, + const SimulatorState& state, + const WellState& wellState) + { + // VTK output + if( vtkWriter_ ) { + vtkWriter_->writeTimeStep( timer, state, wellState ); + } + // Matlab output + if( matlabWriter_ ) { + matlabWriter_->writeTimeStep( timer, state, wellState ); + } + // ECL output + if ( eclWriter_ ) { + eclWriter_->writeTimeStep(timer, state, wellState); + } + } } diff --git a/opm/autodiff/SimulatorFullyImplicitBlackoilOutput.hpp b/opm/autodiff/SimulatorFullyImplicitBlackoilOutput.hpp index e3b683262..1a875d6fa 100644 --- a/opm/autodiff/SimulatorFullyImplicitBlackoilOutput.hpp +++ b/opm/autodiff/SimulatorFullyImplicitBlackoilOutput.hpp @@ -1,3 +1,22 @@ +/* + Copyright (c) 2014 SINTEF ICT, Applied Mathematics. + Copyright (c) 2015 IRIS AS + + 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_SIMULATORFULLYIMPLICITBLACKOILOUTPUT_HEADER_INCLUDED #define OPM_SIMULATORFULLYIMPLICITBLACKOILOUTPUT_HEADER_INCLUDED #include @@ -6,6 +25,10 @@ #include #include #include +#include + +#include +#include #include @@ -23,7 +46,7 @@ namespace Opm { void outputStateVtk(const UnstructuredGrid& grid, - const Opm::BlackoilState& state, + const Opm::SimulatorState& state, const int step, const std::string& output_dir); @@ -38,7 +61,7 @@ namespace Opm const std::string& output_dir); #ifdef HAVE_DUNE_CORNERPOINT void outputStateVtk(const Dune::CpGrid& grid, - const Opm::BlackoilState& state, + const Opm::SimulatorState& state, const int step, const std::string& output_dir); #endif @@ -89,6 +112,141 @@ namespace Opm } } + /** Wrapper class satisfying the OutputWriter interface */ + template + class BlackoilVTKWriter : public OutputWriter + { + public: + // constructor taking grid and directory + BlackoilVTKWriter(const Grid& grid, + const std::string& outputDir) + : grid_( grid ), + outputDir_( outputDir ) + {} + /** \copydoc Opm::OutputWriter::writeInit */ + void writeInit(const SimulatorTimerInterface &timer) {} + + /** \copydoc Opm::OutputWriter::writeTimeStep */ + void writeTimeStep(const SimulatorTimerInterface& timer, + const SimulatorState& state, + const WellState& ) + { + outputStateVtk(grid_, state, timer.currentStepNum(), outputDir_); + } + + protected: + const Grid& grid_; + const std::string outputDir_; + }; + + template + class BlackoilMatlabWriter : public OutputWriter + { + public: + // constructor taking grid and directory + BlackoilMatlabWriter(const Grid& grid, + const std::string& outputDir) + : grid_( grid ), + outputDir_( outputDir ) + {} + + /** \copydoc Opm::OutputWriter::writeInit */ + void writeInit(const SimulatorTimerInterface &timer) {} + + /** \copydoc Opm::OutputWriter::writeTimeStep */ + void writeTimeStep(const SimulatorTimerInterface& timer, + const SimulatorState& reservoirState, + const WellState& wellState) + { + const BlackoilState* state = + dynamic_cast< const BlackoilState* > (&reservoirState); + if( state ) { + outputStateMatlab(grid_, *state, timer.currentStepNum(), outputDir_); + } + else { + OPM_THROW(std::logic_error,"BlackoilMatlabWriter only works for BlackoilState"); + } + outputWellStateMatlab(wellState, timer.currentStepNum(), outputDir_); + } + + protected: + const Grid& grid_; + const std::string outputDir_; + }; + + class BlackoilOutputWriter : public OutputWriter + { + public: + // constructor creating different sub writers + template + BlackoilOutputWriter(const Grid& grid, + const parameter::ParameterGroup& param, + Opm::EclipseStateConstPtr eclipseState, + const Opm::PhaseUsage &phaseUsage); + + /** \copydoc Opm::OutputWriter::writeInit */ + void writeInit(const SimulatorTimerInterface &timer); + + /** \copydoc Opm::OutputWriter::writeTimeStep */ + void writeTimeStep(const SimulatorTimerInterface& timer, + const SimulatorState& reservoirState, + const WellState& wellState); + + /** \brief return output directory */ + const std::string& outputDirectory() const { return outputDir_; } + + /** \brief return true if output is enabled */ + const bool output () const { return output_; } + + protected: + // Parameters for output. + const bool output_; + const std::string outputDir_; + const int output_interval_; + + std::unique_ptr< OutputWriter > vtkWriter_; + std::unique_ptr< OutputWriter > matlabWriter_; + std::unique_ptr< EclipseWriter > eclWriter_; + }; + + + ////////////////////////////////////////////////////////////// + // + // Implementation + // + ////////////////////////////////////////////////////////////// + template + inline + BlackoilOutputWriter:: + BlackoilOutputWriter(const Grid& grid, + const parameter::ParameterGroup& param, + Opm::EclipseStateConstPtr eclipseState, + const Opm::PhaseUsage &phaseUsage ) + : output_( param.getDefault("output", true) ), + outputDir_( output_ ? param.getDefault("output_dir", std::string("output")) : "." ), + output_interval_( output_ ? param.getDefault("output_interval", 1): 0 ), + vtkWriter_( output_ && param.getDefault("output_vtk",false) ? + new BlackoilVTKWriter< Grid >( grid, outputDir_ ) : 0 ), + matlabWriter_( output_ && param.getDefault("output_matlab", false) ? + new BlackoilMatlabWriter< Grid >( grid, outputDir_ ) : 0 ), + eclWriter_( output_ && param.getDefault("output_ecl", true) ? + new EclipseWriter(param, eclipseState, phaseUsage, + Opm::UgGridHelpers::numCells( grid ), + Opm::UgGridHelpers::globalCell( grid ) ) + : 0 ) + { + // For output. + if (output_) { + // Ensure that output dir exists + boost::filesystem::path fpath(outputDir_); + try { + create_directories(fpath); + } + catch (...) { + OPM_THROW(std::runtime_error, "Creating directories failed: " << fpath); + } + } + } } #endif diff --git a/opm/autodiff/SimulatorFullyImplicitBlackoil_impl.hpp b/opm/autodiff/SimulatorFullyImplicitBlackoil_impl.hpp index 21747f357..ca62f30c2 100644 --- a/opm/autodiff/SimulatorFullyImplicitBlackoil_impl.hpp +++ b/opm/autodiff/SimulatorFullyImplicitBlackoil_impl.hpp @@ -34,7 +34,6 @@ #include #include -#include #include #include #include @@ -87,7 +86,7 @@ namespace Opm bool has_disgas, bool has_vapoil, std::shared_ptr eclipse_state, - EclipseWriter& output_writer, + BlackoilOutputWriter& output_writer, const std::vector& threshold_pressures_by_face); SimulatorReport run(SimulatorTimer& timer, @@ -101,13 +100,6 @@ namespace Opm const parameter::ParameterGroup param_; - // Parameters for output. - const bool output_; - const bool output_vtk_; - const bool output_matlab_; - const std::string output_dir_; - const int output_interval_; - // Observed objects. const Grid& grid_; BlackoilPropsAdInterface& props_; @@ -123,7 +115,7 @@ namespace Opm // eclipse_state std::shared_ptr eclipse_state_; // output_writer - EclipseWriter& output_writer_; + BlackoilOutputWriter& output_writer_; RateConverterType rateConverter_; // Threshold pressures. std::vector threshold_pressures_by_face_; @@ -149,7 +141,7 @@ namespace Opm const bool has_disgas, const bool has_vapoil, std::shared_ptr eclipse_state, - EclipseWriter& output_writer, + BlackoilOutputWriter& output_writer, const std::vector& threshold_pressures_by_face) { @@ -169,64 +161,6 @@ namespace Opm } - - static void outputWellStateMatlab(const Opm::WellStateFullyImplicitBlackoil& well_state, - const int step, - const std::string& output_dir) - { - Opm::DataMap dm; - dm["bhp"] = &well_state.bhp(); - dm["wellrates"] = &well_state.wellRates(); - - // Write data (not grid) in Matlab format - for (Opm::DataMap::const_iterator it = dm.begin(); it != dm.end(); ++it) { - std::ostringstream fname; - fname << output_dir << "/" << it->first; - boost::filesystem::path fpath = fname.str(); - try { - create_directories(fpath); - } - catch (...) { - OPM_THROW(std::runtime_error,"Creating directories failed: " << fpath); - } - fname << "/" << std::setw(3) << std::setfill('0') << step << ".txt"; - std::ofstream file(fname.str().c_str()); - if (!file) { - OPM_THROW(std::runtime_error,"Failed to open " << fname.str()); - } - file.precision(15); - const std::vector& d = *(it->second); - std::copy(d.begin(), d.end(), std::ostream_iterator(file, "\n")); - } - } - -#if 0 - static void outputWaterCut(const Opm::Watercut& watercut, - const std::string& output_dir) - { - // Write water cut curve. - std::string fname = output_dir + "/watercut.txt"; - std::ofstream os(fname.c_str()); - if (!os) { - OPM_THROW(std::runtime_error, "Failed to open " << fname); - } - watercut.write(os); - } - - static void outputWellReport(const Opm::WellReport& wellreport, - const std::string& output_dir) - { - // Write well report. - std::string fname = output_dir + "/wellreport.txt"; - std::ofstream os(fname.c_str()); - if (!os) { - OPM_THROW(std::runtime_error, "Failed to open " << fname); - } - wellreport.write(os); - } -#endif - - // \TODO: Treat bcs. template SimulatorFullyImplicitBlackoil::Impl::Impl(const parameter::ParameterGroup& param, @@ -239,14 +173,9 @@ namespace Opm const bool has_disgas, const bool has_vapoil, std::shared_ptr eclipse_state, - EclipseWriter& output_writer, + BlackoilOutputWriter& output_writer, const std::vector& threshold_pressures_by_face) : param_(param), - output_( param.getDefault("output", true) ), - output_vtk_( output_ ? param.getDefault("output_vtk",true) : false ), - output_matlab_( output_ ? param.getDefault("output_matlab", true) : false ), - output_dir_( output_ ? param.getDefault("output_dir", std::string("output")) : "" ), - output_interval_( output_ ? param.getDefault("output_interval", 1): 0 ), grid_(grid), props_(props), rock_comp_props_(rock_comp_props), @@ -260,18 +189,6 @@ namespace Opm rateConverter_(props_, std::vector(AutoDiffGrid::numCells(grid_), 0)), threshold_pressures_by_face_(threshold_pressures_by_face) { - // For output. - if (output_) { - // Ensure that output dir exists - boost::filesystem::path fpath(output_dir_); - try { - create_directories(fpath); - } - catch (...) { - OPM_THROW(std::runtime_error, "Creating directories failed: " << fpath); - } - } - // Misc init. const int num_cells = AutoDiffGrid::numCells(grid); allcells_.resize(num_cells); @@ -295,7 +212,7 @@ namespace Opm Opm::time::StopWatch step_timer; Opm::time::StopWatch total_timer; total_timer.start(); - std::string tstep_filename = output_dir_ + "/step_timing.txt"; + std::string tstep_filename = output_writer_.outputDirectory() + "/step_timing.txt"; std::ofstream tstep_os(tstep_filename.c_str()); typename FullyImplicitBlackoilSolver::SolverParameter solverParam( param_ ); @@ -307,6 +224,9 @@ namespace Opm adaptiveTimeStepping.reset( new AdaptiveTimeStepping( param_ ) ); } + // init output writer + output_writer_.writeInit( timer ); + // Main simulation loop. while (!timer.done()) { // Report timestep. @@ -328,22 +248,8 @@ namespace Opm WellStateFullyImplicitBlackoil well_state; well_state.init(wells, state, prev_well_state); - // Output state at start of time step. - if (output_ && (timer.currentStepNum() % output_interval_ == 0)) { - if (output_vtk_) { - outputStateVtk(grid_, state, timer.currentStepNum(), output_dir_); - } - if (output_matlab_) { - outputStateMatlab(grid_, state, timer.currentStepNum(), output_dir_); - outputWellStateMatlab(well_state,timer.currentStepNum(), output_dir_); - } - } - if (output_) { - if (timer.currentStepNum() == 0) { - output_writer_.writeInit(timer); - } - if( ! adaptiveTimeStepping || timer.currentStepNum() == 0 ) - output_writer_.writeTimeStep(timer, state, well_state); + if( ! adaptiveTimeStepping ) { + output_writer_.writeTimeStep( timer, state, well_state ); } // Max oil saturation (for VPPARS), hysteresis update. @@ -381,7 +287,7 @@ namespace Opm const double st = solver_timer.secsSinceStart(); std::cout << "Fully implicit solver took: " << st << " seconds." << std::endl; stime += st; - if (output_) { + if ( output_writer_.output() ) { SimulatorReport step_report; step_report.pressure_time = st; step_report.total_time = step_timer.secsSinceStart(); @@ -394,17 +300,8 @@ namespace Opm } // Write final simulation state. - if (output_) { - if (output_vtk_) { - outputStateVtk(grid_, state, timer.currentStepNum(), output_dir_); - } - if (output_matlab_) { - outputStateMatlab(grid_, state, timer.currentStepNum(), output_dir_); - outputWellStateMatlab(prev_well_state, timer.currentStepNum(), output_dir_); - } - if( ! adaptiveTimeStepping ) - //std::cout << "Write last step" << std::endl; - output_writer_.writeTimeStep(timer, state, prev_well_state); + if( ! adaptiveTimeStepping ) { + output_writer_.writeTimeStep( timer, state, prev_well_state ); } // Stop timer and create timing report