mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge remote-tracking branch 'origin/master' into frankenstein_merge_master
This commit is contained in:
commit
36b00ba570
@ -146,6 +146,4 @@ if (HAVE_OPM_DATA)
|
||||
endif()
|
||||
|
||||
include (${CMAKE_CURRENT_SOURCE_DIR}/compareECLFiles.cmake)
|
||||
|
||||
|
||||
endif()
|
||||
|
@ -1,9 +1,9 @@
|
||||
# Set absolute tolerance to be used for testing
|
||||
set(abs_tol 2e-2)
|
||||
set(rel_tol 1e-5)
|
||||
|
||||
# Define some paths
|
||||
set(RESULT_PATH ${PROJECT_BINARY_DIR}/tests/results)
|
||||
# Create directory to store upscaling results in
|
||||
set(BASE_RESULT_PATH ${PROJECT_BINARY_DIR}/tests/results)
|
||||
|
||||
###########################################################################
|
||||
# TEST: compareECLFiles
|
||||
@ -14,6 +14,7 @@ set(RESULT_PATH ${PROJECT_BINARY_DIR}/tests/results)
|
||||
#
|
||||
macro (add_test_compareECLFiles casename filename)
|
||||
|
||||
set(RESULT_PATH ${BASE_RESULT_PATH}/${casename})
|
||||
# Add test that runs flow and outputs the results to file
|
||||
opm_add_test(compareECLFiles_${filename} NO_COMPILE
|
||||
EXE_NAME flow
|
||||
@ -21,9 +22,8 @@ macro (add_test_compareECLFiles casename filename)
|
||||
${CMAKE_BINARY_DIR}/bin
|
||||
${filename}
|
||||
${abs_tol} ${rel_tol}
|
||||
${SUMMARY_REGRESSION_TEST_COMMAND}
|
||||
${RESTART_REGRESSION_TEST_COMMAND}
|
||||
${INIT_REGRESSION_TEST_COMMAND}
|
||||
${COMPARE_SUMMARY_COMMAND}
|
||||
${COMPARE_ECL_COMMAND}
|
||||
TEST_ARGS ${OPM_DATA_ROOT}/${casename}/${filename}.DATA )
|
||||
endmacro (add_test_compareECLFiles)
|
||||
|
||||
@ -32,8 +32,8 @@ if(NOT TARGET test-suite)
|
||||
add_custom_target(test-suite)
|
||||
endif()
|
||||
|
||||
|
||||
opm_set_test_driver(${PROJECT_SOURCE_DIR}/tests/run-regressionTest.sh "")
|
||||
|
||||
add_test_compareECLFiles(spe9 SPE9_CP)
|
||||
|
||||
add_test_compareECLFiles(spe1 SPE1CASE2)
|
||||
add_test_compareECLFiles(spe3 SPE3CASE1)
|
||||
add_test_compareECLFiles(spe9 SPE9_CP_SHORT)
|
||||
|
@ -93,8 +93,8 @@ namespace Opm {
|
||||
struct SimulatorData {
|
||||
SimulatorData(int num_phases);
|
||||
std::vector<ReservoirResidualQuant> rq;
|
||||
ADB rs;
|
||||
ADB rv;
|
||||
ADB rsSat;
|
||||
ADB rvSat;
|
||||
};
|
||||
|
||||
typedef typename ModelTraits<Implementation>::ReservoirState ReservoirState;
|
||||
@ -212,6 +212,9 @@ namespace Opm {
|
||||
ReservoirState& reservoir_state,
|
||||
WellState& well_state);
|
||||
|
||||
/// Return true if this is a parallel run.
|
||||
bool isParallel() const;
|
||||
|
||||
/// Return true if output to cout is wanted.
|
||||
bool terminalOutputEnabled() const;
|
||||
|
||||
@ -284,7 +287,7 @@ namespace Opm {
|
||||
bool use_threshold_pressure_;
|
||||
V threshold_pressures_by_connection_;
|
||||
|
||||
SimulatorData sd_;
|
||||
mutable SimulatorData sd_;
|
||||
std::vector<PhasePresence> phaseCondition_;
|
||||
|
||||
// Well Model
|
||||
|
@ -185,7 +185,26 @@ typedef Eigen::Array<double,
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class Grid, class WellModel, class Implementation>
|
||||
bool
|
||||
BlackoilModelBase<Grid, WellModel, Implementation>::
|
||||
isParallel() const
|
||||
{
|
||||
#if HAVE_MPI
|
||||
if ( linsolver_.parallelInformation().type() !=
|
||||
typeid(ParallelISTLInformation) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& comm =boost::any_cast<const ParallelISTLInformation&>(linsolver_.parallelInformation()).communicator();
|
||||
return comm.size() > 1;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template <class Grid, class WellModel, class Implementation>
|
||||
@ -403,8 +422,8 @@ typedef Eigen::Array<double,
|
||||
BlackoilModelBase<Grid, WellModel, Implementation>::
|
||||
SimulatorData::SimulatorData(int num_phases)
|
||||
: rq(num_phases)
|
||||
, rs(ADB::null())
|
||||
, rv(ADB::null())
|
||||
, rsSat(ADB::null())
|
||||
, rvSat(ADB::null())
|
||||
{
|
||||
}
|
||||
|
||||
@ -591,17 +610,17 @@ typedef Eigen::Array<double,
|
||||
|
||||
if (active_[ Oil ]) {
|
||||
// RS and RV is only defined if both oil and gas phase are active.
|
||||
const ADB rsSat = fluidRsSat(state.canonical_phase_pressures[ Oil ], so , cells_);
|
||||
sd_.rsSat = fluidRsSat(state.canonical_phase_pressures[ Oil ], so , cells_);
|
||||
if (has_disgas_) {
|
||||
state.rs = (1-isRs_)*rsSat + isRs_*xvar;
|
||||
state.rs = (1-isRs_)*sd_.rsSat + isRs_*xvar;
|
||||
} else {
|
||||
state.rs = rsSat;
|
||||
state.rs = sd_.rsSat;
|
||||
}
|
||||
const ADB rvSat = fluidRvSat(state.canonical_phase_pressures[ Gas ], so , cells_);
|
||||
sd_.rvSat = fluidRvSat(state.canonical_phase_pressures[ Gas ], so , cells_);
|
||||
if (has_vapoil_) {
|
||||
state.rv = (1-isRv_)*rvSat + isRv_*xvar;
|
||||
state.rv = (1-isRv_)*sd_.rvSat + isRv_*xvar;
|
||||
} else {
|
||||
state.rv = rvSat;
|
||||
state.rv = sd_.rvSat;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1219,6 +1238,7 @@ typedef Eigen::Array<double,
|
||||
if (has_disgas_) {
|
||||
const V rsSat0 = fluidRsSat(p_old, s_old.col(pu.phase_pos[Oil]), cells_);
|
||||
const V rsSat = fluidRsSat(p, so, cells_);
|
||||
sd_.rsSat = ADB::constant(rsSat);
|
||||
// The obvious case
|
||||
auto hasGas = (sg > 0 && isRs_ == 0);
|
||||
|
||||
@ -1244,6 +1264,7 @@ typedef Eigen::Array<double,
|
||||
const V gaspress = computeGasPressure(p, sw, so, sg);
|
||||
const V rvSat0 = fluidRvSat(gaspress_old, s_old.col(pu.phase_pos[Oil]), cells_);
|
||||
const V rvSat = fluidRvSat(gaspress, so, cells_);
|
||||
sd_.rvSat = ADB::constant(rvSat);
|
||||
|
||||
// The obvious case
|
||||
auto hasOil = (so > 0 && isRv_ == 0);
|
||||
@ -2160,8 +2181,16 @@ typedef Eigen::Array<double,
|
||||
fip[4] = rv.value() * fip[pg];
|
||||
}
|
||||
|
||||
const int dims = *std::max_element(fipnum.begin(), fipnum.end());
|
||||
// For a parallel run this is just a local maximum and needs to be updated later
|
||||
int dims = *std::max_element(fipnum.begin(), fipnum.end());
|
||||
std::vector<V> values(dims, V::Zero(7));
|
||||
|
||||
const V hydrocarbon = saturation[Oil].value() + saturation[Gas].value();
|
||||
V hcpv;
|
||||
V pres;
|
||||
|
||||
if ( !isParallel() )
|
||||
{
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
for (int c = 0; c < nc; ++c) {
|
||||
if (fipnum[c] != 0) {
|
||||
@ -2170,10 +2199,9 @@ typedef Eigen::Array<double,
|
||||
}
|
||||
}
|
||||
|
||||
// compute PAV and PORV for every regions.
|
||||
const V hydrocarbon = saturation[Oil].value() + saturation[Gas].value();
|
||||
V hcpv = V::Zero(nc);
|
||||
V pres = V::Zero(nc);
|
||||
hcpv = V::Zero(dims);
|
||||
pres = V::Zero(dims);
|
||||
|
||||
for (int c = 0; c < nc; ++c) {
|
||||
if (fipnum[c] != 0) {
|
||||
hcpv[fipnum[c]-1] += pv[c] * hydrocarbon[c];
|
||||
@ -2182,7 +2210,56 @@ typedef Eigen::Array<double,
|
||||
values[fipnum[c]-1][6] += pv[c] * pressure.value()[c] * hydrocarbon[c];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if HAVE_MPI
|
||||
// mask[c] is 1 if we need to compute something in parallel
|
||||
const auto & pinfo =
|
||||
boost::any_cast<const ParallelISTLInformation&>(linsolver_.parallelInformation());
|
||||
const auto& mask = pinfo.getOwnerMask();
|
||||
auto comm = pinfo.communicator();
|
||||
// Compute the global dims value and resize values accordingly.
|
||||
dims = comm.max(dims);
|
||||
values.resize(dims, V::Zero(7));
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
for (int c = 0; c < nc; ++c) {
|
||||
if (fipnum[c] != 0 && mask[c]) {
|
||||
values[fipnum[c]-1][i] += fip[i][c];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hcpv = V::Zero(dims);
|
||||
pres = V::Zero(dims);
|
||||
|
||||
for (int c = 0; c < nc; ++c) {
|
||||
if (fipnum[c] != 0 && mask[c]) {
|
||||
hcpv[fipnum[c]-1] += pv[c] * hydrocarbon[c];
|
||||
pres[fipnum[c]-1] += pv[c] * pressure.value()[c];
|
||||
values[fipnum[c]-1][5] += pv[c];
|
||||
values[fipnum[c]-1][6] += pv[c] * pressure.value()[c] * hydrocarbon[c];
|
||||
}
|
||||
}
|
||||
|
||||
// For the frankenstein branch we hopefully can turn values into a vanilla
|
||||
// std::vector<double>, use some index magic above, use one communication
|
||||
// to sum up the vector entries instead of looping over the regions.
|
||||
for(int reg=0; reg < dims; ++reg)
|
||||
{
|
||||
comm.sum(values[reg].data(), values[reg].size());
|
||||
}
|
||||
|
||||
comm.sum(hcpv.data(), hcpv.size());
|
||||
comm.sum(pres.data(), pres.size());
|
||||
#else
|
||||
// This should never happen!
|
||||
OPM_THROW(std::logic_error, "HAVE_MPI should be defined if we are running in parallel");
|
||||
#endif
|
||||
}
|
||||
|
||||
// compute PAV and PORV for every regions.
|
||||
for (int reg = 0; reg < dims; ++reg) {
|
||||
if (hcpv[reg] != 0) {
|
||||
values[reg][6] /= hcpv[reg];
|
||||
@ -2192,7 +2269,6 @@ typedef Eigen::Array<double,
|
||||
}
|
||||
|
||||
return values;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Opm
|
||||
|
@ -220,17 +220,17 @@ namespace Opm {
|
||||
if (active_[ Oil ]) {
|
||||
// RS and RV is only defined if both oil and gas phase are active.
|
||||
state.canonical_phase_pressures = computePressures(state.pressure, state.saturation[pu.phase_pos[ Water ]], so, sg, state.solvent_saturation);
|
||||
const ADB rsSat = fluidRsSat(state.canonical_phase_pressures[ Oil ], so , cells_);
|
||||
sd_.rsSat = fluidRsSat(state.canonical_phase_pressures[ Oil ], so , cells_);
|
||||
if (has_disgas_) {
|
||||
state.rs = (1-Base::isRs_)*rsSat + Base::isRs_*xvar;
|
||||
state.rs = (1-Base::isRs_)*sd_.rsSat + Base::isRs_*xvar;
|
||||
} else {
|
||||
state.rs = rsSat;
|
||||
state.rs = sd_.rsSat;
|
||||
}
|
||||
const ADB rvSat = fluidRvSat(state.canonical_phase_pressures[ Gas ], so , cells_);
|
||||
sd_.rvSat = fluidRvSat(state.canonical_phase_pressures[ Gas ], so , cells_);
|
||||
if (has_vapoil_) {
|
||||
state.rv = (1-Base::isRv_)*rvSat + Base::isRv_*xvar;
|
||||
state.rv = (1-Base::isRv_)*sd_.rvSat + Base::isRv_*xvar;
|
||||
} else {
|
||||
state.rv = rvSat;
|
||||
state.rv = sd_.rvSat;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -549,6 +549,7 @@ namespace Opm {
|
||||
if (has_disgas_) {
|
||||
const V rsSat0 = fluidRsSat(p_old, s_old.col(pu.phase_pos[Oil]), cells_);
|
||||
const V rsSat = fluidRsSat(p, so, cells_);
|
||||
sd_.rsSat = ADB::constant(rsSat);
|
||||
// The obvious case
|
||||
auto hasGas = (sg > 0 && Base::isRs_ == 0);
|
||||
|
||||
@ -574,6 +575,7 @@ namespace Opm {
|
||||
const V gaspress = computeGasPressure(p, sw, so, sg);
|
||||
const V rvSat0 = fluidRvSat(gaspress_old, s_old.col(pu.phase_pos[Oil]), cells_);
|
||||
const V rvSat = fluidRvSat(gaspress, so, cells_);
|
||||
sd_.rvSat = ADB::constant(rvSat);
|
||||
|
||||
// The obvious case
|
||||
auto hasOil = (so > 0 && Base::isRv_ == 0);
|
||||
|
@ -215,6 +215,9 @@ namespace Opm
|
||||
std::unique_ptr<Simulator> simulator_;
|
||||
// create log file
|
||||
std::string logFile_;
|
||||
// The names of wells that are artifically defunct in parallel runs.
|
||||
// Those wells are handled on a another process.
|
||||
std::unordered_set<std::string> defunct_well_names_;
|
||||
// ------------ Methods ------------
|
||||
|
||||
|
||||
@ -599,6 +602,7 @@ namespace Opm
|
||||
// If there are more than one processors involved, we now repartition the grid
|
||||
// and initilialize new properties and states for it.
|
||||
if (must_distribute_) {
|
||||
defunct_well_names_ =
|
||||
distributeGridAndData(grid_init_->grid(), deck_, eclipse_state_,
|
||||
*state_, *fluidprops_, *geoprops_,
|
||||
material_law_manager_, threshold_pressures_,
|
||||
@ -812,7 +816,8 @@ namespace Opm
|
||||
Base::deck_->hasKeyword("VAPOIL"),
|
||||
Base::eclipse_state_,
|
||||
*Base::output_writer_,
|
||||
Base::threshold_pressures_));
|
||||
Base::threshold_pressures_,
|
||||
Base::defunct_well_names_));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -111,21 +111,8 @@ namespace Opm
|
||||
// Get grid from parser.
|
||||
EclipseGridConstPtr eclgrid = eclState->getInputGrid();
|
||||
|
||||
// Pore volume.
|
||||
// New keywords MINPVF will add some PV due to OPM cpgrid process algorithm.
|
||||
// But the default behavior is to get the comparable pore volume with ECLIPSE.
|
||||
for (int cellIdx = 0; cellIdx < numCells; ++cellIdx) {
|
||||
int cartesianCellIdx = AutoDiffGrid::globalCell(grid)[cellIdx];
|
||||
pvol_[cellIdx] =
|
||||
props.porosity()[cellIdx]
|
||||
* multpv[cartesianCellIdx]
|
||||
* ntg[cartesianCellIdx];
|
||||
if (eclgrid->getMinpvMode() == MinpvMode::ModeEnum::OpmFIL) {
|
||||
pvol_[cellIdx] *= AutoDiffGrid::cellVolume(grid, cellIdx);
|
||||
} else {
|
||||
pvol_[cellIdx] *= eclgrid->getCellVolume(cartesianCellIdx);
|
||||
}
|
||||
}
|
||||
// update the pore volume of all active cells in the grid
|
||||
computePoreVolume_(grid, eclState);
|
||||
|
||||
// Non-neighbour connections.
|
||||
nnc_ = eclState->getInputNNC();
|
||||
@ -304,6 +291,59 @@ namespace Opm
|
||||
Opm::EclipseStateConstPtr eclState,
|
||||
std::vector<double> &ntg);
|
||||
|
||||
template <class GridType>
|
||||
void computePoreVolume_(const GridType &grid,
|
||||
Opm::EclipseStateConstPtr eclState)
|
||||
{
|
||||
int numCells = Opm::AutoDiffGrid::numCells(grid);
|
||||
const int* globalCell = Opm::UgGridHelpers::globalCell(grid);
|
||||
EclipseGridConstPtr eclGrid = eclState->getInputGrid();
|
||||
const int nx = eclGrid->getNX();
|
||||
const int ny = eclGrid->getNY();
|
||||
|
||||
// the "raw" pore volume.
|
||||
const std::vector<double>& porvData =
|
||||
eclState->get3DProperties().getDoubleGridProperty("PORV").getData();
|
||||
pvol_.resize(numCells);
|
||||
|
||||
// the "activation number" grid property
|
||||
const std::vector<int>& actnumData =
|
||||
eclState->get3DProperties().getIntGridProperty("ACTNUM").getData();
|
||||
|
||||
|
||||
for (int cellIdx = 0; cellIdx < numCells; ++cellIdx) {
|
||||
const int cellCartIdx = globalCell[cellIdx];
|
||||
|
||||
double cellPoreVolume = porvData[cellCartIdx];
|
||||
|
||||
if (eclGrid->getMinpvMode() == MinpvMode::ModeEnum::OpmFIL) {
|
||||
// Sum the pore volumes of the cells above which have been deactivated
|
||||
// because their volume less is less than the MINPV threshold
|
||||
for (int aboveCellCartIdx = cellCartIdx - nx*ny;
|
||||
aboveCellCartIdx >= 0;
|
||||
aboveCellCartIdx -= nx*ny)
|
||||
{
|
||||
if (porvData[aboveCellCartIdx] >= eclGrid->getMinpvValue()) {
|
||||
// stop if we encounter a cell which has a pore volume which is
|
||||
// at least as large as the minimum one
|
||||
break;
|
||||
}
|
||||
|
||||
const double aboveCellVolume = eclGrid->getCellVolume(aboveCellCartIdx);
|
||||
if (actnumData[aboveCellCartIdx] == 0 && aboveCellVolume > 1e-6) {
|
||||
// stop at explicitly disabled cells, but only if their volume is
|
||||
// greater than 10^-6 m^3
|
||||
break;
|
||||
}
|
||||
|
||||
cellPoreVolume += porvData[aboveCellCartIdx];
|
||||
}
|
||||
}
|
||||
|
||||
pvol_[cellIdx] = cellPoreVolume;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Grid>
|
||||
void pinchProcess_(const Grid& grid,
|
||||
const Opm::EclipseState& eclState,
|
||||
|
@ -698,7 +698,7 @@ namespace Opm
|
||||
SolutionVector dx = newtonIncrement.computeNewtonIncrement( residual );
|
||||
// get number of linear iterations
|
||||
iterations_ = newtonIncrement.iterations();
|
||||
return std::move(dx);
|
||||
return dx;
|
||||
}
|
||||
|
||||
const boost::any& NewtonIterationBlackoilInterleaved::parallelInformation() const
|
||||
|
@ -19,6 +19,8 @@
|
||||
#ifndef OPM_PARALLELDEBUGOUTPUT_HEADER_INCLUDED
|
||||
#define OPM_PARALLELDEBUGOUTPUT_HEADER_INCLUDED
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include <opm/common/data/SimulationDataContainer.hpp>
|
||||
|
||||
|
||||
@ -543,7 +545,14 @@ namespace Opm
|
||||
Opm::UgGridHelpers::beginFaceCentroids( globalGrid ),
|
||||
permeability_,
|
||||
dynamic_list_econ_limited,
|
||||
false);
|
||||
false
|
||||
// We need to pass the optionaly arguments
|
||||
// as we get the following error otherwise
|
||||
// with c++ (Debian 4.9.2-10) 4.9.2 and -std=c++11
|
||||
// converting to ‘const std::unordered_set<std::basic_string<char> >’ from initializer list would use explicit constructor
|
||||
, std::vector<double>(),
|
||||
std::unordered_set<std::string>()
|
||||
);
|
||||
|
||||
const Wells* wells = wells_manager.c_wells();
|
||||
globalWellState_.init(wells, *globalReservoirState_, globalWellState_ );
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services.
|
||||
Copyright 2015-2016 Dr. Blatt - HPC-Simulation-Software & Services.
|
||||
Coypright 2015 NTNU
|
||||
Copyright 2015 Statoil AS
|
||||
Copyright 2015-2016 Statoil AS
|
||||
Copyright 2015 IRIS AS
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
@ -22,6 +22,9 @@
|
||||
#ifndef OPM_REDISTRIBUTEDATAHANDLES_HEADER
|
||||
#define OPM_REDISTRIBUTEDATAHANDLES_HEADER
|
||||
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
|
||||
#include <opm/core/simulator/BlackoilState.hpp>
|
||||
|
||||
#include <opm/autodiff/BlackoilPropsAdFromDeck.hpp>
|
||||
@ -33,7 +36,8 @@ namespace Opm
|
||||
{
|
||||
|
||||
template <class Grid>
|
||||
inline void distributeGridAndData( Grid& ,
|
||||
inline std::unordered_set<std::string>
|
||||
distributeGridAndData( Grid& ,
|
||||
Opm::DeckConstPtr ,
|
||||
EclipseStateConstPtr ,
|
||||
BlackoilState& ,
|
||||
@ -44,6 +48,7 @@ inline void distributeGridAndData( Grid& ,
|
||||
boost::any& ,
|
||||
const bool )
|
||||
{
|
||||
return std::unordered_set<std::string>();
|
||||
}
|
||||
|
||||
#if HAVE_OPM_GRID && HAVE_MPI
|
||||
@ -413,7 +418,8 @@ private:
|
||||
};
|
||||
|
||||
inline
|
||||
void distributeGridAndData( Dune::CpGrid& grid,
|
||||
std::unordered_set<std::string>
|
||||
distributeGridAndData( Dune::CpGrid& grid,
|
||||
Opm::DeckConstPtr deck,
|
||||
EclipseStateConstPtr eclipseState,
|
||||
BlackoilState& state,
|
||||
@ -428,7 +434,9 @@ void distributeGridAndData( Dune::CpGrid& grid,
|
||||
global_grid.switchToGlobalView();
|
||||
|
||||
// distribute the grid and switch to the distributed view
|
||||
grid.loadBalance(eclipseState, geology.transmissibility().data());
|
||||
using std::get;
|
||||
auto my_defunct_wells = get<1>(grid.loadBalance(eclipseState,
|
||||
geology.transmissibility().data()));
|
||||
grid.switchToDistributedView();
|
||||
std::vector<int> compressedToCartesianIdx;
|
||||
Opm::createGlobalCellArray(grid, compressedToCartesianIdx);
|
||||
@ -493,6 +501,8 @@ void distributeGridAndData( Dune::CpGrid& grid,
|
||||
material_law_manager = distributed_material_law_manager;
|
||||
threshold_pressures = distributed_pressures;
|
||||
extractParallelGridInformationToISTL(grid, parallelInformation);
|
||||
|
||||
return my_defunct_wells;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -130,7 +130,8 @@ namespace Opm
|
||||
const bool vapoil,
|
||||
std::shared_ptr<EclipseState> eclipse_state,
|
||||
OutputWriter& output_writer,
|
||||
const std::vector<double>& threshold_pressures_by_face);
|
||||
const std::vector<double>& threshold_pressures_by_face,
|
||||
const std::unordered_set<std::string>& defunct_well_names);
|
||||
|
||||
/// Run the simulation.
|
||||
/// This will run succesive timesteps until timer.done() is true. It will
|
||||
@ -214,6 +215,10 @@ namespace Opm
|
||||
std::vector<double> threshold_pressures_by_face_;
|
||||
// Whether this a parallel simulation or not
|
||||
bool is_parallel_run_;
|
||||
// The names of wells that should be defunct
|
||||
// (e.g. in a parallel run when they are handeled by
|
||||
// a different process)
|
||||
std::unordered_set<std::string> defunct_well_names_;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <locale>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Events.hpp>
|
||||
@ -43,7 +44,8 @@ namespace Opm
|
||||
const bool has_vapoil,
|
||||
std::shared_ptr<EclipseState> eclipse_state,
|
||||
OutputWriter& output_writer,
|
||||
const std::vector<double>& threshold_pressures_by_face)
|
||||
const std::vector<double>& threshold_pressures_by_face,
|
||||
const std::unordered_set<std::string>& defunct_well_names)
|
||||
: param_(param),
|
||||
model_param_(param),
|
||||
solver_param_(param),
|
||||
@ -60,7 +62,8 @@ namespace Opm
|
||||
output_writer_(output_writer),
|
||||
rateConverter_(props_, std::vector<int>(AutoDiffGrid::numCells(grid_), 0)),
|
||||
threshold_pressures_by_face_(threshold_pressures_by_face),
|
||||
is_parallel_run_( false )
|
||||
is_parallel_run_( false ),
|
||||
defunct_well_names_(defunct_well_names)
|
||||
{
|
||||
// Misc init.
|
||||
const int num_cells = AutoDiffGrid::numCells(grid);
|
||||
@ -167,7 +170,8 @@ namespace Opm
|
||||
props_.permeability(),
|
||||
dynamic_list_econ_limited,
|
||||
is_parallel_run_,
|
||||
well_potentials);
|
||||
well_potentials,
|
||||
defunct_well_names_);
|
||||
const Wells* wells = wells_manager.c_wells();
|
||||
WellState well_state;
|
||||
well_state.init(wells, state, prev_well_state);
|
||||
@ -698,8 +702,37 @@ namespace Opm
|
||||
const V sg = pu.phase_used[BlackoilPhases::Vapour] ? V(s.col(BlackoilPhases::Vapour)) : V::Zero(nc);
|
||||
const V hydrocarbon = so + sg;
|
||||
const V p = Eigen::Map<const V>(& state.pressure()[0], nc);
|
||||
if ( ! is_parallel_run_ )
|
||||
{
|
||||
totals[5] = geo_.poreVolume().sum();
|
||||
totals[6] = unit::convert::to((p * geo_.poreVolume() * hydrocarbon).sum() / ((geo_.poreVolume() * hydrocarbon).sum()), unit::barsa);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if HAVE_MPI
|
||||
const auto & pinfo =
|
||||
boost::any_cast<const ParallelISTLInformation&>(solver_.parallelInformation());
|
||||
auto operators = std::make_tuple(Opm::Reduction::makeGlobalSumFunctor<double>(),
|
||||
Opm::Reduction::makeGlobalSumFunctor<double>(),
|
||||
Opm::Reduction::makeGlobalSumFunctor<double>());
|
||||
auto pav_nom = p * geo_.poreVolume() * hydrocarbon;
|
||||
auto pav_denom = geo_.poreVolume() * hydrocarbon;
|
||||
|
||||
// using ref cref to prevent copying
|
||||
auto inputs = std::make_tuple(std::cref(geo_.poreVolume()),
|
||||
std::cref(pav_nom), std::cref(pav_denom));
|
||||
std::tuple<double, double, double> results(0.0, 0.0, 0.0);
|
||||
|
||||
pinfo.computeReduction(inputs, operators, results);
|
||||
using std::get;
|
||||
totals[5] = get<0>(results);
|
||||
totals[6] = unit::convert::to(get<1>(results)/get<2>(results),
|
||||
unit::barsa);
|
||||
#else
|
||||
// This should never happen!
|
||||
OPM_THROW(std::logic_error, "HAVE_MPI should be defined if we are running in parallel");
|
||||
#endif
|
||||
}
|
||||
|
||||
return totals;
|
||||
}
|
||||
|
@ -62,9 +62,10 @@ public:
|
||||
const bool vapoil,
|
||||
std::shared_ptr<EclipseState> eclipse_state,
|
||||
BlackoilOutputWriter& output_writer,
|
||||
const std::vector<double>& threshold_pressures_by_face)
|
||||
const std::vector<double>& threshold_pressures_by_face,
|
||||
const std::unordered_set<std::string>& defunct_well_names)
|
||||
: Base(param, grid, geo, props, rock_comp_props, linsolver, gravity, disgas, vapoil,
|
||||
eclipse_state, output_writer, threshold_pressures_by_face)
|
||||
eclipse_state, output_writer, threshold_pressures_by_face, defunct_well_names)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -73,9 +73,10 @@ public:
|
||||
const bool vapoil,
|
||||
std::shared_ptr<EclipseState> eclipse_state,
|
||||
BlackoilOutputWriter& output_writer,
|
||||
const std::vector<double>& threshold_pressures_by_face)
|
||||
const std::vector<double>& threshold_pressures_by_face,
|
||||
const std::unordered_set<std::string>& defunct_well_names)
|
||||
: Base(param, grid, geo, props, rock_comp_props, linsolver, gravity, disgas, vapoil,
|
||||
eclipse_state, output_writer, threshold_pressures_by_face)
|
||||
eclipse_state, output_writer, threshold_pressures_by_face, defunct_well_names)
|
||||
{}
|
||||
|
||||
|
||||
|
@ -108,7 +108,13 @@ namespace Opm
|
||||
Opm::UgGridHelpers::beginFaceCentroids(grid_),
|
||||
props_.permeability(),
|
||||
dynamic_list_econ_limited,
|
||||
is_parallel_run_);
|
||||
is_parallel_run_,
|
||||
// We need to pass the optionaly arguments
|
||||
// as we get the following error otherwise
|
||||
// with c++ (Debian 4.9.2-10) 4.9.2 and -std=c++11
|
||||
// converting to ‘const std::unordered_set<std::basic_string<char> >’ from initializer list would use explicit constructor
|
||||
std::vector<double>(), // null well_potentials
|
||||
Base::defunct_well_names_);
|
||||
const Wells* wells = wells_manager.c_wells();
|
||||
WellState well_state;
|
||||
// well_state.init(wells, state, prev_well_state);
|
||||
|
@ -379,7 +379,7 @@ namespace Opm
|
||||
substep,
|
||||
timer.simulationTimeElapsed(),
|
||||
simToSolution( state, phaseUsage_ ),
|
||||
wellState.report(),
|
||||
wellState.report(phaseUsage_),
|
||||
simProps);
|
||||
}
|
||||
}
|
||||
|
@ -397,7 +397,14 @@ namespace Opm
|
||||
Opm::UgGridHelpers::cell2Faces(grid),
|
||||
Opm::UgGridHelpers::beginFaceCentroids(grid),
|
||||
permeability,
|
||||
dummy_list_econ_limited);
|
||||
dummy_list_econ_limited
|
||||
// We need to pass the optionaly arguments
|
||||
// as we get the following error otherwise
|
||||
// with c++ (Debian 4.9.2-10) 4.9.2 and -std=c++11
|
||||
// converting to ‘const std::unordered_set<std::basic_string<char> >’ from initializer list would use explicit constructo
|
||||
, false,
|
||||
std::vector<double>(),
|
||||
std::unordered_set<std::string>());
|
||||
|
||||
const Wells* wells = wellsmanager.c_wells();
|
||||
wellstate.resize(wells, simulatorstate); //Resize for restart step
|
||||
@ -579,14 +586,14 @@ namespace Opm
|
||||
simProps.emplace_back(data::CellData{
|
||||
"RSSAT",
|
||||
Opm::UnitSystem::measure::gas_oil_ratio,
|
||||
std::move(adbToDoubleVector(sd.rs))});
|
||||
std::move(adbToDoubleVector(sd.rsSat))});
|
||||
}
|
||||
if (vapour_active && liquid_active && outKeywords["RVSAT"] > 0) {
|
||||
outKeywords["RVSAT"] = 0;
|
||||
simProps.emplace_back(data::CellData{
|
||||
"RVSAT",
|
||||
Opm::UnitSystem::measure::oil_gas_ratio,
|
||||
std::move(adbToDoubleVector(sd.rv))});
|
||||
std::move(adbToDoubleVector(sd.rvSat))});
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,7 +50,9 @@ namespace Opm
|
||||
has_vapoil,
|
||||
eclipse_state,
|
||||
output_writer,
|
||||
threshold_pressures_by_face)
|
||||
threshold_pressures_by_face,
|
||||
// names of deactivated wells in parallel run
|
||||
std::unordered_set<std::string>())
|
||||
, has_solvent_(has_solvent)
|
||||
, deck_(deck)
|
||||
, solvent_props_(solvent_props)
|
||||
|
@ -65,7 +65,9 @@ public:
|
||||
BlackoilOutputWriter& output_writer,
|
||||
const std::vector<double>& threshold_pressures_by_face)
|
||||
: Base(param, grid, geo, props, rock_comp_props, linsolver, gravity, disgas, vapoil,
|
||||
eclipse_state, output_writer, threshold_pressures_by_face)
|
||||
eclipse_state, output_writer, threshold_pressures_by_face,
|
||||
// names of deactivated wells in parallel run
|
||||
std::unordered_set<std::string>())
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <opm/core/well_controls.h>
|
||||
#include <opm/core/simulator/WellState.hpp>
|
||||
#include <opm/autodiff/BlackoilModelEnums.hpp>
|
||||
#include <opm/core/props/BlackoilPhases.hpp>
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
@ -257,7 +257,7 @@ namespace Opm {
|
||||
|
||||
/// Computing the water velocity without shear-thinning for the cell faces.
|
||||
/// The water velocity will be used for shear-thinning calculation.
|
||||
void computeWaterShearVelocityFaces(const V& transi, const std::vector<ADB>& kr,
|
||||
void computeWaterShearVelocityFaces(const V& transi,
|
||||
const std::vector<ADB>& phasePressure, const SolutionState& state,
|
||||
std::vector<double>& water_vel, std::vector<double>& visc_mult);
|
||||
|
||||
|
@ -291,14 +291,19 @@ namespace Opm {
|
||||
// Set up the common parts of the mass balance equations
|
||||
// for each active phase.
|
||||
const V transi = subset(geo_.transmissibility(), ops_.internal_faces);
|
||||
{
|
||||
const std::vector<ADB> kr = computeRelPerm(state);
|
||||
for (int phaseIdx = 0; phaseIdx < fluid_.numPhases(); ++phaseIdx) {
|
||||
sd_.rq[phaseIdx].kr = kr[canph_[phaseIdx]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (has_plyshlog_) {
|
||||
std::vector<double> water_vel;
|
||||
std::vector<double> visc_mult;
|
||||
|
||||
computeWaterShearVelocityFaces(transi, kr, state.canonical_phase_pressures, state, water_vel, visc_mult);
|
||||
computeWaterShearVelocityFaces(transi, state.canonical_phase_pressures, state, water_vel, visc_mult);
|
||||
if ( !polymer_props_ad_.computeShearMultLog(water_vel, visc_mult, shear_mult_faces_) ) {
|
||||
// std::cerr << " failed in calculating the shear-multiplier " << std::endl;
|
||||
OPM_THROW(std::runtime_error, " failed in calculating the shear-multiplier. ");
|
||||
@ -307,9 +312,9 @@ namespace Opm {
|
||||
|
||||
for (int phaseIdx = 0; phaseIdx < fluid_.numPhases(); ++phaseIdx) {
|
||||
const std::vector<PhasePresence>& cond = phaseCondition();
|
||||
const ADB mu = fluidViscosity(canph_[phaseIdx], state.canonical_phase_pressures[canph_[phaseIdx]], state.temperature, state.rs, state.rv, cond);
|
||||
const ADB rho = fluidDensity(canph_[phaseIdx], sd_.rq[phaseIdx].b, state.rs, state.rv);
|
||||
computeMassFlux(phaseIdx, transi, kr[canph_[phaseIdx]], mu, rho, state.canonical_phase_pressures[canph_[phaseIdx]], state);
|
||||
sd_.rq[phaseIdx].mu = fluidViscosity(canph_[phaseIdx], state.canonical_phase_pressures[canph_[phaseIdx]], state.temperature, state.rs, state.rv, cond);
|
||||
sd_.rq[phaseIdx].rho = fluidDensity(canph_[phaseIdx], sd_.rq[phaseIdx].b, state.rs, state.rv);
|
||||
computeMassFlux(phaseIdx, transi, sd_.rq[phaseIdx].kr, sd_.rq[phaseIdx].mu, sd_.rq[phaseIdx].rho, state.canonical_phase_pressures[canph_[phaseIdx]], state);
|
||||
|
||||
residual_.material_balance_eq[ phaseIdx ] =
|
||||
pvdt_ * (sd_.rq[phaseIdx].accum[1] - sd_.rq[phaseIdx].accum[0])
|
||||
@ -585,7 +590,7 @@ namespace Opm {
|
||||
|
||||
template<class Grid>
|
||||
void
|
||||
BlackoilPolymerModel<Grid>::computeWaterShearVelocityFaces(const V& transi, const std::vector<ADB>& kr,
|
||||
BlackoilPolymerModel<Grid>::computeWaterShearVelocityFaces(const V& transi,
|
||||
const std::vector<ADB>& phasePressure, const SolutionState& state,
|
||||
std::vector<double>& water_vel, std::vector<double>& visc_mult)
|
||||
{
|
||||
@ -598,7 +603,7 @@ namespace Opm {
|
||||
|
||||
const ADB tr_mult = transMult(state.pressure);
|
||||
const ADB mu = fluidViscosity(canonicalPhaseIdx, phasePressure[canonicalPhaseIdx], state.temperature, state.rs, state.rv, cond);
|
||||
sd_.rq[phase].mob = tr_mult * kr[canonicalPhaseIdx] / mu;
|
||||
sd_.rq[phase].mob = tr_mult * sd_.rq[phase].kr / mu;
|
||||
|
||||
// compute gravity potensial using the face average as in eclipse and MRST
|
||||
const ADB rho = fluidDensity(canonicalPhaseIdx, sd_.rq[phase].b, state.rs, state.rv);
|
||||
@ -617,7 +622,7 @@ namespace Opm {
|
||||
const ADB mc = computeMc(state);
|
||||
ADB krw_eff = polymer_props_ad_.effectiveRelPerm(state.concentration,
|
||||
cmax,
|
||||
kr[canonicalPhaseIdx]);
|
||||
sd_.rq[phase].kr);
|
||||
ADB inv_wat_eff_visc = polymer_props_ad_.effectiveInvWaterVisc(state.concentration, mu.value());
|
||||
sd_.rq[ phase ].mob = tr_mult * krw_eff * inv_wat_eff_visc;
|
||||
|
||||
|
@ -78,13 +78,13 @@ namespace Opm {
|
||||
struct SimulatorData {
|
||||
SimulatorData(int num_phases)
|
||||
: rq(num_phases)
|
||||
, rs(ADB::null())
|
||||
, rv(ADB::null())
|
||||
, rsSat(ADB::null())
|
||||
, rvSat(ADB::null())
|
||||
{
|
||||
}
|
||||
std::vector<ReservoirResidualQuant> rq;
|
||||
ADB rs;
|
||||
ADB rv;
|
||||
ADB rsSat;
|
||||
ADB rvSat;
|
||||
};
|
||||
|
||||
/// Construct a solver. It will retain references to the
|
||||
|
@ -51,7 +51,9 @@ namespace Opm
|
||||
has_vapoil,
|
||||
eclipse_state,
|
||||
output_writer,
|
||||
threshold_pressures_by_face)
|
||||
threshold_pressures_by_face,
|
||||
// names of deactivated wells in parallel run
|
||||
std::unordered_set<std::string>())
|
||||
, polymer_props_(polymer_props)
|
||||
, has_polymer_(has_polymer)
|
||||
, has_plyshlog_(has_plyshlog)
|
||||
|
@ -48,7 +48,9 @@ SimulatorFullyImplicitCompressiblePolymer(const parameter::ParameterGroup& param
|
||||
/*vapoil=*/false,
|
||||
eclipse_state,
|
||||
output_writer,
|
||||
/*threshold_pressures_by_face=*/std::vector<double>())
|
||||
/*threshold_pressures_by_face=*/std::vector<double>(),
|
||||
// names of deactivated wells in parallel run
|
||||
std::unordered_set<std::string>())
|
||||
, deck_(deck)
|
||||
, polymer_props_(polymer_props)
|
||||
|
||||
|
@ -7,23 +7,23 @@ BINPATH="$3"
|
||||
FILENAME="$4"
|
||||
ABS_TOL="$5"
|
||||
REL_TOL="$6"
|
||||
SUMMARY_REGRESSION_TEST_COMMAND="$7"
|
||||
RESTART_REGRESSION_TEST_COMMAND="$8"
|
||||
INIT_REGRESSION_TEST_COMMAND="$9"
|
||||
EXE_NAME="${10}"
|
||||
shift 10
|
||||
COMPARE_SUMMARY_COMMAND="$7"
|
||||
COMPARE_ECL_COMMAND="$8"
|
||||
EXE_NAME="${9}"
|
||||
shift 9
|
||||
TEST_ARGS="$@"
|
||||
|
||||
|
||||
rm -Rf ${RESULT_PATH};
|
||||
rm -Rf ${RESULT_PATH}
|
||||
mkdir -p ${RESULT_PATH}
|
||||
cd ${RESULT_PATH}
|
||||
${BINPATH}/${EXE_NAME} ${TEST_ARGS}
|
||||
cd ..
|
||||
|
||||
${SUMMARY_REGRESSION_TEST_COMMAND} ${RESULT_PATH}/${FILENAME} ${INPUT_DATA_PATH}/opm-simulation-reference/${FILENAME} ${ABS_TOL} ${REL_TOL}
|
||||
${COMPARE_SUMMARY_COMMAND} -r ${RESULT_PATH}/${FILENAME} ${INPUT_DATA_PATH}/opm-simulation-reference/${FILENAME} ${ABS_TOL} ${REL_TOL}
|
||||
|
||||
${COMPARE_ECL_COMMAND} ${RESULT_PATH}/${FILENAME} ${INPUT_DATA_PATH}/opm-simulation-reference/${FILENAME} ${ABS_TOL} ${REL_TOL}
|
||||
|
||||
${COMPARE_ECL_COMMAND} -t INIT ${RESULT_PATH}/${FILENAME} ${INPUT_DATA_PATH}/opm-simulation-reference/${FILENAME} ${ABS_TOL} ${REL_TOL}
|
||||
|
||||
${RESTART_REGRESSION_TEST_COMMAND} ${RESULT_PATH}/${FILENAME} ${INPUT_DATA_PATH}/opm-simulation-reference/${FILENAME} ${ABS_TOL} ${REL_TOL}
|
||||
|
||||
${INIT_REGRESSION_TEST_COMMAND} ${RESULT_PATH}/${FILENAME} ${INPUT_DATA_PATH}/opm-simulation-reference/${FILENAME} ${ABS_TOL} ${REL_TOL}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define BOOST_TEST_MODULE MultisegmentWellsTest
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <memory>
|
||||
#include <array>
|
||||
|
||||
@ -106,7 +107,13 @@ struct SetupMSW {
|
||||
Opm::UgGridHelpers::beginFaceCentroids(grid),
|
||||
fluidprops->permeability(),
|
||||
dummy_dynamic_list,
|
||||
false);
|
||||
false
|
||||
// We need to pass the optionaly arguments
|
||||
// as we get the following error otherwise
|
||||
// with c++ (Debian 4.9.2-10) 4.9.2 and -std=c++11
|
||||
// converting to ‘const std::unordered_set<std::basic_string<char> >’ from initializer list would use explicit constructor
|
||||
, std::vector<double>(), // null well_potentials
|
||||
std::unordered_set<std::string>());
|
||||
|
||||
const Wells* wells = wells_manager.c_wells();
|
||||
const auto wells_ecl = ecl_state->getSchedule()->getWells(current_timestep);
|
||||
|
Loading…
Reference in New Issue
Block a user