port the RateConverter to use the FluidSystem instead of the old fluid property API

this makes the RateConverter stuff independent of Eigen and it
simplifies some things because the the old PVT API is designed as a
"bulk-with-derivatives" API while the rate converter code used it in
"single shot" mode without derivatives.
This commit is contained in:
Andreas Lauser 2016-12-29 16:56:31 +01:00
parent 66decb4bda
commit 5fd83985a9
7 changed files with 83 additions and 113 deletions

View File

@ -117,7 +117,7 @@ namespace Opm {
// For the conversion between the surface volume rate and resrevoir voidage rate
using RateConverterType = RateConverter::
SurfaceToReservoirVoidage<BlackoilPropsAdFromDeck, std::vector<int> >;
SurfaceToReservoirVoidage<BlackoilPropsAdFromDeck::FluidSystem, std::vector<int> >;
// --------- Public methods ---------

View File

@ -144,7 +144,7 @@ typedef Eigen::Array<double,
// the field will be calculated.
// TODO: more delicate implementation will be required if we want to handle different
// FIP regions specified from the well specifications.
, rate_converter_(fluid_, std::vector<int>(AutoDiffGrid::numCells(grid_),0))
, rate_converter_(fluid_.phaseUsage(), fluid_.cellPvtRegionIndex(), AutoDiffGrid::numCells(grid_), std::vector<int>(AutoDiffGrid::numCells(grid_),0))
{
if (active_[Water]) {
material_name_.push_back("Water");

View File

@ -28,8 +28,6 @@
#include <opm/core/utility/RegionMapping.hpp>
#include <opm/core/linalg/ParallelIstlInformation.hpp>
#include <Eigen/Core>
#include <algorithm>
#include <cmath>
#include <memory>
@ -385,9 +383,7 @@ namespace Opm {
* The conversion uses fluid properties evaluated at average
* hydrocarbon pressure in regions or field.
*
* \tparam Property Fluid property object. Expected to
* feature the formation volume factor functions of the
* BlackoilPropsAdInterface.
* \tparam FluidSystem Fluid system class. Expected to be a BlackOilFluidSystem
*
* \tparam Region Type of a forward region mapping. Expected
* to provide indexed access through \code operator[]()
@ -395,24 +391,29 @@ namespace Opm {
* size_type, and \c const_iterator. Typically \code
* std::vector<int> \endcode.
*/
template <class Property, class Region>
template <class FluidSystem, class Region>
class SurfaceToReservoirVoidage {
public:
/**
* Constructor.
*
* \param[in] props Fluid property object.
*
* \param[in] region Forward region mapping. Often
* corresponds to the "FIPNUM" mapping of an ECLIPSE input
* deck.
*/
SurfaceToReservoirVoidage(const Property& props,
SurfaceToReservoirVoidage(const PhaseUsage& phaseUsage,
const int* cellPvtRegionIdx,
const int numCells,
const Region& region)
: props_(props)
: phaseUsage_(phaseUsage)
, rmap_ (region)
, attr_ (rmap_, Attributes(props_.numPhases()))
{}
, attr_ (rmap_, Attributes(phaseUsage_.num_phases))
{
cellPvtIdx_.resize(numCells, 0);
if (cellPvtRegionIdx) {
std::copy_n(cellPvtRegionIdx, numCells, cellPvtIdx_.begin());
}
}
/**
* Compute average hydrocarbon pressure and maximum
@ -484,59 +485,58 @@ namespace Opm {
void
calcCoeff(const Input& in, const RegionId r, Coeff& coeff) const
{
using V = typename Property::V;
const auto& pu = props_.phaseUsage();
const auto& pu = phaseUsage_;
const auto& ra = attr_.attributes(r);
const auto p = this->constant(ra.pressure);
const auto T = this->constant(ra.temperature);
const auto c = this->getRegCell(r);
const double p = ra.pressure;
const double T = ra.temperature;
const int cellIdx = attr_.cell(r);
const int pvtRegionIdx = cellPvtIdx_[cellIdx];
const int iw = Details::PhasePos::water(pu);
const int io = Details::PhasePos::oil (pu);
const int ig = Details::PhasePos::gas (pu);
std::fill(& coeff[0], & coeff[0] + props_.numPhases(), 0.0);
std::fill(& coeff[0], & coeff[0] + phaseUsage_.num_phases, 0.0);
if (Details::PhaseUsed::water(pu)) {
// q[w]_r = q[w]_s / bw
const V bw = props_.bWat(p, T, c).value();
const double bw = FluidSystem::waterPvt().inverseFormationVolumeFactor(pvtRegionIdx, T, p);
coeff[iw] = 1.0 / bw(0);
coeff[iw] = 1.0 / bw;
}
const Miscibility& m = calcMiscibility(in, r);
// Determinant of 'R' matrix
const double detR = 1.0 - (m.rs(0) * m.rv(0));
const double detR = 1.0 - (m.rs * m.rv);
if (Details::PhaseUsed::oil(pu)) {
// q[o]_r = 1/(bo * (1 - rs*rv)) * (q[o]_s - rv*q[g]_s)
const auto rs = this->constant(m.rs);
const V bo = props_.bOil(p, T, rs, m.cond, c).value();
const double den = bo(0) * detR;
const double Rs = m.rs;
const double bo = FluidSystem::oilPvt().inverseFormationVolumeFactor(pvtRegionIdx, T, p, Rs);
const double den = bo * detR;
coeff[io] += 1.0 / den;
if (Details::PhaseUsed::gas(pu)) {
coeff[ig] -= m.rv(0) / den;
coeff[ig] -= m.rv / den;
}
}
if (Details::PhaseUsed::gas(pu)) {
// q[g]_r = 1/(bg * (1 - rs*rv)) * (q[g]_s - rs*q[o]_s)
const auto rv = this->constant(m.rv);
const V bg = props_.bGas(p, T, rv, m.cond, c).value();
const double den = bg(0) * detR;
const double Rv = m.rv;
const double bg = FluidSystem::gasPvt().inverseFormationVolumeFactor(pvtRegionIdx, T, p, Rv);
const double den = bg * detR;
coeff[ig] += 1.0 / den;
if (Details::PhaseUsed::oil(pu)) {
coeff[io] -= m.rs(0) / den;
coeff[io] -= m.rs / den;
}
}
}
@ -545,7 +545,8 @@ namespace Opm {
/**
* Fluid property object.
*/
const Property& props_;
const PhaseUsage phaseUsage_;
std::vector<int> cellPvtIdx_;
/**
* "Fluid-in-place" region mapping (forward and reverse).
@ -559,12 +560,12 @@ namespace Opm {
Attributes(const int np)
: pressure (0.0)
, temperature(0.0)
, Rmax (Eigen::ArrayXd::Zero(np, 1))
, Rmax(np, 0.0)
{}
double pressure;
double temperature;
Eigen::ArrayXd Rmax;
std::vector<double> Rmax;
};
Details::RegionAttributes<RegionId, Attributes> attr_;
@ -580,8 +581,8 @@ namespace Opm {
, rv (1)
, cond(1)
{
rs << 0.0;
rv << 0.0;
rs = 0.0;
rv = 0.0;
}
/**
@ -591,7 +592,7 @@ namespace Opm {
* Limited by "RSmax" at average hydrocarbon pressure
* in region.
*/
typename Property::V rs;
double rs;
/**
* Evaporated oil-gas ratio at particular component oil
@ -600,7 +601,7 @@ namespace Opm {
* Limited by "RVmax" at average hydrocarbon pressure
* in region.
*/
typename Property::V rv;
double rv;
/**
* Fluid condition in representative region cell.
@ -674,14 +675,13 @@ namespace Opm {
void
calcRmax()
{
const PhaseUsage& pu = props_.phaseUsage();
const PhaseUsage& pu = phaseUsage_;
if (Details::PhaseUsed::oil(pu) &&
Details::PhaseUsed::gas(pu))
{
const Eigen::ArrayXd::Index
io = Details::PhasePos::oil(pu),
ig = Details::PhasePos::gas(pu);
const int io = Details::PhasePos::oil(pu);
const int ig = Details::PhasePos::gas(pu);
// Note: Intentionally does not take capillary
// pressure into account. This facility uses the
@ -691,13 +691,14 @@ namespace Opm {
for (const auto& reg : rmap_.activeRegions()) {
auto& ra = attr_.attributes(reg);
const auto c = this->getRegCell(reg);
const auto p = this->constant(ra.pressure);
const auto T = this->constant(ra.temperature);
const double T = ra.temperature;
const double p = ra.pressure;
const int cellIdx = attr_.cell(reg);
const int pvtRegionIdx = cellPvtIdx_[cellIdx];
auto& Rmax = ra.Rmax;
Rmax.row(io) = props_.rsSat(p, T, c).value();
Rmax.row(ig) = props_.rvSat(p, T, c).value();
std::vector<double>& Rmax = ra.Rmax;
Rmax[io] = FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx, T, p);
Rmax[ig] = FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx, T, p);
}
}
}
@ -723,7 +724,7 @@ namespace Opm {
Miscibility
calcMiscibility(const Input& in, const RegionId r) const
{
const auto& pu = props_.phaseUsage();
const auto& pu = phaseUsage_;
const auto& attr = attr_.attributes(r);
const int io = Details::PhasePos::oil(pu);
@ -740,7 +741,7 @@ namespace Opm {
cond.setFreeOil();
if (Details::PhaseUsed::gas(pu)) {
const double rsmax = attr.Rmax(io);
const double rsmax = attr.Rmax[io];
const double rs =
(0.0 < std::abs(in[io]))
? in[ig] / in[io]
@ -750,7 +751,7 @@ namespace Opm {
cond.setFreeGas();
}
m.rs(0) = std::min(rs, rsmax);
m.rs = std::min(rs, rsmax);
}
}
@ -761,56 +762,18 @@ namespace Opm {
}
if (Details::PhaseUsed::oil(pu)) {
const double rvmax = attr.Rmax(ig);
const double rvmax = attr.Rmax[ig];
const double rv =
(0.0 < std::abs(in[ig]))
? (in[io] / in[ig])
: (0.0 < std::abs(in[io])) ? rvmax : 0.0;
m.rv(0) = std::min(rv, rvmax);
m.rv = std::min(rv, rvmax);
}
}
return m;
}
/**
* Conversion from \code Property::V \endcode to (constant)
* \code Property::ADB \endcode (zero derivatives).
*/
typename Property::ADB
constant(const typename Property::V& x) const
{
return Property::ADB::constant(x);
}
/**
* Conversion from \c double to (constant) \code Property::ADB
* \endcode (zero derivatives).
*/
typename Property::ADB
constant(const double x) const
{
typename Property::V y(1);
y << x;
return this->constant(y);
}
/**
* Retrieve representative cell of region
*
* \param[in] r Particular region.
*
* \return Representative cell of region \c r.
*/
typename Property::Cells
getRegCell(const RegionId r) const
{
typename Property::Cells c(1, this->attr_.cell(r));
return c;
}
};
} // namespace RateConverter
} // namespace Opm

View File

@ -189,7 +189,7 @@ namespace Opm
// Data.
typedef RateConverter::
SurfaceToReservoirVoidage< BlackoilPropsAdFromDeck,
SurfaceToReservoirVoidage< BlackoilPropsAdFromDeck::FluidSystem,
std::vector<int> > RateConverterType;
typedef typename Traits::Model Model;
typedef typename Model::ModelParameters ModelParameters;

View File

@ -60,7 +60,7 @@ namespace Opm
terminal_output_(param.getDefault("output_terminal", true)),
eclipse_state_(eclipse_state),
output_writer_(output_writer),
rateConverter_(props_, std::vector<int>(AutoDiffGrid::numCells(grid_), 0)),
rateConverter_(props_.phaseUsage(), props.cellPvtRegionIndex(), AutoDiffGrid::numCells(grid_), std::vector<int>(AutoDiffGrid::numCells(grid_), 0)),
threshold_pressures_by_face_(threshold_pressures_by_face),
is_parallel_run_( false ),
defunct_well_names_(defunct_well_names)

View File

@ -117,15 +117,11 @@ public:
defunct_well_names_( defunct_well_names ),
is_parallel_run_( false )
{
DUNE_UNUSED_PARAMETER(eclState);
// Misc init.
const int num_cells = AutoDiffGrid::numCells(grid());
allcells_.resize(num_cells);
for (int cell = 0; cell < num_cells; ++cell) {
allcells_[cell] = cell;
}
rateConverter_.reset(new RateConverterType(props_, std::vector<int>(AutoDiffGrid::numCells(grid()), 0)));
extractLegacyCellPvtRegionIndex_();
rateConverter_.reset(new RateConverterType(props.phaseUsage(),
legacyCellPvtRegionIdx_.data(),
AutoDiffGrid::numCells(grid()),
std::vector<int>(AutoDiffGrid::numCells(grid()), 0)));
#if HAVE_MPI
if ( solver_.parallelInformation().type() == typeid(ParallelISTLInformation) )
@ -708,15 +704,24 @@ protected:
const EclipseState& eclState() const
{ return ebosSimulator_.gridManager().eclState(); }
EclipseState& eclState()
{ return ebosSimulator_.gridManager().eclState(); }
void extractLegacyCellPvtRegionIndex_()
{
const auto& grid = ebosSimulator_.gridManager().grid();
const auto& eclProblem = ebosSimulator_.problem();
const unsigned numCells = grid.size(/*codim=*/0);
legacyCellPvtRegionIdx_.resize(numCells);
for (unsigned cellIdx = 0; cellIdx < numCells; ++cellIdx) {
legacyCellPvtRegionIdx_[cellIdx] =
eclProblem.pvtRegionIndex(cellIdx);
}
}
// Data.
Simulator& ebosSimulator_;
typedef RateConverter::
SurfaceToReservoirVoidage< BlackoilPropsAdFromDeck,
std::vector<int> > RateConverterType;
std::vector<int> legacyCellPvtRegionIdx_;
typedef RateConverter::SurfaceToReservoirVoidage<FluidSystem, std::vector<int> > RateConverterType;
typedef typename Solver::SolverParameters SolverParameters;
const parameter::ParameterGroup param_;

View File

@ -87,10 +87,11 @@ BOOST_FIXTURE_TEST_CASE(Construction, TestFixture<SetupSimple>)
typedef std::vector<int> Region;
typedef Opm::BlackoilPropsAdFromDeck Props;
typedef Opm::RateConverter::
SurfaceToReservoirVoidage<Props, Region> RCvrt;
SurfaceToReservoirVoidage<Props::FluidSystem, Region> RCvrt;
Region reg{ 0 };
RCvrt cvrt(ad_props, reg);
int numCells = Opm::UgGridHelpers::numCells(*grid.c_grid());
RCvrt cvrt(ad_props.phaseUsage(), ad_props.cellPvtRegionIndex(), numCells, reg);
}
@ -100,12 +101,13 @@ BOOST_FIXTURE_TEST_CASE(ThreePhase, TestFixture<SetupSimple>)
typedef std::vector<int> Region;
typedef Opm::BlackoilPropsAdFromDeck Props;
typedef Opm::RateConverter::
SurfaceToReservoirVoidage<Props, Region> RCvrt;
SurfaceToReservoirVoidage<Props::FluidSystem, Region> RCvrt;
Region reg{ 0 };
RCvrt cvrt(ad_props, reg);
int numCells = Opm::UgGridHelpers::numCells(*grid.c_grid());
RCvrt cvrt(ad_props.phaseUsage(), ad_props.cellPvtRegionIndex(), numCells, reg);
Opm::BlackoilState x( Opm::UgGridHelpers::numCells( *grid.c_grid()) , Opm::UgGridHelpers::numFaces( *grid.c_grid()) , 3);
Opm::BlackoilState x(numCells, Opm::UgGridHelpers::numFaces( *grid.c_grid()) , 3);
cvrt.defineState(x);