mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-01-07 23:13:01 -06:00
Equilibration with water-gas ratio vs depth (RVWVD) table
This commit is contained in:
parent
bae2c258a6
commit
1c70b5beea
@ -195,6 +195,42 @@ satRv(const double press, const double temp) const
|
||||
}
|
||||
|
||||
|
||||
template<class FluidSystem>
|
||||
RvwVD<FluidSystem>::RvwVD(const int pvtRegionIdx,
|
||||
const std::vector<double>& depth,
|
||||
const std::vector<double>& rvw)
|
||||
: pvtRegionIdx_(pvtRegionIdx)
|
||||
, rvwVsDepth_(depth, rvw)
|
||||
{
|
||||
}
|
||||
|
||||
template<class FluidSystem>
|
||||
double RvwVD<FluidSystem>::
|
||||
operator()(const double depth,
|
||||
const double press,
|
||||
const double temp,
|
||||
const double satWat) const
|
||||
{
|
||||
if (std::abs(satWat) > 1e-16) {
|
||||
return satRvw(press, temp); //saturated Rvw
|
||||
}
|
||||
else {
|
||||
if (rvwVsDepth_.xMin() > depth)
|
||||
return rvwVsDepth_.valueAt(0);
|
||||
else if (rvwVsDepth_.xMax() < depth)
|
||||
return rvwVsDepth_.valueAt(rvwVsDepth_.numSamples() - 1);
|
||||
return std::min(satRvw(press, temp), rvwVsDepth_.eval(depth, /*extrapolate=*/false));
|
||||
}
|
||||
}
|
||||
|
||||
template<class FluidSystem>
|
||||
double RvwVD<FluidSystem>::
|
||||
satRvw(const double press, const double temp) const
|
||||
{
|
||||
return FluidSystem::gasPvt().saturatedWaterVaporizationFactor(pvtRegionIdx_, temp, press);
|
||||
}
|
||||
|
||||
|
||||
template<class FluidSystem>
|
||||
RsSatAtContact<FluidSystem>::
|
||||
RsSatAtContact(const int pvtRegionIdx, const double pContact, const double T_contact)
|
||||
@ -255,16 +291,48 @@ satRv(const double press, const double temp) const
|
||||
return FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_, temp, press);;
|
||||
}
|
||||
|
||||
template<class FluidSystem>
|
||||
RvwSatAtContact<FluidSystem>::
|
||||
RvwSatAtContact(const int pvtRegionIdx, const double pContact, const double T_contact)
|
||||
: pvtRegionIdx_(pvtRegionIdx)
|
||||
{
|
||||
rvwSatContact_ = satRvw(pContact, T_contact);
|
||||
}
|
||||
|
||||
template<class FluidSystem>
|
||||
double RvwSatAtContact<FluidSystem>::
|
||||
operator()(const double /*depth*/,
|
||||
const double press,
|
||||
const double temp,
|
||||
const double satWat) const
|
||||
{
|
||||
if (satWat > 0.0) {
|
||||
return satRvw(press, temp);
|
||||
}
|
||||
else {
|
||||
return std::min(satRvw(press, temp), rvwSatContact_);
|
||||
}
|
||||
}
|
||||
|
||||
template<class FluidSystem>
|
||||
double RvwSatAtContact<FluidSystem>::
|
||||
satRvw(const double press, const double temp) const
|
||||
{
|
||||
return FluidSystem::gasPvt().saturatedWaterVaporizationFactor(pvtRegionIdx_, temp, press);;
|
||||
}
|
||||
|
||||
} // namespace Miscibility
|
||||
|
||||
EquilReg::EquilReg(const EquilRecord& rec,
|
||||
std::shared_ptr<Miscibility::RsFunction> rs,
|
||||
std::shared_ptr<Miscibility::RsFunction> rv,
|
||||
std::shared_ptr<Miscibility::RsFunction> rvw,
|
||||
const TabulatedFunction& saltVdTable,
|
||||
const int pvtIdx)
|
||||
: rec_ (rec)
|
||||
, rs_ (rs)
|
||||
, rv_ (rv)
|
||||
, rvw_ (rvw)
|
||||
, saltVdTable_ (saltVdTable)
|
||||
, pvtIdx_ (pvtIdx)
|
||||
{
|
||||
@ -317,6 +385,12 @@ EquilReg::evaporationCalculator() const
|
||||
return *this->rv_;
|
||||
}
|
||||
|
||||
const EquilReg::CalcWaterEvaporation&
|
||||
EquilReg::waterEvaporationCalculator() const
|
||||
{
|
||||
return *this->rvw_;
|
||||
}
|
||||
|
||||
const EquilReg::TabulatedFunction&
|
||||
EquilReg::saltVdTable() const
|
||||
{
|
||||
@ -556,7 +630,9 @@ namespace Miscibility {
|
||||
template class RsVD<FS>;
|
||||
template class RsSatAtContact<FS>;
|
||||
template class RvSatAtContact<FS>;
|
||||
template class RvwSatAtContact<FS>;
|
||||
template class RvVD<FS>;
|
||||
template class RvwVD<FS>;
|
||||
}
|
||||
|
||||
} // namespace Equil
|
||||
|
@ -363,6 +363,56 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Type that implements "vaporized water-gas ratio"
|
||||
* tabulated as a function of depth policy. Data
|
||||
* typically taken from keyword 'RVWVD'.
|
||||
*/
|
||||
template <class FluidSystem>
|
||||
class RvwVD : public RsFunction
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* \param[in] pvtRegionIdx The pvt region index
|
||||
* \param[in] depth Depth nodes.
|
||||
* \param[in] rvw Evaporized water-gasl ratio at @c depth.
|
||||
*/
|
||||
RvwVD(const int pvtRegionIdx,
|
||||
const std::vector<double>& depth,
|
||||
const std::vector<double>& rvw);
|
||||
|
||||
/**
|
||||
* Function call.
|
||||
*
|
||||
* \param[in] depth Depth at which to calculate RVW
|
||||
* value.
|
||||
*
|
||||
* \param[in] press Pressure at which to calculate RVW
|
||||
* value.
|
||||
*
|
||||
* \param[in] temp Temperature at which to calculate RVW
|
||||
* value.
|
||||
*
|
||||
* \return Vaporized water-gas ratio (RVW) at depth @c
|
||||
* depth and pressure @c press.
|
||||
*/
|
||||
double operator()(const double depth,
|
||||
const double press,
|
||||
const double temp,
|
||||
const double satWat = 0.0) const;
|
||||
|
||||
private:
|
||||
using RvwVsDepthFunc = Tabulated1DFunction<double>;
|
||||
|
||||
const int pvtRegionIdx_;
|
||||
RvwVsDepthFunc rvwVsDepth_;
|
||||
|
||||
double satRvw(const double press, const double temp) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class that implements "dissolved gas-oil ratio" (Rs)
|
||||
* as function of depth and pressure as follows:
|
||||
@ -472,6 +522,61 @@ private:
|
||||
double satRv(const double press, const double temp) const;
|
||||
};
|
||||
|
||||
//TODO: check if needed
|
||||
/**
|
||||
* Class that implements "vaporized water-gas ratio" (Rvw)
|
||||
* as function of depth and pressure as follows:
|
||||
*
|
||||
* 1. The Rvw at the gas-water contact is equal to the
|
||||
* saturated Rv value, RvwSatContact.
|
||||
*
|
||||
* 2. The Rvw elsewhere is equal to RvwSatContact, but
|
||||
* constrained to the saturated value as given by the
|
||||
* local pressure.
|
||||
*
|
||||
* This should yield Rvw-values that are constant below the
|
||||
* contact, and decreasing above the contact.
|
||||
*/
|
||||
template <class FluidSystem>
|
||||
class RvwSatAtContact : public RsFunction
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* \param[in] pvtRegionIdx The pvt region index
|
||||
* \param[in] pContact oil pressure at the contact
|
||||
* \param[in] T_contact temperature at the contact
|
||||
*/
|
||||
RvwSatAtContact(const int pvtRegionIdx, const double pContact, const double T_contact);
|
||||
|
||||
/**
|
||||
* Function call.
|
||||
*
|
||||
* \param[in] depth Depth at which to calculate RVW
|
||||
* value.
|
||||
*
|
||||
* \param[in] press Pressure at which to calculate RVW
|
||||
* value.
|
||||
*
|
||||
* \param[in] temp Temperature at which to calculate RVW
|
||||
* value.
|
||||
*
|
||||
* \return Dissolved water-gas ratio (RVW) at depth @c
|
||||
* depth and pressure @c press.
|
||||
*/
|
||||
double operator()(const double /*depth*/,
|
||||
const double press,
|
||||
const double temp,
|
||||
const double satWat = 0.0) const;
|
||||
|
||||
private:
|
||||
const int pvtRegionIdx_;
|
||||
double rvwSatContact_;
|
||||
|
||||
double satRvw(const double press, const double temp) const;
|
||||
};
|
||||
|
||||
} // namespace Miscibility
|
||||
|
||||
/**
|
||||
@ -504,11 +609,13 @@ public:
|
||||
* \param[in] rec Equilibration data of current region.
|
||||
* \param[in] rs Calculator of dissolved gas-oil ratio.
|
||||
* \param[in] rv Calculator of vapourised oil-gas ratio.
|
||||
* \param[in] rvw Calculator of vapourised water-gas ratio.
|
||||
* \param[in] pvtRegionIdx The pvt region index
|
||||
*/
|
||||
EquilReg(const EquilRecord& rec,
|
||||
std::shared_ptr<Miscibility::RsFunction> rs,
|
||||
std::shared_ptr<Miscibility::RsFunction> rv,
|
||||
std::shared_ptr<Miscibility::RsFunction> rvw,
|
||||
const TabulatedFunction& saltVdTable,
|
||||
const int pvtIdx);
|
||||
|
||||
@ -522,6 +629,12 @@ public:
|
||||
*/
|
||||
using CalcEvaporation = Miscibility::RsFunction;
|
||||
|
||||
/**
|
||||
* Type of vapourised water-gas ratio calculator.
|
||||
*/
|
||||
using CalcWaterEvaporation = Miscibility::RsFunction;
|
||||
|
||||
|
||||
/**
|
||||
* Datum depth in current region
|
||||
*/
|
||||
@ -577,6 +690,12 @@ public:
|
||||
*/
|
||||
const CalcEvaporation& evaporationCalculator() const;
|
||||
|
||||
/**
|
||||
* Retrieve vapourised water-gas ratio calculator of current
|
||||
* region.
|
||||
*/
|
||||
const CalcWaterEvaporation& waterEvaporationCalculator() const;
|
||||
|
||||
const TabulatedFunction& saltVdTable() const;
|
||||
/**
|
||||
* Retrieve pvtIdx of the region.
|
||||
@ -587,6 +706,7 @@ private:
|
||||
EquilRecord rec_; /**< Equilibration data */
|
||||
std::shared_ptr<Miscibility::RsFunction> rs_; /**< RS calculator */
|
||||
std::shared_ptr<Miscibility::RsFunction> rv_; /**< RV calculator */
|
||||
std::shared_ptr<Miscibility::RsFunction> rvw_; /**< RVW calculator */
|
||||
const TabulatedFunction& saltVdTable_;
|
||||
const int pvtIdx_;
|
||||
};
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/RsvdTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/RvvdTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/RvwvdTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/PbvdTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/PdvdTable.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/SaltvdTable.hpp>
|
||||
@ -324,6 +325,7 @@ density(const double depth,
|
||||
return rho;
|
||||
}
|
||||
|
||||
// TODO: add RVW
|
||||
template<class FluidSystem, class RV>
|
||||
Gas<FluidSystem,RV>::
|
||||
Gas(const double temp,
|
||||
@ -1203,6 +1205,7 @@ InitialStateComputer(MaterialLawManager& materialLawManager,
|
||||
std::vector<double>(grid.size(/*codim=*/0))),
|
||||
rs_(grid.size(/*codim=*/0)),
|
||||
rv_(grid.size(/*codim=*/0)),
|
||||
rvw_(grid.size(/*codim=*/0)),
|
||||
cartesianIndexMapper_(cartMapper)
|
||||
{
|
||||
//Check for presence of kw SWATINIT
|
||||
@ -1322,6 +1325,54 @@ InitialStateComputer(MaterialLawManager& materialLawManager,
|
||||
}
|
||||
}
|
||||
|
||||
rvwFunc_.reserve(rec.size());
|
||||
if (FluidSystem::enableVaporizedWater()) {
|
||||
for (size_t i = 0; i < rec.size(); ++i) {
|
||||
if (eqlmap.cells(i).empty()) {
|
||||
rvwFunc_.push_back(std::shared_ptr<Miscibility::RvwVD<FluidSystem>>());
|
||||
continue;
|
||||
}
|
||||
const int pvtIdx = regionPvtIdx_[i];
|
||||
if (!rec[i].wetGasInitConstantRv()) {
|
||||
const TableContainer& rvwvdTables = tables.getRvwvdTables();
|
||||
//const TableContainer& pdvdTables = tables.getPdvdTables();
|
||||
|
||||
if (rvwvdTables.size() > 0) {
|
||||
const RvwvdTable& rvwvdTable = rvwvdTables.getTable<RvwvdTable>(i);
|
||||
std::vector<double> depthColumn = rvwvdTable.getColumn("DEPTH").vectorCopy();
|
||||
std::vector<double> rvwvdColumn = rvwvdTable.getColumn("RVWVD").vectorCopy();
|
||||
rvwFunc_.push_back(std::make_shared<Miscibility::RvwVD<FluidSystem>>(pvtIdx,
|
||||
depthColumn, rvwvdColumn));
|
||||
// } else if (pdvdTables.size() > 0) {
|
||||
// const PdvdTable& pdvdTable = pdvdTables.getTable<PdvdTable>(i);
|
||||
// std::vector<double> depthColumn = pdvdTable.getColumn("DEPTH").vectorCopy();
|
||||
// std::vector<double> pdewColumn = pdvdTable.getColumn("PDEW").vectorCopy();
|
||||
// rvFunc_.push_back(std::make_shared<Miscibility::PDVD<FluidSystem>>(pvtIdx,
|
||||
// depthColumn, pdewColumn));
|
||||
} else {
|
||||
throw std::runtime_error("Cannot initialise: RVWVD table not available.");
|
||||
}
|
||||
}
|
||||
// else {
|
||||
// if (rec[i].gasOilContactDepth() != rec[i].datumDepth()) {
|
||||
// throw std::runtime_error(
|
||||
// "Cannot initialise: when no explicit RVVD table is given, \n"
|
||||
// "datum depth must be at the gas-oil-contact. "
|
||||
// "In EQUIL region "+std::to_string(i + 1)+" (counting from 1), this does not hold.");
|
||||
// }
|
||||
// const double pContact = rec[i].datumDepthPressure() + rec[i].gasOilContactCapillaryPressure();
|
||||
// const double TContact = 273.15 + 20; // standard temperature for now
|
||||
// rvFunc_.push_back(std::make_shared<Miscibility::RvSatAtContact<FluidSystem>>(pvtIdx,pContact, TContact));
|
||||
// }
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (size_t i = 0; i < rec.size(); ++i) {
|
||||
rvwFunc_.push_back(std::make_shared<Miscibility::NoMixing>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// EXTRACT the initial temperature
|
||||
updateInitialTemperature_(eclipseState);
|
||||
|
||||
@ -1603,7 +1654,7 @@ calcPressSatRsRv(const RMap& reg,
|
||||
}
|
||||
|
||||
const auto eqreg = EquilReg {
|
||||
rec[r], this->rsFunc_[r], this->rvFunc_[r], this->saltVdTable_[r], this->regionPvtIdx_[r]
|
||||
rec[r], this->rsFunc_[r], this->rvFunc_[r], this->rvwFunc_[r], this->saltVdTable_[r], this->regionPvtIdx_[r]
|
||||
};
|
||||
|
||||
// Ensure gas/oil and oil/water contacts are within the span for the
|
||||
@ -1664,9 +1715,10 @@ cellLoop(const CellRange& cells,
|
||||
auto saturations = Details::PhaseQuantityValue{};
|
||||
auto Rs = 0.0;
|
||||
auto Rv = 0.0;
|
||||
auto Rvw = 0.0;
|
||||
|
||||
for (const auto& cell : cells) {
|
||||
eqmethod(cell, pressures, saturations, Rs, Rv);
|
||||
eqmethod(cell, pressures, saturations, Rs, Rv, Rvw);
|
||||
|
||||
if (oilActive) {
|
||||
this->pp_ [oilPos][cell] = pressures.oil;
|
||||
@ -1687,6 +1739,10 @@ cellLoop(const CellRange& cells,
|
||||
this->rs_[cell] = Rs;
|
||||
this->rv_[cell] = Rv;
|
||||
}
|
||||
|
||||
if (watActive && gasActive) {
|
||||
this->rvw_[cell] = Rvw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1714,7 +1770,8 @@ equilibrateCellCentres(const CellRange& cells,
|
||||
Details::PhaseQuantityValue& pressures,
|
||||
Details::PhaseQuantityValue& saturations,
|
||||
double& Rs,
|
||||
double& Rv) -> void
|
||||
double& Rv,
|
||||
double& Rvw) -> void
|
||||
{
|
||||
const auto pos = CellPos {
|
||||
cell, cellCenterDepth_[cell]
|
||||
@ -1730,6 +1787,9 @@ equilibrateCellCentres(const CellRange& cells,
|
||||
|
||||
Rv = eqreg.evaporationCalculator()
|
||||
(pos.depth, pressures.gas, temp, saturations.oil);
|
||||
|
||||
Rvw = eqreg.waterEvaporationCalculator()
|
||||
(pos.depth, pressures.gas, temp, saturations.water);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1759,7 +1819,8 @@ equilibrateHorizontal(const CellRange& cells,
|
||||
Details::PhaseQuantityValue& pressures,
|
||||
Details::PhaseQuantityValue& saturations,
|
||||
double& Rs,
|
||||
double& Rv) -> void
|
||||
double& Rv,
|
||||
double& Rvw) -> void
|
||||
{
|
||||
pressures .reset();
|
||||
saturations.reset();
|
||||
@ -1785,6 +1846,9 @@ equilibrateHorizontal(const CellRange& cells,
|
||||
|
||||
Rv = eqreg.evaporationCalculator()
|
||||
(cz, pressures.gas, temp, saturations.oil);
|
||||
|
||||
Rvw = eqreg.waterEvaporationCalculator()
|
||||
(cz, pressures.gas, temp, saturations.water);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,7 @@ private:
|
||||
const double press) const;
|
||||
};
|
||||
|
||||
//TODO:add argument rvw
|
||||
template <class FluidSystem, class RV>
|
||||
class Gas
|
||||
{
|
||||
@ -741,6 +742,7 @@ private:
|
||||
|
||||
std::vector< std::shared_ptr<Miscibility::RsFunction> > rsFunc_;
|
||||
std::vector< std::shared_ptr<Miscibility::RsFunction> > rvFunc_;
|
||||
std::vector< std::shared_ptr<Miscibility::RsFunction> > rvwFunc_;
|
||||
using TabulatedFunction = Tabulated1DFunction<double>;
|
||||
std::vector<TabulatedFunction> saltVdTable_;
|
||||
std::vector<TabulatedFunction> saltpVdTable_;
|
||||
|
@ -264,6 +264,7 @@ BOOST_AUTO_TEST_CASE(PhasePressure)
|
||||
record,
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
trivialSaltVdTable,
|
||||
0
|
||||
};
|
||||
@ -320,24 +321,28 @@ BOOST_AUTO_TEST_CASE(CellSubset)
|
||||
Opm::EQUIL::EquilReg(record[0],
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
trivialSaltVdTable,
|
||||
0)
|
||||
,
|
||||
Opm::EQUIL::EquilReg(record[0],
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
trivialSaltVdTable,
|
||||
0)
|
||||
,
|
||||
Opm::EQUIL::EquilReg(record[1],
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
trivialSaltVdTable,
|
||||
0)
|
||||
,
|
||||
Opm::EQUIL::EquilReg(record[1],
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
trivialSaltVdTable,
|
||||
0)
|
||||
};
|
||||
@ -423,24 +428,28 @@ BOOST_AUTO_TEST_CASE(RegMapping)
|
||||
Opm::EQUIL::EquilReg(record[0],
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
trivialSaltVdTable,
|
||||
0)
|
||||
,
|
||||
Opm::EQUIL::EquilReg(record[0],
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
trivialSaltVdTable,
|
||||
0)
|
||||
,
|
||||
Opm::EQUIL::EquilReg(record[1],
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
trivialSaltVdTable,
|
||||
0)
|
||||
,
|
||||
Opm::EQUIL::EquilReg(record[1],
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
std::make_shared<Opm::EQUIL::Miscibility::NoMixing>(),
|
||||
trivialSaltVdTable,
|
||||
0)
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user