Merged main program for flow and flow_cp to avoid code duplication.

This commit is contained in:
Robert Kloefkorn 2015-06-16 16:17:56 +02:00
parent 21accccc01
commit 10725c0b70
3 changed files with 255 additions and 469 deletions

View File

@ -1,5 +1,7 @@
/* /*
Copyright 2013 SINTEF ICT, Applied Mathematics. Copyright 2013 SINTEF ICT, Applied Mathematics.
Copyright 2014 Dr. Blatt - HPC-Simulation-Software & Services
Copyright 2015 IRIS AS
This file is part of the Open Porous Media project (OPM). This file is part of the Open Porous Media project (OPM).
@ -16,12 +18,40 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>. along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/ */
#if HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif // HAVE_CONFIG_H
#include <dune/common/version.hh>
#include <opm/core/utility/platform_dependent/disable_warnings.h>
#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 3)
#include <dune/common/parallel/mpihelper.hh>
#else
#include <dune/common/mpihelper.hh>
#endif
#if HAVE_DUNE_CORNERPOINT && defined(WANT_DUNE_CORNERPOINTGRID)
#define USE_DUNE_CORNERPOINTGRID
#include <dune/grid/CpGrid.hpp>
#include <dune/grid/common/GridAdapter.hpp>
#else
#undef USE_DUNE_CORNERPOINTGRID
#endif
#include <opm/core/utility/platform_dependent/reenable_warnings.h>
#include <opm/core/pressure/FlowBCManager.hpp> #include <opm/core/pressure/FlowBCManager.hpp>
#include <opm/core/grid.h> #include <opm/core/grid.h>
#include <opm/core/grid/cornerpoint_grid.h>
#include <opm/core/grid/GridManager.hpp> #include <opm/core/grid/GridManager.hpp>
#include <opm/autodiff/GridHelpers.hpp>
#include <opm/core/wells.h> #include <opm/core/wells.h>
#include <opm/core/wells/WellsManager.hpp> #include <opm/core/wells/WellsManager.hpp>
#include <opm/core/utility/ErrorMacros.hpp> #include <opm/core/utility/ErrorMacros.hpp>
@ -31,7 +61,7 @@
#include <opm/core/simulator/SimulatorTimer.hpp> #include <opm/core/simulator/SimulatorTimer.hpp>
#include <opm/core/utility/miscUtilities.hpp> #include <opm/core/utility/miscUtilities.hpp>
#include <opm/core/utility/parameters/ParameterGroup.hpp> #include <opm/core/utility/parameters/ParameterGroup.hpp>
#include <opm/core/utility/thresholdPressures.hpp> #include <opm/core/utility/thresholdPressures.hpp> // Note: the GridHelpers must be included before this (to make overloads available). \TODO: Fix.
#include <opm/core/props/BlackoilPropertiesBasic.hpp> #include <opm/core/props/BlackoilPropertiesBasic.hpp>
#include <opm/core/props/BlackoilPropertiesFromDeck.hpp> #include <opm/core/props/BlackoilPropertiesFromDeck.hpp>
@ -46,6 +76,9 @@
#include <opm/autodiff/SimulatorFullyImplicitBlackoil.hpp> #include <opm/autodiff/SimulatorFullyImplicitBlackoil.hpp>
#include <opm/autodiff/BlackoilPropsAdFromDeck.hpp> #include <opm/autodiff/BlackoilPropsAdFromDeck.hpp>
#include <opm/autodiff/RedistributeDataHandles.hpp>
#include <opm/core/utility/share_obj.hpp>
#include <opm/parser/eclipse/OpmLog/OpmLog.hpp> #include <opm/parser/eclipse/OpmLog/OpmLog.hpp>
#include <opm/parser/eclipse/OpmLog/StreamLog.hpp> #include <opm/parser/eclipse/OpmLog/StreamLog.hpp>
@ -60,12 +93,12 @@
#include <memory> #include <memory>
#include <algorithm> #include <algorithm>
#include <cstdlib>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <numeric> #include <numeric>
#include <cstdlib> #include <cstdlib>
namespace namespace
{ {
void warnIfUnusedParams(const Opm::parameter::ParameterGroup& param) void warnIfUnusedParams(const Opm::parameter::ParameterGroup& param)
@ -86,7 +119,22 @@ main(int argc, char** argv)
try try
{ {
using namespace Opm; using namespace Opm;
#ifdef USE_DUNE_CORNERPOINTGRID
// Must ensure an instance of the helper is created to initialise MPI.
const Dune::MPIHelper& mpi_helper = Dune::MPIHelper::instance(argc, argv);
const int mpi_rank = mpi_helper.rank();
const int mpi_size = mpi_helper.size();
#else
// default values for serial run
const int mpi_rank = 0;
const int mpi_size = 1;
#endif
// Write parameters used for later reference. (only if rank is zero)
bool output_cout = ( mpi_rank == 0 );
if(output_cout)
{
std::cout << "**********************************************************************\n"; std::cout << "**********************************************************************\n";
std::cout << "* *\n"; std::cout << "* *\n";
std::cout << "* This is Flow (version 2015.04) *\n"; std::cout << "* This is Flow (version 2015.04) *\n";
@ -96,10 +144,20 @@ try
std::cout << "* http://opm-project.org *\n"; std::cout << "* http://opm-project.org *\n";
std::cout << "* *\n"; std::cout << "* *\n";
std::cout << "**********************************************************************\n\n"; std::cout << "**********************************************************************\n\n";
}
// Read parameters, see if a deck was specified on the command line. // Read parameters, see if a deck was specified on the command line.
if ( output_cout )
{
std::cout << "--------------- Reading parameters ---------------" << std::endl; std::cout << "--------------- Reading parameters ---------------" << std::endl;
parameter::ParameterGroup param(argc, argv, false); }
parameter::ParameterGroup param(argc, argv, false, output_cout);
if( !output_cout )
{
param.disableOutput();
}
if (!param.unhandledArguments().empty()) { if (!param.unhandledArguments().empty()) {
if (param.unhandledArguments().size() != 1) { if (param.unhandledArguments().size() != 1) {
std::cerr << "You can only specify a single input deck on the command line.\n"; std::cerr << "You can only specify a single input deck on the command line.\n";
@ -118,7 +176,7 @@ try
" c) as a parameter in a parameter file (.param or .xml) passed to the program.\n"; " c) as a parameter in a parameter file (.param or .xml) passed to the program.\n";
return EXIT_FAILURE; return EXIT_FAILURE;
} }
std::shared_ptr<GridManager> grid;
std::shared_ptr<BlackoilPropertiesInterface> props; std::shared_ptr<BlackoilPropertiesInterface> props;
std::shared_ptr<BlackoilPropsAdFromDeck> new_props; std::shared_ptr<BlackoilPropsAdFromDeck> new_props;
std::shared_ptr<RockCompressibility> rock_comp; std::shared_ptr<RockCompressibility> rock_comp;
@ -128,8 +186,8 @@ try
double gravity[3] = { 0.0 }; double gravity[3] = { 0.0 };
std::string deck_filename = param.get<std::string>("deck_filename"); std::string deck_filename = param.get<std::string>("deck_filename");
// Write parameters used for later reference. // Write parameters used for later reference. (only if rank is zero)
bool output = param.getDefault("output", true); bool output = ( mpi_rank == 0 ) && param.getDefault("output", true);
std::string output_dir; std::string output_dir;
if (output) { if (output) {
// Create output directory if needed. // Create output directory if needed.
@ -157,7 +215,6 @@ try
Opm::OpmLog::addBackend( "COUNTER" , counterLog ); Opm::OpmLog::addBackend( "COUNTER" , counterLog );
} }
Opm::DeckConstPtr deck; Opm::DeckConstPtr deck;
std::shared_ptr<EclipseState> eclipseState; std::shared_ptr<EclipseState> eclipseState;
try { try {
@ -171,11 +228,22 @@ try
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Grid init
std::vector<double> porv = eclipseState->getDoubleGridProperty("PORV")->getData(); std::vector<double> porv = eclipseState->getDoubleGridProperty("PORV")->getData();
grid.reset(new GridManager(eclipseState->getEclipseGrid(), porv)); #ifdef USE_DUNE_CORNERPOINTGRID
auto &cGrid = *grid->c_grid(); // Dune::CpGrid as grid manager
const PhaseUsage pu = Opm::phaseUsageFromDeck(deck); typedef Dune::CpGrid Grid;
std::shared_ptr<Grid> gridPtr;
// Grid init
gridPtr.reset(new Grid);
Grid& grid = *gridPtr;
grid.processEclipseFormat(deck, false, false, false, porv);
#else
// UnstructuredGrid as grid manager
typedef UnstructuredGrid Grid;
std::shared_ptr<GridManager> gridManager;
gridManager.reset(new GridManager(eclipseState->getEclipseGrid(), porv));
const Grid& grid = *(gridManager->c_grid());
#endif
// Possibly override IOConfig setting (from deck) for how often RESTART files should get written to disk (every N report step) // Possibly override IOConfig setting (from deck) for how often RESTART files should get written to disk (every N report step)
if (param.has("output_interval")) { if (param.has("output_interval")) {
@ -184,15 +252,17 @@ try
ioConfig->overrideRestartWriteInterval((size_t)output_interval); ioConfig->overrideRestartWriteInterval((size_t)output_interval);
} }
Opm::BlackoilOutputWriter outputWriter(cGrid, const PhaseUsage pu = Opm::phaseUsageFromDeck(deck);
param, Opm::BlackoilOutputWriter outputWriter(grid, param, eclipseState, pu );
eclipseState,
pu );
// Rock and fluid init // Rock and fluid init
props.reset(new BlackoilPropertiesFromDeck(deck, eclipseState, *grid->c_grid(), param)); props.reset(new BlackoilPropertiesFromDeck(deck, eclipseState,
new_props.reset(new BlackoilPropsAdFromDeck(deck, eclipseState, *grid->c_grid())); Opm::UgGridHelpers::numCells(grid),
Opm::UgGridHelpers::globalCell(grid),
Opm::UgGridHelpers::cartDims(grid),
Opm::UgGridHelpers::beginCellCentroids(grid),
Opm::UgGridHelpers::dimensions(grid), param));
new_props.reset(new BlackoilPropsAdFromDeck(deck, eclipseState, grid));
// check_well_controls = param.getDefault("check_well_controls", false); // check_well_controls = param.getDefault("check_well_controls", false);
// max_well_control_iterations = param.getDefault("max_well_control_iterations", 10); // max_well_control_iterations = param.getDefault("max_well_control_iterations", 10);
// Rock compressibility. // Rock compressibility.
@ -203,45 +273,87 @@ try
// Init state variables (saturation and pressure). // Init state variables (saturation and pressure).
if (param.has("init_saturation")) { if (param.has("init_saturation")) {
initStateBasic(*grid->c_grid(), *props, param, gravity[2], state); initStateBasic(Opm::UgGridHelpers::numCells(grid),
initBlackoilSurfvol(*grid->c_grid(), *props, state); Opm::UgGridHelpers::globalCell(grid),
Opm::UgGridHelpers::cartDims(grid),
Opm::UgGridHelpers::numFaces(grid),
Opm::UgGridHelpers::faceCells(grid),
Opm::UgGridHelpers::beginFaceCentroids(grid),
Opm::UgGridHelpers::beginCellCentroids(grid),
Opm::UgGridHelpers::dimensions(grid),
*props, param, gravity[2], state);
initBlackoilSurfvol(Opm::UgGridHelpers::numCells(grid), *props, state);
enum { Oil = BlackoilPhases::Liquid, Gas = BlackoilPhases::Vapour }; enum { Oil = BlackoilPhases::Liquid, Gas = BlackoilPhases::Vapour };
if (pu.phase_used[Oil] && pu.phase_used[Gas]) { if (pu.phase_used[Oil] && pu.phase_used[Gas]) {
const int np = props->numPhases(); const int numPhases = props->numPhases();
const int nc = grid->c_grid()->number_of_cells; const int numCells = Opm::UgGridHelpers::numCells(grid);
for (int c = 0; c < nc; ++c) { for (int c = 0; c < numCells; ++c) {
state.gasoilratio()[c] = state.surfacevol()[c*np + pu.phase_pos[Gas]] state.gasoilratio()[c] = state.surfacevol()[c*numPhases + pu.phase_pos[Gas]]
/ state.surfacevol()[c*np + pu.phase_pos[Oil]]; / state.surfacevol()[c*numPhases + pu.phase_pos[Oil]];
} }
} }
} else if (deck->hasKeyword("EQUIL") && props->numPhases() == 3) { } else if (deck->hasKeyword("EQUIL") && props->numPhases() == 3) {
state.init(*grid->c_grid(), props->numPhases()); state.init(Opm::UgGridHelpers::numCells(grid),
Opm::UgGridHelpers::numFaces(grid),
props->numPhases());
const double grav = param.getDefault("gravity", unit::gravity); const double grav = param.getDefault("gravity", unit::gravity);
initStateEquil(*grid->c_grid(), *props, deck, eclipseState, grav, state); initStateEquil(grid, *props, deck, eclipseState, grav, state);
state.faceflux().resize(grid->c_grid()->number_of_faces, 0.0); state.faceflux().resize(Opm::UgGridHelpers::numFaces(grid), 0.0);
} else { } else {
initBlackoilStateFromDeck(*grid->c_grid(), *props, deck, gravity[2], state); initBlackoilStateFromDeck(Opm::UgGridHelpers::numCells(grid),
Opm::UgGridHelpers::globalCell(grid),
Opm::UgGridHelpers::numFaces(grid),
Opm::UgGridHelpers::faceCells(grid),
Opm::UgGridHelpers::beginFaceCentroids(grid),
Opm::UgGridHelpers::beginCellCentroids(grid),
Opm::UgGridHelpers::dimensions(grid),
*props, deck, gravity[2], state);
} }
// The capillary pressure is scaled in new_props to match the scaled capillary pressure in props. // The capillary pressure is scaled in new_props to match the scaled capillary pressure in props.
if (deck->hasKeyword("SWATINIT")) { if (deck->hasKeyword("SWATINIT")) {
const int nc = grid->c_grid()->number_of_cells; const int numCells = Opm::UgGridHelpers::numCells(grid);
std::vector<int> cells(nc); std::vector<int> cells(numCells);
for (int c = 0; c < nc; ++c) { cells[c] = c; } for (int c = 0; c < numCells; ++c) { cells[c] = c; }
std::vector<double> pc = state.saturation(); std::vector<double> pc = state.saturation();
props->capPress(nc, state.saturation().data(), cells.data(), pc.data(),NULL); props->capPress(numCells, state.saturation().data(), cells.data(), pc.data(),NULL);
new_props->setSwatInitScaling(state.saturation(),pc); new_props->setSwatInitScaling(state.saturation(),pc);
} }
bool use_gravity = (gravity[0] != 0.0 || gravity[1] != 0.0 || gravity[2] != 0.0); bool use_gravity = (gravity[0] != 0.0 || gravity[1] != 0.0 || gravity[2] != 0.0);
const double *grav = use_gravity ? &gravity[0] : 0; const double *grav = use_gravity ? &gravity[0] : 0;
const bool use_local_perm = param.getDefault("use_local_perm", true);
std::shared_ptr<DerivedGeology> geoprops;
geoprops.reset(new Opm::DerivedGeology(grid, *new_props, eclipseState, use_local_perm, grav));
boost::any parallel_information;
// At this point all properties and state variables are correctly initialized
// If there are more than one processors involved, we now repartition the grid
// and initilialize new properties and states for it.
if( mpi_size > 1 )
{
if( param.getDefault("output_matlab", false) || param.getDefault("output_ecl", true) )
{
std::cerr << "We only support vtk output during parallel runs. \n"
<< "Please use \"output_matlab=false output_ecl=false\" to deactivate the \n"
<< "other outputs!" << std::endl;
return EXIT_FAILURE;
}
Opm::distributeGridAndData( grid, eclipseState, state, *new_props, *geoprops, parallel_information, use_local_perm );
}
// Solver for Newton iterations. // Solver for Newton iterations.
std::unique_ptr<NewtonIterationBlackoilInterface> fis_solver; std::unique_ptr<NewtonIterationBlackoilInterface> fis_solver;
if (param.getDefault("use_cpr", true)) { if (param.getDefault("use_cpr", true)) {
fis_solver.reset(new NewtonIterationBlackoilCPR(param)); fis_solver.reset(new NewtonIterationBlackoilCPR(param, parallel_information));
} else { } else {
fis_solver.reset(new NewtonIterationBlackoilSimple(param)); fis_solver.reset(new NewtonIterationBlackoilSimple(param, parallel_information));
} }
Opm::ScheduleConstPtr schedule = eclipseState->getSchedule(); Opm::ScheduleConstPtr schedule = eclipseState->getSchedule();
@ -251,14 +363,11 @@ try
// initialize variables // initialize variables
simtimer.init(timeMap); simtimer.init(timeMap);
bool use_local_perm = param.getDefault("use_local_perm", true); std::vector<double> threshold_pressures = thresholdPressures(eclipseState, grid);
Opm::DerivedGeology geology(*grid->c_grid(), *new_props, eclipseState, use_local_perm, grav);
std::vector<double> threshold_pressures = thresholdPressures(eclipseState, *grid->c_grid()); SimulatorFullyImplicitBlackoil< Grid > simulator(param,
grid,
SimulatorFullyImplicitBlackoil<UnstructuredGrid> simulator(param, *geoprops,
*grid->c_grid(),
geology,
*new_props, *new_props,
rock_comp->isActive() ? rock_comp.get() : 0, rock_comp->isActive() ? rock_comp.get() : 0,
*fis_solver, *fis_solver,
@ -270,13 +379,19 @@ try
threshold_pressures); threshold_pressures);
if (!schedule->initOnly()){ if (!schedule->initOnly()){
if( output_cout )
{
std::cout << "\n\n================ Starting main simulation loop ===============\n" std::cout << "\n\n================ Starting main simulation loop ===============\n"
<< std::flush; << std::flush;
}
SimulatorReport fullReport = simulator.run(simtimer, state); SimulatorReport fullReport = simulator.run(simtimer, state);
if( output_cout )
{
std::cout << "\n\n================ End of simulation ===============\n\n"; std::cout << "\n\n================ End of simulation ===============\n\n";
fullReport.reportFullyImplicit(std::cout); fullReport.reportFullyImplicit(std::cout);
}
if (output) { if (output) {
std::string filename = output_dir + "/walltime.txt"; std::string filename = output_dir + "/walltime.txt";
@ -286,9 +401,12 @@ try
} }
} else { } else {
outputWriter.writeInit( simtimer ); outputWriter.writeInit( simtimer );
if ( output_cout )
{
std::cout << "\n\n================ Simulation turned off ===============\n" << std::flush; std::cout << "\n\n================ Simulation turned off ===============\n" << std::flush;
} }
} }
}
catch (const std::exception &e) { catch (const std::exception &e) {
std::cerr << "Program threw an exception: " << e.what() << "\n"; std::cerr << "Program threw an exception: " << e.what() << "\n";
return EXIT_FAILURE; return EXIT_FAILURE;

View File

@ -1,402 +1,2 @@
/* #define WANT_DUNE_CORNERPOINTGRID
Copyright 2013 SINTEF ICT, Applied Mathematics. #include "flow.cpp"
Copyright 2014 Dr. Blatt - HPC-Simulation-Software & Services
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/>.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H
#include <dune/common/version.hh>
#include <opm/core/utility/platform_dependent/disable_warnings.h>
#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 3)
#include <dune/common/parallel/mpihelper.hh>
#else
#include <dune/common/mpihelper.hh>
#endif
#include <dune/grid/CpGrid.hpp>
#include <dune/grid/common/GridAdapter.hpp>
#include <opm/core/utility/platform_dependent/reenable_warnings.h>
#include <opm/core/pressure/FlowBCManager.hpp>
#include <opm/core/grid.h>
#include <opm/core/grid/cornerpoint_grid.h>
#include <opm/autodiff/GridHelpers.hpp>
#include <opm/core/wells.h>
#include <opm/core/wells/WellsManager.hpp>
#include <opm/core/utility/ErrorMacros.hpp>
#include <opm/core/simulator/initState.hpp>
#include <opm/core/simulator/initStateEquil.hpp>
#include <opm/core/simulator/SimulatorReport.hpp>
#include <opm/core/simulator/SimulatorTimer.hpp>
#include <opm/core/utility/miscUtilities.hpp>
#include <opm/core/utility/parameters/ParameterGroup.hpp>
#include <opm/core/utility/thresholdPressures.hpp> // Note: the GridHelpers must be included before this (to make overloads available). \TODO: Fix.
#include <opm/core/props/BlackoilPropertiesBasic.hpp>
#include <opm/core/props/BlackoilPropertiesFromDeck.hpp>
#include <opm/core/props/rock/RockCompressibility.hpp>
#include <opm/core/linalg/LinearSolverFactory.hpp>
#include <opm/autodiff/NewtonIterationBlackoilSimple.hpp>
#include <opm/autodiff/NewtonIterationBlackoilCPR.hpp>
#include <opm/autodiff/ExtractParallelGridInformationToISTL.hpp>
#include <opm/core/simulator/BlackoilState.hpp>
#include <opm/autodiff/WellStateFullyImplicitBlackoil.hpp>
#include <opm/autodiff/SimulatorFullyImplicitBlackoil.hpp>
#include <opm/autodiff/BlackoilPropsAdFromDeck.hpp>
#include <opm/autodiff/RedistributeDataHandles.hpp>
#include <opm/core/utility/share_obj.hpp>
#include <opm/parser/eclipse/OpmLog/OpmLog.hpp>
#include <opm/parser/eclipse/OpmLog/StreamLog.hpp>
#include <opm/parser/eclipse/OpmLog/CounterLog.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/EclipseState/checkDeck.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <memory>
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <numeric>
#include <cstdlib>
namespace
{
void warnIfUnusedParams(const Opm::parameter::ParameterGroup& param)
{
if (param.anyUnused()) {
std::cout << "-------------------- Unused parameters: --------------------\n";
param.displayUsage();
std::cout << "----------------------------------------------------------------" << std::endl;
}
}
} // anon namespace
// ----------------- Main program -----------------
int
main(int argc, char** argv)
try
{
// Must ensure an instance of the helper is created to initialise MPI.
const Dune::MPIHelper& mpi_helper = Dune::MPIHelper::instance(argc, argv);
using namespace Opm;
// Write parameters used for later reference. (only if rank is zero)
bool output_cout = ( mpi_helper.rank() == 0 );
if(output_cout)
{
std::cout << "******************************************************************************************\n";
std::cout << "* *\n";
std::cout << "* This is Flow (version 2015.04, experimental variant using dune-cornerpoint) *\n";
std::cout << "* *\n";
std::cout << "* Flow is a simulator for fully implicit three-phase black-oil flow that is part of OPM. *\n";
std::cout << "* For more information see: *\n";
std::cout << "* http://opm-project.org *\n";
std::cout << "* *\n";
std::cout << "******************************************************************************************\n\n";
}
// Read parameters, see if a deck was specified on the command line.
if ( output_cout )
{
std::cout << "--------------- Reading parameters ---------------" << std::endl;
}
parameter::ParameterGroup param(argc, argv, false, output_cout);
if( !output_cout )
{
param.disableOutput();
}
if (!param.unhandledArguments().empty()) {
if (param.unhandledArguments().size() != 1) {
std::cerr << "You can only specify a single input deck on the command line.\n";
return EXIT_FAILURE;
} else {
param.insertParameter("deck_filename", param.unhandledArguments()[0]);
}
}
// We must have an input deck. Grid and props will be read from that.
if (!param.has("deck_filename")) {
std::cerr << "This program must be run with an input deck.\n"
"Specify the deck filename either\n"
" a) as a command line argument by itself\n"
" b) as a command line parameter with the syntax deck_filename=<path to your deck>, or\n"
" c) as a parameter in a parameter file (.param or .xml) passed to the program.\n";
return EXIT_FAILURE;
}
std::shared_ptr<Dune::CpGrid> grid;
std::shared_ptr<BlackoilPropertiesInterface> props;
std::shared_ptr<BlackoilPropsAdFromDeck> new_props;
std::shared_ptr<RockCompressibility> rock_comp;
BlackoilState state;
// bool check_well_controls = false;
// int max_well_control_iterations = 0;
double gravity[3] = { 0.0 };
std::string deck_filename = param.get<std::string>("deck_filename");
// Write parameters used for later reference. (only if rank is zero)
bool output = ( mpi_helper.rank() == 0 ) && param.getDefault("output", true);
std::string output_dir;
if (output) {
// Create output directory if needed.
output_dir =
param.getDefault("output_dir", std::string("output"));
boost::filesystem::path fpath(output_dir);
try {
create_directories(fpath);
}
catch (...) {
std::cerr << "Creating directories failed: " << fpath << std::endl;
return EXIT_FAILURE;
}
// Write simulation parameters.
param.writeParam(output_dir + "/simulation.param");
}
std::string logFile = output_dir + "/LOGFILE.txt";
Opm::ParserPtr parser(new Opm::Parser());
{
std::shared_ptr<Opm::StreamLog> streamLog = std::make_shared<Opm::StreamLog>(logFile , Opm::Log::DefaultMessageTypes);
std::shared_ptr<Opm::CounterLog> counterLog = std::make_shared<Opm::CounterLog>(Opm::Log::DefaultMessageTypes);
Opm::OpmLog::addBackend( "STREAM" , streamLog );
Opm::OpmLog::addBackend( "COUNTER" , counterLog );
}
Opm::DeckConstPtr deck;
std::shared_ptr<EclipseState> eclipseState;
try {
deck = parser->parseFile(deck_filename);
Opm::checkDeck(deck);
eclipseState.reset(new Opm::EclipseState(deck));
}
catch (const std::invalid_argument& e) {
std::cerr << "Failed to create valid ECLIPSESTATE object. See logfile: " << logFile << std::endl;
std::cerr << "Exception caught: " << e.what() << std::endl;
return EXIT_FAILURE;
}
// Grid init
grid.reset(new Dune::CpGrid);
std::vector<double> porv = eclipseState->getDoubleGridProperty("PORV")->getData();
grid->processEclipseFormat(deck, false, false, false, porv);
// Possibly override IOConfig setting (from deck) for how often RESTART files should get written to disk (every N report step)
if (param.has("output_interval")) {
int output_interval = param.get<int>("output_interval");
IOConfigPtr ioConfig = eclipseState->getIOConfig();
ioConfig->overrideRestartWriteInterval((size_t)output_interval);
}
const PhaseUsage pu = Opm::phaseUsageFromDeck(deck);
Opm::BlackoilOutputWriter outputWriter(*grid, param, eclipseState, pu );
// Rock and fluid init
props.reset(new BlackoilPropertiesFromDeck(deck, eclipseState,
Opm::UgGridHelpers::numCells(*grid),
Opm::UgGridHelpers::globalCell(*grid),
Opm::UgGridHelpers::cartDims(*grid),
Opm::UgGridHelpers::beginCellCentroids(*grid),
Opm::UgGridHelpers::dimensions(*grid), param));
new_props.reset(new BlackoilPropsAdFromDeck(deck, eclipseState, *grid));
// check_well_controls = param.getDefault("check_well_controls", false);
// max_well_control_iterations = param.getDefault("max_well_control_iterations", 10);
// Rock compressibility.
rock_comp.reset(new RockCompressibility(deck, eclipseState));
// Gravity.
gravity[2] = deck->hasKeyword("NOGRAV") ? 0.0 : unit::gravity;
// Init state variables (saturation and pressure).
if (param.has("init_saturation")) {
initStateBasic(grid->numCells(), &(grid->globalCell())[0],
&(grid->logicalCartesianSize()[0]),
grid->numFaces(), UgGridHelpers::faceCells(*grid),
grid->beginFaceCentroids(),
grid->beginCellCentroids(), Dune::CpGrid::dimension,
*props, param, gravity[2], state);
initBlackoilSurfvol(grid->numCells(), *props, state);
enum { Oil = BlackoilPhases::Liquid, Gas = BlackoilPhases::Vapour };
if (pu.phase_used[Oil] && pu.phase_used[Gas]) {
const int np = props->numPhases();
const int nc = grid->numCells();
for (int c = 0; c < nc; ++c) {
state.gasoilratio()[c] = state.surfacevol()[c*np + pu.phase_pos[Gas]]
/ state.surfacevol()[c*np + pu.phase_pos[Oil]];
}
}
} else if (deck->hasKeyword("EQUIL") && props->numPhases() == 3) {
state.init(grid->numCells(), grid->numFaces(), props->numPhases());
const double grav = param.getDefault("gravity", unit::gravity);
initStateEquil(*grid, *props, deck, eclipseState, grav, state);
state.faceflux().resize(grid->numFaces(), 0.0);
} else {
initBlackoilStateFromDeck(grid->numCells(), &(grid->globalCell())[0],
grid->numFaces(), UgGridHelpers::faceCells(*grid),
grid->beginFaceCentroids(),
grid->beginCellCentroids(), Dune::CpGrid::dimension,
*props, deck, gravity[2], state);
}
// The capillary pressure is scaled in new_props to match the scaled capillary pressure in props.
if (deck->hasKeyword("SWATINIT")) {
const int nc = grid->numCells();
std::vector<int> cells(nc);
for (int c = 0; c < nc; ++c) { cells[c] = c; }
std::vector<double> pc = state.saturation();
props->capPress(nc, state.saturation().data(), cells.data(), pc.data(),NULL);
new_props->setSwatInitScaling(state.saturation(),pc);
}
bool use_gravity = (gravity[0] != 0.0 || gravity[1] != 0.0 || gravity[2] != 0.0);
const double *grav = use_gravity ? &gravity[0] : 0;
std::shared_ptr<DerivedGeology> geoprops;
std::shared_ptr<DerivedGeology> distributed_geology;
geoprops.reset(new Opm::DerivedGeology(*grid, *new_props, eclipseState, false, grav));
distributed_geology = geoprops; // copy for serial case.
BlackoilState distributed_state;
std::shared_ptr<Opm::BlackoilPropsAdFromDeck> distributed_props = new_props;
Dune::CpGrid distributed_grid = *grid;
// At this point all properties and state variables are correctly initialized
// If there are more than one processors involved, we now repartition the grid
// and initilialize new properties and states for it.
bool must_distribute = ( mpi_helper.size() > 1 );
if( must_distribute )
{
if( param.getDefault("output_matlab", false) || param.getDefault("output_ecl", true) )
{
std::cerr << "We only support vtk output during parallel runs. \n"
<< "Please use \"output_matlab=false output_ecl=false\" to deactivate the \n"
<< "other outputs!" << std::endl;
return EXIT_FAILURE;
}
grid->loadBalance();
Dune::CpGrid global_grid = *grid;
distributed_grid = *grid;
global_grid.switchToGlobalView();
distributed_grid.switchToDistributedView();
distributed_props = std::make_shared<BlackoilPropsAdFromDeck>(*new_props, grid->numCells());
distributed_state.init(grid->numCells(), grid->numFaces(), state.numPhases());
// init does not resize surfacevol. Do it manually.
distributed_state.surfacevol().resize(grid->numCells()*state.numPhases(),
std::numeric_limits<double>::max());
Opm::BlackoilStateDataHandle state_handle(global_grid, distributed_grid,
state, distributed_state);
Opm::BlackoilPropsDataHandle props_handle(*new_props,
*distributed_props);
grid->scatterData(state_handle);
grid->scatterData(props_handle);
// Create a distributed Geology. Some values will be updated using communication
// below
distributed_geology.reset(new Opm::DerivedGeology(distributed_grid,
*distributed_props, eclipseState,
false, grav));
Opm::GeologyDataHandle geo_handle(global_grid, distributed_grid,
*geoprops, *distributed_geology);
grid->scatterData(geo_handle);
}
// Solver for Newton iterations.
std::unique_ptr<NewtonIterationBlackoilInterface> fis_solver;
boost::any parallel_information;
Opm::extractParallelGridInformationToISTL(*grid, parallel_information);
if (param.getDefault("use_cpr", true)) {
fis_solver.reset(new NewtonIterationBlackoilCPR(param, parallel_information));
} else {
fis_solver.reset(new NewtonIterationBlackoilSimple(param, parallel_information));
}
Opm::ScheduleConstPtr schedule = eclipseState->getSchedule();
Opm::TimeMapConstPtr timeMap(schedule->getTimeMap());
SimulatorTimer simtimer;
// initialize variables
simtimer.init(timeMap);
std::vector<double> threshold_pressures = thresholdPressures(eclipseState, distributed_grid);
SimulatorFullyImplicitBlackoil<Dune::CpGrid> simulator(param,
distributed_grid,
*distributed_geology,
*distributed_props,
rock_comp->isActive() ? rock_comp.get() : 0,
*fis_solver,
grav,
deck->hasKeyword("DISGAS"),
deck->hasKeyword("VAPOIL"),
eclipseState,
outputWriter,
threshold_pressures);
if (!schedule->initOnly()){
if( output_cout )
{
std::cout << "\n\n================ Starting main simulation loop ===============\n"
<< std::flush;
}
SimulatorReport fullReport = simulator.run(simtimer, must_distribute ? distributed_state : state);
if( output_cout )
{
std::cout << "\n\n================ End of simulation ===============\n\n";
fullReport.reportFullyImplicit(std::cout);
}
if (output) {
std::string filename = output_dir + "/walltime.txt";
std::fstream tot_os(filename.c_str(),std::fstream::trunc | std::fstream::out);
fullReport.reportParam(tot_os);
warnIfUnusedParams(param);
}
} else {
outputWriter.writeInit( simtimer );
if ( output_cout )
{
std::cout << "\n\n================ Simulation turned off ===============\n" << std::flush;
}
}
}
catch (const std::exception &e) {
std::cerr << "Program threw an exception: " << e.what() << "\n";
return EXIT_FAILURE;
}

View File

@ -2,6 +2,7 @@
Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services. Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services.
Coypright 2015 NTNU Coypright 2015 NTNU
Copyright 2015 Statoil AS Copyright 2015 Statoil AS
Copyright 2015 IRIS AS
This file is part of the Open Porous Media project (OPM). This file is part of the Open Porous Media project (OPM).
@ -18,14 +19,31 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>. along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef OPM_REDISTRIBUTEDATAHANDLES_HEADER
#define OPM_REDISTRIBUTEDATAHANDLES_HEADER
#include <opm/core/simulator/BlackoilState.hpp>
#include <opm/autodiff/BlackoilPropsAdFromDeck.hpp> #include <opm/autodiff/BlackoilPropsAdFromDeck.hpp>
#include <opm/core/simulator/BlackoilState.hpp> #include <opm/autodiff/ExtractParallelGridInformationToISTL.hpp>
#include<boost/any.hpp>
namespace Opm namespace Opm
{ {
template <class Grid>
inline void distributeGridAndData( Grid& ,
Opm::EclipseStateConstPtr eclipseState,
BlackoilState& ,
BlackoilPropsAdFromDeck& ,
DerivedGeology&,
boost::any& ,
const bool )
{
}
#if HAVE_DUNE_CORNERPOINT
/// \brief a data handle to distribute Derived Geology /// \brief a data handle to distribute Derived Geology
class GeologyDataHandle class GeologyDataHandle
{ {
@ -288,4 +306,54 @@ private:
std::size_t size_; std::size_t size_;
}; };
inline
void distributeGridAndData( Dune::CpGrid& grid,
Opm::EclipseStateConstPtr eclipseState,
BlackoilState& state,
BlackoilPropsAdFromDeck& properties,
DerivedGeology& geology,
boost::any& parallelInformation,
const bool useLocalPerm)
{
std::shared_ptr<DerivedGeology> distributed_geology;
BlackoilState distributed_state;
std::shared_ptr<Opm::BlackoilPropsAdFromDeck> distributed_props;// = new_props;
Dune::CpGrid global_grid ( grid );
global_grid.switchToGlobalView();
// distribute the grid and switch to the distributed view
grid.loadBalance();
grid.switchToDistributedView();
distributed_props = std::make_shared<BlackoilPropsAdFromDeck>(properties, grid.numCells());
distributed_state.init(grid.numCells(), grid.numFaces(), state.numPhases());
// init does not resize surfacevol. Do it manually.
distributed_state.surfacevol().resize(grid.numCells()*state.numPhases(),
std::numeric_limits<double>::max());
Opm::BlackoilStateDataHandle state_handle(global_grid, grid,
state, distributed_state);
Opm::BlackoilPropsDataHandle props_handle(properties,
*distributed_props);
grid.scatterData(state_handle);
grid.scatterData(props_handle);
// Create a distributed Geology. Some values will be updated using communication
// below
distributed_geology.reset(new Opm::DerivedGeology(grid,
*distributed_props, eclipseState,
useLocalPerm, geology.gravity()));
Opm::GeologyDataHandle geo_handle(global_grid, grid,
geology, *distributed_geology);
grid.scatterData(geo_handle);
// copy states
properties = *distributed_props;
geology = *distributed_geology;
state = distributed_state;
Opm::extractParallelGridInformationToISTL(grid, parallelInformation);
}
#endif
} // end namespace Opm } // end namespace Opm
#endif