mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-07-29 18:37:55 -05:00
Use pore volume weighted averaged hydrocarbon state in rateConverted.
- pressure, rs and rv is averaged using hydrocarbon pore volume weights. - pvtRegions is used as input in the conversion factor calculations. - the pvt cell of the first well cell is used as the pvt index. (Completing a well in two different PVT regions sounds like a very bad idea anyway) - FIP region support is added to the rate converter also for the ebos interface.
This commit is contained in:
@@ -143,7 +143,7 @@ typedef Eigen::Array<double,
|
|||||||
// the field will be calculated.
|
// the field will be calculated.
|
||||||
// TODO: more delicate implementation will be required if we want to handle different
|
// TODO: more delicate implementation will be required if we want to handle different
|
||||||
// FIP regions specified from the well specifications.
|
// FIP regions specified from the well specifications.
|
||||||
, rate_converter_(fluid_.phaseUsage(), fluid_.cellPvtRegionIndex(), AutoDiffGrid::numCells(grid_), std::vector<int>(AutoDiffGrid::numCells(grid_),0))
|
, rate_converter_(fluid_.phaseUsage(), std::vector<int>(AutoDiffGrid::numCells(grid_),0))
|
||||||
{
|
{
|
||||||
if (active_[Water]) {
|
if (active_[Water]) {
|
||||||
material_name_.push_back("Water");
|
material_name_.push_back("Water");
|
||||||
@@ -2513,8 +2513,10 @@ typedef Eigen::Array<double,
|
|||||||
|
|
||||||
// the average hydrocarbon conditions of the whole field will be used
|
// the average hydrocarbon conditions of the whole field will be used
|
||||||
const int fipreg = 0; // Not considering FIP for the moment.
|
const int fipreg = 0; // Not considering FIP for the moment.
|
||||||
|
const int well_cell_top = wells->well_cells[wells->well_connpos[w]];
|
||||||
|
const int pvtreg = fluid_.cellPvtRegionIndex()[well_cell_top];
|
||||||
|
|
||||||
rate_converter_.calcCoeff(well_rates, fipreg, convert_coeff);
|
rate_converter_.calcCoeff(fipreg, pvtreg, convert_coeff);
|
||||||
well_voidage_rates[w] = std::inner_product(well_rates.begin(), well_rates.end(),
|
well_voidage_rates[w] = std::inner_product(well_rates.begin(), well_rates.end(),
|
||||||
convert_coeff.begin(), 0.0);
|
convert_coeff.begin(), 0.0);
|
||||||
} else {
|
} else {
|
||||||
@@ -2525,7 +2527,9 @@ typedef Eigen::Array<double,
|
|||||||
well_rates.begin());
|
well_rates.begin());
|
||||||
// the average hydrocarbon conditions of the whole field will be used
|
// the average hydrocarbon conditions of the whole field will be used
|
||||||
const int fipreg = 0; // Not considering FIP for the moment.
|
const int fipreg = 0; // Not considering FIP for the moment.
|
||||||
rate_converter_.calcCoeff(well_rates, fipreg, convert_coeff);
|
const int well_cell_top = wells->well_cells[wells->well_connpos[w]];
|
||||||
|
const int pvtreg = fluid_.cellPvtRegionIndex()[well_cell_top];
|
||||||
|
rate_converter_.calcCoeff(fipreg, pvtreg, convert_coeff);
|
||||||
std::copy(convert_coeff.begin(), convert_coeff.end(),
|
std::copy(convert_coeff.begin(), convert_coeff.end(),
|
||||||
voidage_conversion_coeffs.begin() + np * w);
|
voidage_conversion_coeffs.begin() + np * w);
|
||||||
}
|
}
|
||||||
|
|||||||
+121
-213
@@ -81,37 +81,49 @@ namespace Opm {
|
|||||||
* \brief Computes the temperature, pressure, and counter increment.
|
* \brief Computes the temperature, pressure, and counter increment.
|
||||||
* \param pressure The pressure.
|
* \param pressure The pressure.
|
||||||
* \param temperature The temperature.
|
* \param temperature The temperature.
|
||||||
|
* \param rs The rs.
|
||||||
|
* \param rv The rv.
|
||||||
* \param cell The current cell index.
|
* \param cell The current cell index.
|
||||||
* \param ownership A vector indicating whether a cell is owned
|
* \param ownership A vector indicating whether a cell is owned
|
||||||
* by this process (value 1), or not (value 0).
|
* by this process (value 1), or not (value 0).
|
||||||
* \param cell The cell index.
|
* \param cell The cell index.
|
||||||
*/
|
*/
|
||||||
std::tuple<double, double, int>
|
std::tuple<double, double, double, double, int>
|
||||||
operator()(const std::vector<double>& pressure,
|
operator()(const std::vector<double>& pressure,
|
||||||
const std::vector<double>& temperature,
|
const std::vector<double>& temperature,
|
||||||
|
const std::vector<double>& rs,
|
||||||
|
const std::vector<double>& rv,
|
||||||
const std::vector<double>& ownership,
|
const std::vector<double>& ownership,
|
||||||
std::size_t cell){
|
std::size_t cell){
|
||||||
if ( ownership[cell] )
|
if ( ownership[cell] )
|
||||||
{
|
{
|
||||||
return std::make_tuple(pressure[cell],
|
return std::make_tuple(pressure[cell],
|
||||||
temperature[cell], 1);
|
temperature[cell],
|
||||||
|
rs[cell],
|
||||||
|
rv[cell],
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return std::make_tuple(0, 0, 0);
|
return std::make_tuple(0, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<>
|
template<>
|
||||||
struct AverageIncrementCalculator<false>
|
struct AverageIncrementCalculator<false>
|
||||||
{
|
{
|
||||||
std::tuple<double, double, int>
|
std::tuple<double, double, double, double, int>
|
||||||
operator()(const std::vector<double>& pressure,
|
operator()(const std::vector<double>& pressure,
|
||||||
const std::vector<double>& temperature,
|
const std::vector<double>& temperature,
|
||||||
|
const std::vector<double>& rs,
|
||||||
|
const std::vector<double>& rv,
|
||||||
const std::vector<double>&,
|
const std::vector<double>&,
|
||||||
std::size_t cell){
|
std::size_t cell){
|
||||||
return std::make_tuple(pressure[cell],
|
return std::make_tuple(pressure[cell],
|
||||||
temperature[cell], 1);
|
temperature[cell],
|
||||||
|
rs[cell],
|
||||||
|
rv[cell],
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@@ -402,17 +414,11 @@ namespace Opm {
|
|||||||
* deck.
|
* deck.
|
||||||
*/
|
*/
|
||||||
SurfaceToReservoirVoidage(const PhaseUsage& phaseUsage,
|
SurfaceToReservoirVoidage(const PhaseUsage& phaseUsage,
|
||||||
const int* cellPvtRegionIdx,
|
|
||||||
const int numCells,
|
|
||||||
const Region& region)
|
const Region& region)
|
||||||
: phaseUsage_(phaseUsage)
|
: phaseUsage_(phaseUsage)
|
||||||
, rmap_ (region)
|
, rmap_ (region)
|
||||||
, attr_ (rmap_, Attributes(phaseUsage_.num_phases))
|
, attr_ (rmap_, Attributes())
|
||||||
{
|
{
|
||||||
cellPvtIdx_.resize(numCells, 0);
|
|
||||||
if (cellPvtRegionIdx) {
|
|
||||||
std::copy_n(cellPvtRegionIdx, numCells, cellPvtIdx_.begin());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -448,37 +454,41 @@ namespace Opm {
|
|||||||
std::vector<double> dummyOwnership; // not actually used
|
std::vector<double> dummyOwnership; // not actually used
|
||||||
calcAverages<false>(state, info, dummyOwnership);
|
calcAverages<false>(state, info, dummyOwnership);
|
||||||
}
|
}
|
||||||
calcRmax();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute average hydrocarbon pressure and maximum
|
* Compute pore volume averaged hydrocarbon state pressure, rs and rv.
|
||||||
* dissolution and evaporation at average hydrocarbon
|
|
||||||
* pressure in all regions in field.
|
|
||||||
*
|
*
|
||||||
* Fluid properties are evaluated at average hydrocarbon
|
* Fluid properties are evaluated at average hydrocarbon
|
||||||
* pressure for purpose of conversion from surface rate to
|
* state for purpose of conversion from surface rate to
|
||||||
* reservoir voidage rate.
|
* reservoir voidage rate.
|
||||||
*
|
*
|
||||||
* \param[in] state Dynamic reservoir state.
|
|
||||||
* \param[in] any The information and communication utilities
|
|
||||||
* about/of the parallelization. in any parallel
|
|
||||||
* it wraps a ParallelISTLInformation. Parameter
|
|
||||||
* is optional.
|
|
||||||
*/
|
*/
|
||||||
template <typename ElementContext, class EbosSimulator>
|
template <typename ElementContext, class EbosSimulator>
|
||||||
void defineState(const EbosSimulator& simulator)
|
void defineState(const EbosSimulator& simulator)
|
||||||
{
|
{
|
||||||
|
|
||||||
//const int numCells = cellPvtIdx_.size();
|
// create map from cell to region
|
||||||
//const Region region = std::vector<int>(numCells, 0);
|
// and set all attributes to zero
|
||||||
auto& ra = attr_.attributes(0);
|
const auto& grid = simulator.gridManager().grid();
|
||||||
auto& p = ra.pressure;
|
const unsigned numCells = grid.size(/*codim=*/0);
|
||||||
auto& T = ra.temperature;
|
std::vector<int> cell2region(numCells, -1);
|
||||||
std::size_t n = 0;
|
for (const auto& reg : rmap_.activeRegions()) {
|
||||||
|
for (const auto& cell : rmap_.cells(reg)) {
|
||||||
|
cell2region[cell] = reg;
|
||||||
|
}
|
||||||
|
auto& ra = attr_.attributes(reg);
|
||||||
|
ra.pressure = 0.0;
|
||||||
|
ra.temperature = 0.0;
|
||||||
|
ra.rs = 0.0;
|
||||||
|
ra.rv = 0.0;
|
||||||
|
ra.pv = 0.0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
ElementContext elemCtx( simulator );
|
ElementContext elemCtx( simulator );
|
||||||
const auto& gridView = simulator.gridView();
|
const auto& gridView = simulator.gridView();
|
||||||
|
const auto& comm = gridView.comm();
|
||||||
|
|
||||||
const auto& elemEndIt = gridView.template end</*codim=*/0>();
|
const auto& elemEndIt = gridView.template end</*codim=*/0>();
|
||||||
for (auto elemIt = gridView.template begin</*codim=*/0>();
|
for (auto elemIt = gridView.template begin</*codim=*/0>();
|
||||||
@@ -492,21 +502,58 @@ namespace Opm {
|
|||||||
|
|
||||||
elemCtx.updatePrimaryStencil(elem);
|
elemCtx.updatePrimaryStencil(elem);
|
||||||
elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
|
elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
|
||||||
|
const unsigned cellIdx = elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0);
|
||||||
const auto& intQuants = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0);
|
const auto& intQuants = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0);
|
||||||
const auto& fs = intQuants.fluidState();
|
const auto& fs = intQuants.fluidState();
|
||||||
|
// use pore volume weighted averages.
|
||||||
|
const double pv_cell =
|
||||||
|
simulator.model().dofTotalVolume(cellIdx)
|
||||||
|
* intQuants.porosity().value();
|
||||||
|
|
||||||
p += fs.pressure(FluidSystem::oilPhaseIdx).value();
|
// only count oil and gas filled parts of the domain
|
||||||
T += fs.temperature(FluidSystem::oilPhaseIdx).value();
|
double hydrocarbon = 1.0;
|
||||||
n += 1;
|
const auto& pu = phaseUsage_;
|
||||||
|
if (Details::PhaseUsed::water(pu)) {
|
||||||
|
hydrocarbon -= fs.saturation(FluidSystem::waterPhaseIdx).value();
|
||||||
|
}
|
||||||
|
|
||||||
|
int reg = cell2region[cellIdx];
|
||||||
|
assert(reg >= 0);
|
||||||
|
auto& ra = attr_.attributes(reg);
|
||||||
|
auto& p = ra.pressure;
|
||||||
|
auto& T = ra.temperature;
|
||||||
|
auto& rs = ra.rs;
|
||||||
|
auto& rv = ra.rv;
|
||||||
|
auto& pv = ra.pv;
|
||||||
|
|
||||||
|
// sum p, rs, rv, and T.
|
||||||
|
double hydrocarbonPV = pv_cell*hydrocarbon;
|
||||||
|
pv += hydrocarbonPV;
|
||||||
|
p += fs.pressure(FluidSystem::oilPhaseIdx).value()*hydrocarbonPV;
|
||||||
|
rs += fs.Rs().value()*hydrocarbonPV;
|
||||||
|
rv += fs.Rv().value()*hydrocarbonPV;
|
||||||
|
T += fs.temperature(FluidSystem::oilPhaseIdx).value()*hydrocarbonPV;
|
||||||
}
|
}
|
||||||
p = gridView.comm().sum(p);
|
|
||||||
T = gridView.comm().sum(T);
|
|
||||||
n = gridView.comm().sum(n);
|
|
||||||
|
|
||||||
p /= n;
|
for (const auto& reg : rmap_.activeRegions()) {
|
||||||
T /= n;
|
auto& ra = attr_.attributes(reg);
|
||||||
|
auto& p = ra.pressure;
|
||||||
calcRmax();
|
auto& T = ra.temperature;
|
||||||
|
auto& rs = ra.rs;
|
||||||
|
auto& rv = ra.rv;
|
||||||
|
auto& pv = ra.pv;
|
||||||
|
// communicate sums
|
||||||
|
p = comm.sum(p);
|
||||||
|
T = comm.sum(T);
|
||||||
|
rs = comm.sum(rs);
|
||||||
|
rv = comm.sum(rv);
|
||||||
|
pv = comm.sum(pv);
|
||||||
|
// compute average
|
||||||
|
p /= pv;
|
||||||
|
T /= pv;
|
||||||
|
rs /= pv;
|
||||||
|
rv /= pv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -529,28 +576,22 @@ namespace Opm {
|
|||||||
* support direct indexing through \code operator[]()
|
* support direct indexing through \code operator[]()
|
||||||
* \endcode.
|
* \endcode.
|
||||||
*
|
*
|
||||||
* \param[in] in Single tuple of active component rates at
|
|
||||||
* surface conditions.
|
|
||||||
*
|
*
|
||||||
* \param[in] r Fluid-in-place region to which the
|
* \param[in] r Fluid-in-place region of the well
|
||||||
* component rates correspond.
|
* \param[in] pvtRegionIdx PVT region of the well
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* \param[out] coeff Surface-to-reservoir conversion
|
* \param[out] coeff Surface-to-reservoir conversion
|
||||||
* coefficients for all active phases, corresponding to
|
* coefficients for all active phases.
|
||||||
* input rates \c in in region \c r.
|
|
||||||
*/
|
*/
|
||||||
template <class Input,
|
template <class Coeff>
|
||||||
class Coeff>
|
|
||||||
void
|
void
|
||||||
calcCoeff(const Input& in, const RegionId r, Coeff& coeff) const
|
calcCoeff(const RegionId r, const int pvtRegionIdx, Coeff& coeff) const
|
||||||
{
|
{
|
||||||
const auto& pu = phaseUsage_;
|
const auto& pu = phaseUsage_;
|
||||||
const auto& ra = attr_.attributes(r);
|
const auto& ra = attr_.attributes(r);
|
||||||
|
|
||||||
const double p = ra.pressure;
|
const double p = ra.pressure;
|
||||||
const double T = ra.temperature;
|
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 iw = Details::PhasePos::water(pu);
|
||||||
const int io = Details::PhasePos::oil (pu);
|
const int io = Details::PhasePos::oil (pu);
|
||||||
@@ -566,36 +607,34 @@ namespace Opm {
|
|||||||
coeff[iw] = 1.0 / bw;
|
coeff[iw] = 1.0 / bw;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Miscibility& m = calcMiscibility(in, r);
|
|
||||||
|
|
||||||
// Determinant of 'R' matrix
|
// Determinant of 'R' matrix
|
||||||
const double detR = 1.0 - (m.rs * m.rv);
|
const double detR = 1.0 - (ra.rs * ra.rv);
|
||||||
|
|
||||||
if (Details::PhaseUsed::oil(pu)) {
|
if (Details::PhaseUsed::oil(pu)) {
|
||||||
// q[o]_r = 1/(bo * (1 - rs*rv)) * (q[o]_s - rv*q[g]_s)
|
// q[o]_r = 1/(bo * (1 - rs*rv)) * (q[o]_s - rv*q[g]_s)
|
||||||
|
|
||||||
const double Rs = m.rs;
|
const double Rs = ra.rs;
|
||||||
const double bo = FluidSystem::oilPvt().inverseFormationVolumeFactor(pvtRegionIdx, T, p, Rs);
|
const double bo = FluidSystem::oilPvt().inverseFormationVolumeFactor(pvtRegionIdx, T, p, Rs);
|
||||||
const double den = bo * detR;
|
const double den = bo * detR;
|
||||||
|
|
||||||
coeff[io] += 1.0 / den;
|
coeff[io] += 1.0 / den;
|
||||||
|
|
||||||
if (Details::PhaseUsed::gas(pu)) {
|
if (Details::PhaseUsed::gas(pu)) {
|
||||||
coeff[ig] -= m.rv / den;
|
coeff[ig] -= ra.rv / den;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Details::PhaseUsed::gas(pu)) {
|
if (Details::PhaseUsed::gas(pu)) {
|
||||||
// q[g]_r = 1/(bg * (1 - rs*rv)) * (q[g]_s - rs*q[o]_s)
|
// q[g]_r = 1/(bg * (1 - rs*rv)) * (q[g]_s - rs*q[o]_s)
|
||||||
|
|
||||||
const double Rv = m.rv;
|
const double Rv = ra.rv;
|
||||||
const double bg = FluidSystem::gasPvt().inverseFormationVolumeFactor(pvtRegionIdx, T, p, Rv);
|
const double bg = FluidSystem::gasPvt().inverseFormationVolumeFactor(pvtRegionIdx, T, p, Rv);
|
||||||
const double den = bg * detR;
|
const double den = bg * detR;
|
||||||
|
|
||||||
coeff[ig] += 1.0 / den;
|
coeff[ig] += 1.0 / den;
|
||||||
|
|
||||||
if (Details::PhaseUsed::oil(pu)) {
|
if (Details::PhaseUsed::oil(pu)) {
|
||||||
coeff[io] -= m.rs / den;
|
coeff[io] -= ra.rs / den;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -605,7 +644,6 @@ namespace Opm {
|
|||||||
* Fluid property object.
|
* Fluid property object.
|
||||||
*/
|
*/
|
||||||
const PhaseUsage phaseUsage_;
|
const PhaseUsage phaseUsage_;
|
||||||
std::vector<int> cellPvtIdx_;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Fluid-in-place" region mapping (forward and reverse).
|
* "Fluid-in-place" region mapping (forward and reverse).
|
||||||
@@ -616,59 +654,23 @@ namespace Opm {
|
|||||||
* Derived property attributes for each active region.
|
* Derived property attributes for each active region.
|
||||||
*/
|
*/
|
||||||
struct Attributes {
|
struct Attributes {
|
||||||
Attributes(const int np)
|
Attributes()
|
||||||
: pressure (0.0)
|
: pressure (0.0)
|
||||||
, temperature(0.0)
|
, temperature(0.0)
|
||||||
, Rmax(np, 0.0)
|
, rs(0.0)
|
||||||
|
, rv(0.0)
|
||||||
|
, pv(0.0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
double pressure;
|
double pressure;
|
||||||
double temperature;
|
double temperature;
|
||||||
std::vector<double> Rmax;
|
double rs;
|
||||||
|
double rv;
|
||||||
|
double pv;
|
||||||
};
|
};
|
||||||
|
|
||||||
Details::RegionAttributes<RegionId, Attributes> attr_;
|
Details::RegionAttributes<RegionId, Attributes> attr_;
|
||||||
|
|
||||||
/**
|
|
||||||
* Aggregate structure defining fluid miscibility
|
|
||||||
* conditions in single region with particular input
|
|
||||||
* surface rates.
|
|
||||||
*/
|
|
||||||
struct Miscibility {
|
|
||||||
Miscibility()
|
|
||||||
: rs (1)
|
|
||||||
, rv (1)
|
|
||||||
, cond(1)
|
|
||||||
{
|
|
||||||
rs = 0.0;
|
|
||||||
rv = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dissolved gas-oil ratio at particular component oil
|
|
||||||
* and gas rates at surface conditions.
|
|
||||||
*
|
|
||||||
* Limited by "RSmax" at average hydrocarbon pressure
|
|
||||||
* in region.
|
|
||||||
*/
|
|
||||||
double rs;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaporated oil-gas ratio at particular component oil
|
|
||||||
* and gas rates at surface conditions.
|
|
||||||
*
|
|
||||||
* Limited by "RVmax" at average hydrocarbon pressure
|
|
||||||
* in region.
|
|
||||||
*/
|
|
||||||
double rv;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fluid condition in representative region cell.
|
|
||||||
*
|
|
||||||
* Needed for purpose of FVF evaluation.
|
|
||||||
*/
|
|
||||||
std::vector<PhasePresence> cond;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute average hydrocarbon pressure and temperatures in all
|
* Compute average hydrocarbon pressure and temperatures in all
|
||||||
@@ -691,148 +693,54 @@ namespace Opm {
|
|||||||
{
|
{
|
||||||
const auto& press = state.pressure();
|
const auto& press = state.pressure();
|
||||||
const auto& temp = state.temperature();
|
const auto& temp = state.temperature();
|
||||||
|
const auto& Rv = state.rv();
|
||||||
|
const auto& Rs = state.gasoilratio();
|
||||||
|
|
||||||
for (const auto& reg : rmap_.activeRegions()) {
|
for (const auto& reg : rmap_.activeRegions()) {
|
||||||
auto& ra = attr_.attributes(reg);
|
auto& ra = attr_.attributes(reg);
|
||||||
auto& p = ra.pressure;
|
auto& p = ra.pressure;
|
||||||
auto& T = ra.temperature;
|
auto& T = ra.temperature;
|
||||||
|
auto& rs = ra.rs;
|
||||||
|
auto& rv = ra.rv;
|
||||||
|
|
||||||
std::size_t n = 0;
|
std::size_t n = 0;
|
||||||
p = T = 0.0;
|
p = T = 0.0;
|
||||||
for (const auto& cell : rmap_.cells(reg)) {
|
for (const auto& cell : rmap_.cells(reg)) {
|
||||||
auto increment = Details::
|
auto increment = Details::
|
||||||
AverageIncrementCalculator<is_parallel>()(press, temp,
|
AverageIncrementCalculator<is_parallel>()(press, temp, Rs, Rv,
|
||||||
ownerShip,
|
ownerShip,
|
||||||
cell);
|
cell);
|
||||||
p += std::get<0>(increment);
|
p += std::get<0>(increment);
|
||||||
T += std::get<1>(increment);
|
T += std::get<1>(increment);
|
||||||
n += std::get<2>(increment);
|
rs += std::get<2>(increment);
|
||||||
|
rv += std::get<3>(increment);
|
||||||
|
n += std::get<4>(increment);
|
||||||
}
|
}
|
||||||
std::size_t global_n = n;
|
std::size_t global_n = n;
|
||||||
double global_p = p;
|
double global_p = p;
|
||||||
double global_T = T;
|
double global_T = T;
|
||||||
|
double global_rs = rs;
|
||||||
|
double global_rv = rv;
|
||||||
#if HAVE_MPI
|
#if HAVE_MPI
|
||||||
if ( is_parallel )
|
if ( is_parallel )
|
||||||
{
|
{
|
||||||
const auto& real_info = boost::any_cast<const ParallelISTLInformation&>(info);
|
const auto& real_info = boost::any_cast<const ParallelISTLInformation&>(info);
|
||||||
global_n = real_info.communicator().sum(n);
|
global_n = real_info.communicator().sum(n);
|
||||||
global_p = real_info.communicator().sum(p);
|
global_p = real_info.communicator().sum(p);
|
||||||
|
global_rs = real_info.communicator().sum(rs);
|
||||||
|
global_rv = real_info.communicator().sum(rv);
|
||||||
global_T = real_info.communicator().sum(T);
|
global_T = real_info.communicator().sum(T);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
p = global_p / global_n;
|
p = global_p / global_n;
|
||||||
|
rs = global_rs / global_n;
|
||||||
|
rv = global_rv / global_n;
|
||||||
T = global_T / global_n;
|
T = global_T / global_n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Compute maximum dissolution and evaporation ratios at
|
|
||||||
* average hydrocarbon pressure.
|
|
||||||
*
|
|
||||||
* Uses the pressure value computed by averagePressure()
|
|
||||||
* and must therefore be called *after* that method.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
calcRmax()
|
|
||||||
{
|
|
||||||
const PhaseUsage& pu = phaseUsage_;
|
|
||||||
|
|
||||||
if (Details::PhaseUsed::oil(pu) &&
|
|
||||||
Details::PhaseUsed::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
|
|
||||||
// average *hydrocarbon* pressure rather than
|
|
||||||
// average phase pressure.
|
|
||||||
|
|
||||||
for (const auto& reg : rmap_.activeRegions()) {
|
|
||||||
auto& ra = attr_.attributes(reg);
|
|
||||||
|
|
||||||
const double T = ra.temperature;
|
|
||||||
const double p = ra.pressure;
|
|
||||||
const int cellIdx = attr_.cell(reg);
|
|
||||||
const int pvtRegionIdx = cellPvtIdx_[cellIdx];
|
|
||||||
|
|
||||||
std::vector<double>& Rmax = ra.Rmax;
|
|
||||||
Rmax[io] = FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx, T, p);
|
|
||||||
Rmax[ig] = FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx, T, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute fluid conditions in particular region for a
|
|
||||||
* given set of component rates at surface conditions.
|
|
||||||
*
|
|
||||||
* \tparam Input Type representing collection of (active)
|
|
||||||
* component rates at surface conditions. Must support
|
|
||||||
* direct indexing through \code operator[]()\endcode.
|
|
||||||
*
|
|
||||||
* \param[in] in Single tuple of active component rates at
|
|
||||||
* surface conditions.
|
|
||||||
*
|
|
||||||
* \param[in] r Fluid-in-place region to which the
|
|
||||||
* component rates correspond.
|
|
||||||
*
|
|
||||||
* \return Fluid conditions in region \c r corresponding
|
|
||||||
* to surface component rates \c in.
|
|
||||||
*/
|
|
||||||
template <class Input>
|
|
||||||
Miscibility
|
|
||||||
calcMiscibility(const Input& in, const RegionId r) const
|
|
||||||
{
|
|
||||||
const auto& pu = phaseUsage_;
|
|
||||||
const auto& attr = attr_.attributes(r);
|
|
||||||
|
|
||||||
const int io = Details::PhasePos::oil(pu);
|
|
||||||
const int ig = Details::PhasePos::gas(pu);
|
|
||||||
|
|
||||||
Miscibility m;
|
|
||||||
PhasePresence& cond = m.cond[0];
|
|
||||||
|
|
||||||
if (Details::PhaseUsed::water(pu)) {
|
|
||||||
cond.setFreeWater();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Details::PhaseUsed::oil(pu)) {
|
|
||||||
cond.setFreeOil();
|
|
||||||
|
|
||||||
if (Details::PhaseUsed::gas(pu)) {
|
|
||||||
const double rsmax = attr.Rmax[io];
|
|
||||||
const double rs =
|
|
||||||
(0.0 < std::abs(in[io]))
|
|
||||||
? in[ig] / in[io]
|
|
||||||
: (0.0 < std::abs(in[ig])) ? rsmax : 0.0;
|
|
||||||
|
|
||||||
if (rsmax < rs) {
|
|
||||||
cond.setFreeGas();
|
|
||||||
}
|
|
||||||
|
|
||||||
m.rs = std::min(rs, rsmax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Details::PhaseUsed::gas(pu)) {
|
|
||||||
if (! Details::PhaseUsed::oil(pu)) {
|
|
||||||
// Oil *NOT* active -- not really supported.
|
|
||||||
cond.setFreeGas();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Details::PhaseUsed::oil(pu)) {
|
|
||||||
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 = std::min(rv, rvmax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} // namespace RateConverter
|
} // namespace RateConverter
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace Opm
|
|||||||
terminal_output_(param.getDefault("output_terminal", true)),
|
terminal_output_(param.getDefault("output_terminal", true)),
|
||||||
eclipse_state_(eclipse_state),
|
eclipse_state_(eclipse_state),
|
||||||
output_writer_(output_writer),
|
output_writer_(output_writer),
|
||||||
rateConverter_(props_.phaseUsage(), props.cellPvtRegionIndex(), AutoDiffGrid::numCells(grid_), std::vector<int>(AutoDiffGrid::numCells(grid_), 0)),
|
rateConverter_(props_.phaseUsage(), std::vector<int>(AutoDiffGrid::numCells(grid_), 0)),
|
||||||
threshold_pressures_by_face_(threshold_pressures_by_face),
|
threshold_pressures_by_face_(threshold_pressures_by_face),
|
||||||
is_parallel_run_( false ),
|
is_parallel_run_( false ),
|
||||||
defunct_well_names_(defunct_well_names)
|
defunct_well_names_(defunct_well_names)
|
||||||
@@ -560,7 +560,9 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
|
|
||||||
const int fipreg = 0; // Hack. Ignore FIP regions.
|
const int fipreg = 0; // Hack. Ignore FIP regions.
|
||||||
rateConverter_.calcCoeff(prates, fipreg, distr);
|
const int well_cell_top = wells->well_cells[wells->well_connpos[*rp]];
|
||||||
|
const int pvtreg = props_.cellPvtRegionIndex()[well_cell_top];
|
||||||
|
rateConverter_.calcCoeff(fipreg, pvtreg, distr);
|
||||||
|
|
||||||
well_controls_iset_distr(ctrl, rctrl, & distr[0]);
|
well_controls_iset_distr(ctrl, rctrl, & distr[0]);
|
||||||
}
|
}
|
||||||
@@ -582,7 +584,9 @@ namespace Opm
|
|||||||
SimFIBODetails::historyRates(pu, p, hrates);
|
SimFIBODetails::historyRates(pu, p, hrates);
|
||||||
|
|
||||||
const int fipreg = 0; // Hack. Ignore FIP regions.
|
const int fipreg = 0; // Hack. Ignore FIP regions.
|
||||||
rateConverter_.calcCoeff(hrates, fipreg, distr);
|
const int well_cell_top = wells->well_cells[wells->well_connpos[*rp]];
|
||||||
|
const int pvtreg = props_.cellPvtRegionIndex()[well_cell_top];
|
||||||
|
rateConverter_.calcCoeff(fipreg, pvtreg, distr);
|
||||||
|
|
||||||
// WCONHIST/RESV target is sum of all
|
// WCONHIST/RESV target is sum of all
|
||||||
// observed phase rates translated to
|
// observed phase rates translated to
|
||||||
|
|||||||
@@ -292,8 +292,9 @@ public:
|
|||||||
solver_timer.start();
|
solver_timer.start();
|
||||||
|
|
||||||
const auto& wells_ecl = eclState().getSchedule().getWells(timer.currentStepNum());
|
const auto& wells_ecl = eclState().getSchedule().getWells(timer.currentStepNum());
|
||||||
|
extractLegacyCellPvtRegionIndex_();
|
||||||
WellModel well_model(wells, &(wells_manager.wellCollection()), wells_ecl, model_param_,
|
WellModel well_model(wells, &(wells_manager.wellCollection()), wells_ecl, model_param_,
|
||||||
rateConverter_, terminal_output_, timer.currentStepNum());
|
rateConverter_, terminal_output_, timer.currentStepNum(), legacyCellPvtRegionIdx_);
|
||||||
|
|
||||||
auto solver = createSolver(well_model);
|
auto solver = createSolver(well_model);
|
||||||
|
|
||||||
@@ -542,6 +543,9 @@ protected:
|
|||||||
{
|
{
|
||||||
WellControls* ctrl = wells->ctrls[*rp];
|
WellControls* ctrl = wells->ctrls[*rp];
|
||||||
const bool is_producer = wells->type[*rp] == PRODUCER;
|
const bool is_producer = wells->type[*rp] == PRODUCER;
|
||||||
|
const int well_cell_top = wells->well_cells[wells->well_connpos[*rp]];
|
||||||
|
const auto& eclProblem = ebosSimulator_.problem();
|
||||||
|
const int pvtreg = eclProblem.pvtRegionIndex(well_cell_top);
|
||||||
|
|
||||||
// RESV control mode, all wells
|
// RESV control mode, all wells
|
||||||
{
|
{
|
||||||
@@ -563,7 +567,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const int fipreg = 0; // Hack. Ignore FIP regions.
|
const int fipreg = 0; // Hack. Ignore FIP regions.
|
||||||
rateConverter_.calcCoeff(prates, fipreg, distr);
|
rateConverter_.calcCoeff(fipreg, pvtreg, distr);
|
||||||
|
|
||||||
well_controls_iset_distr(ctrl, rctrl, & distr[0]);
|
well_controls_iset_distr(ctrl, rctrl, & distr[0]);
|
||||||
}
|
}
|
||||||
@@ -585,7 +589,7 @@ protected:
|
|||||||
SimFIBODetails::historyRates(pu, p, hrates);
|
SimFIBODetails::historyRates(pu, p, hrates);
|
||||||
|
|
||||||
const int fipreg = 0; // Hack. Ignore FIP regions.
|
const int fipreg = 0; // Hack. Ignore FIP regions.
|
||||||
rateConverter_.calcCoeff(hrates, fipreg, distr);
|
rateConverter_.calcCoeff(fipreg, pvtreg, distr);
|
||||||
|
|
||||||
// WCONHIST/RESV target is sum of all
|
// WCONHIST/RESV target is sum of all
|
||||||
// observed phase rates translated to
|
// observed phase rates translated to
|
||||||
@@ -978,11 +982,8 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
RateConverterType createRateConverter_() {
|
RateConverterType createRateConverter_() {
|
||||||
extractLegacyCellPvtRegionIndex_();
|
|
||||||
RateConverterType rate_converter(phaseUsage_,
|
RateConverterType rate_converter(phaseUsage_,
|
||||||
legacyCellPvtRegionIdx_.data(),
|
std::vector<int>(AutoDiffGrid::numCells(grid()), 0)); // FIP = 0
|
||||||
AutoDiffGrid::numCells(grid()),
|
|
||||||
std::vector<int>(AutoDiffGrid::numCells(grid()), 0));
|
|
||||||
return rate_converter;
|
return rate_converter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ namespace Opm {
|
|||||||
const ModelParameters& param,
|
const ModelParameters& param,
|
||||||
const RateConverterType& rate_converter,
|
const RateConverterType& rate_converter,
|
||||||
const bool terminal_output,
|
const bool terminal_output,
|
||||||
const int current_index);
|
const int current_index,
|
||||||
|
std::vector<int>& pvt_region_idx);
|
||||||
|
|
||||||
void init(const PhaseUsage phase_usage_arg,
|
void init(const PhaseUsage phase_usage_arg,
|
||||||
const std::vector<bool>& active_arg,
|
const std::vector<bool>& active_arg,
|
||||||
@@ -187,6 +188,7 @@ namespace Opm {
|
|||||||
PhaseUsage phase_usage_;
|
PhaseUsage phase_usage_;
|
||||||
std::vector<bool> active_;
|
std::vector<bool> active_;
|
||||||
const RateConverterType& rate_converter_;
|
const RateConverterType& rate_converter_;
|
||||||
|
std::vector<int> pvt_region_idx_;
|
||||||
|
|
||||||
// the number of the cells in the local grid
|
// the number of the cells in the local grid
|
||||||
int number_of_cells_;
|
int number_of_cells_;
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ namespace Opm {
|
|||||||
const ModelParameters& param,
|
const ModelParameters& param,
|
||||||
const RateConverterType& rate_converter,
|
const RateConverterType& rate_converter,
|
||||||
const bool terminal_output,
|
const bool terminal_output,
|
||||||
const int current_timeIdx)
|
const int current_timeIdx,
|
||||||
|
std::vector<int>& pvt_region_idx)
|
||||||
: wells_active_(wells_arg!=nullptr)
|
: wells_active_(wells_arg!=nullptr)
|
||||||
, wells_(wells_arg)
|
, wells_(wells_arg)
|
||||||
, wells_ecl_(wells_ecl)
|
, wells_ecl_(wells_ecl)
|
||||||
@@ -25,6 +26,7 @@ namespace Opm {
|
|||||||
, has_polymer_(GET_PROP_VALUE(TypeTag, EnablePolymer))
|
, has_polymer_(GET_PROP_VALUE(TypeTag, EnablePolymer))
|
||||||
, current_timeIdx_(current_timeIdx)
|
, current_timeIdx_(current_timeIdx)
|
||||||
, rate_converter_(rate_converter)
|
, rate_converter_(rate_converter)
|
||||||
|
, pvt_region_idx_(pvt_region_idx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -776,6 +778,8 @@ namespace Opm {
|
|||||||
|
|
||||||
for (int w = 0; w < nw; ++w) {
|
for (int w = 0; w < nw; ++w) {
|
||||||
const bool is_producer = well_container_[w]->wellType() == PRODUCER;
|
const bool is_producer = well_container_[w]->wellType() == PRODUCER;
|
||||||
|
const int well_cell_top = well_container_[w]->cells()[0];
|
||||||
|
const int pvtRegionIdx = pvt_region_idx_[well_cell_top];
|
||||||
|
|
||||||
// not sure necessary to change all the value to be positive
|
// not sure necessary to change all the value to be positive
|
||||||
if (is_producer) {
|
if (is_producer) {
|
||||||
@@ -786,7 +790,7 @@ namespace Opm {
|
|||||||
// the average hydrocarbon conditions of the whole field will be used
|
// the average hydrocarbon conditions of the whole field will be used
|
||||||
const int fipreg = 0; // Not considering FIP for the moment.
|
const int fipreg = 0; // Not considering FIP for the moment.
|
||||||
|
|
||||||
rate_converter_.calcCoeff(well_rates, fipreg, convert_coeff);
|
rate_converter_.calcCoeff(fipreg, pvtRegionIdx, convert_coeff);
|
||||||
well_voidage_rates[w] = std::inner_product(well_rates.begin(), well_rates.end(),
|
well_voidage_rates[w] = std::inner_product(well_rates.begin(), well_rates.end(),
|
||||||
convert_coeff.begin(), 0.0);
|
convert_coeff.begin(), 0.0);
|
||||||
} else {
|
} else {
|
||||||
@@ -797,7 +801,7 @@ namespace Opm {
|
|||||||
well_rates.begin());
|
well_rates.begin());
|
||||||
// the average hydrocarbon conditions of the whole field will be used
|
// the average hydrocarbon conditions of the whole field will be used
|
||||||
const int fipreg = 0; // Not considering FIP for the moment.
|
const int fipreg = 0; // Not considering FIP for the moment.
|
||||||
rate_converter_.calcCoeff(well_rates, fipreg, convert_coeff);
|
rate_converter_.calcCoeff(fipreg, pvtRegionIdx, convert_coeff);
|
||||||
std::copy(convert_coeff.begin(), convert_coeff.end(),
|
std::copy(convert_coeff.begin(), convert_coeff.end(),
|
||||||
voidage_conversion_coeffs.begin() + np * w);
|
voidage_conversion_coeffs.begin() + np * w);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ namespace Opm
|
|||||||
/// Well name.
|
/// Well name.
|
||||||
const std::string& name() const;
|
const std::string& name() const;
|
||||||
|
|
||||||
|
/// Well cells.
|
||||||
|
const std::vector<int>& cells() {return well_cells_; }
|
||||||
|
|
||||||
/// Well type, INJECTOR or PRODUCER.
|
/// Well type, INJECTOR or PRODUCER.
|
||||||
WellType wellType() const;
|
WellType wellType() const;
|
||||||
|
|
||||||
|
|||||||
@@ -90,8 +90,7 @@ BOOST_FIXTURE_TEST_CASE(Construction, TestFixture<SetupSimple>)
|
|||||||
SurfaceToReservoirVoidage<Props::FluidSystem, Region> RCvrt;
|
SurfaceToReservoirVoidage<Props::FluidSystem, Region> RCvrt;
|
||||||
|
|
||||||
Region reg{ 0 };
|
Region reg{ 0 };
|
||||||
int numCells = Opm::UgGridHelpers::numCells(*grid.c_grid());
|
RCvrt cvrt(ad_props.phaseUsage(), reg);
|
||||||
RCvrt cvrt(ad_props.phaseUsage(), ad_props.cellPvtRegionIndex(), numCells, reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -105,18 +104,17 @@ BOOST_FIXTURE_TEST_CASE(ThreePhase, TestFixture<SetupSimple>)
|
|||||||
|
|
||||||
Region reg{ 0 };
|
Region reg{ 0 };
|
||||||
int numCells = Opm::UgGridHelpers::numCells(*grid.c_grid());
|
int numCells = Opm::UgGridHelpers::numCells(*grid.c_grid());
|
||||||
RCvrt cvrt(ad_props.phaseUsage(), ad_props.cellPvtRegionIndex(), numCells, reg);
|
RCvrt cvrt(ad_props.phaseUsage(), reg);
|
||||||
|
|
||||||
Opm::BlackoilState x(numCells, Opm::UgGridHelpers::numFaces( *grid.c_grid()) , 3);
|
Opm::BlackoilState x(numCells, Opm::UgGridHelpers::numFaces( *grid.c_grid()) , 3);
|
||||||
|
|
||||||
cvrt.defineState(x);
|
cvrt.defineState(x);
|
||||||
|
|
||||||
std::vector<double> qs{1.0e3, 1.0e1, 1.0e-1};
|
std::vector<double> coeff(3, 0.0);
|
||||||
std::vector<double> coeff(qs.size(), 0.0);
|
|
||||||
|
|
||||||
// Immiscible and incompressible: All coefficients are one (1),
|
// Immiscible and incompressible: All coefficients are one (1),
|
||||||
// irrespective of actual surface rates.
|
// irrespective of actual surface rates.
|
||||||
cvrt.calcCoeff(qs, 0, coeff);
|
cvrt.calcCoeff(0, 0, coeff);
|
||||||
BOOST_CHECK_CLOSE(coeff[0], 1.0, 1.0e-6);
|
BOOST_CHECK_CLOSE(coeff[0], 1.0, 1.0e-6);
|
||||||
BOOST_CHECK_CLOSE(coeff[1], 1.0, 1.0e-6);
|
BOOST_CHECK_CLOSE(coeff[1], 1.0, 1.0e-6);
|
||||||
BOOST_CHECK_CLOSE(coeff[2], 1.0, 1.0e-6);
|
BOOST_CHECK_CLOSE(coeff[2], 1.0, 1.0e-6);
|
||||||
|
|||||||
Reference in New Issue
Block a user