Merge pull request #434 from bska/use-common-eps-api
Extract Endpoints Using Common Facilities
This commit is contained in:
commit
3db77dd5f9
@ -176,28 +176,20 @@ public:
|
||||
enableKrnScaling_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// endpoint scaling is used, i.e., at least saturation scaling needs to be enabled
|
||||
enableSatScaling_ = true;
|
||||
enableThreePointKrSatScaling_ = endscale.threepoint();
|
||||
|
||||
if (twoPhaseSystemType == EclOilWaterSystem) {
|
||||
// check if Leverett capillary pressure scaling is requested
|
||||
if (eclState.getTableManager().useJFunc()) {
|
||||
const auto& jfunc = eclState.getTableManager().getJFunc();
|
||||
auto flag = jfunc.flag();
|
||||
if (flag == Opm::JFunc::Flag::BOTH || flag == Opm::JFunc::Flag::WATER)
|
||||
enableLeverettScaling_ = true;
|
||||
}
|
||||
} else {
|
||||
// check if Leverett capillary pressure scaling is requested
|
||||
if (eclState.getTableManager().useJFunc()) {
|
||||
const auto& jfunc = eclState.getTableManager().getJFunc();
|
||||
auto flag = jfunc.flag();
|
||||
if (flag == Opm::JFunc::Flag::BOTH || flag == Opm::JFunc::Flag::GAS)
|
||||
enableLeverettScaling_ = true;
|
||||
}
|
||||
}
|
||||
if (eclState.getTableManager().useJFunc()) {
|
||||
const auto flag = eclState.getTableManager().getJFunc().flag();
|
||||
|
||||
enableLeverettScaling_ = (flag == Opm::JFunc::Flag::BOTH)
|
||||
|| ((twoPhaseSystemType == EclOilWaterSystem) &&
|
||||
(flag == Opm::JFunc::Flag::WATER))
|
||||
|| ((twoPhaseSystemType == EclGasOilSystem) &&
|
||||
(flag == Opm::JFunc::Flag::GAS));
|
||||
}
|
||||
|
||||
const auto& fp = eclState.fieldProps();
|
||||
// check if we are supposed to scale the Y axis of the capillary pressure
|
||||
@ -212,11 +204,13 @@ public:
|
||||
enablePcScaling_ = fp.has_double("PCG");
|
||||
}
|
||||
|
||||
if (enablePcScaling_ && enableLeverettScaling_)
|
||||
throw std::runtime_error("Capillary pressure scaling and the Leverett scaling function are "
|
||||
"mutually exclusive: The deck contains the PCW/PCG property and the "
|
||||
"JFUNC keyword applies to the water phase.");
|
||||
|
||||
if (enablePcScaling_ && enableLeverettScaling_) {
|
||||
throw std::runtime_error {
|
||||
"Capillary pressure scaling and the Leverett scaling function "
|
||||
"are mutually exclusive. The deck contains the PCW/PCG property "
|
||||
"and the JFUNC keyword applies to the water phase."
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -44,13 +44,13 @@
|
||||
|
||||
#include <opm/material/common/Means.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
/*!
|
||||
* \brief Collects all grid properties which are relevant for end point scaling.
|
||||
@ -81,14 +81,12 @@ public:
|
||||
EclEpsGridProperties(const Opm::EclipseState& eclState,
|
||||
bool useImbibition)
|
||||
{
|
||||
std::string kwPrefix = useImbibition?"I":"";
|
||||
const std::string kwPrefix = useImbibition ? "I" : "";
|
||||
|
||||
const auto& fp = eclState.fieldProps();
|
||||
|
||||
if (useImbibition)
|
||||
compressed_satnum = fp.get_int("IMBNUM");
|
||||
else
|
||||
compressed_satnum = fp.get_int("SATNUM");
|
||||
compressed_satnum = useImbibition
|
||||
? fp.get_int("IMBNUM") : fp.get_int("SATNUM");
|
||||
|
||||
this->compressed_swl = try_get( fp, kwPrefix+"SWL");
|
||||
this->compressed_sgl = try_get( fp, kwPrefix+"SGL");
|
||||
@ -108,20 +106,15 @@ public:
|
||||
if (fp.has_double("PORO"))
|
||||
this->compressed_poro = fp.get_double("PORO");
|
||||
|
||||
if (fp.has_double("PERMX"))
|
||||
this->compressed_permx = fp.get_double("PERMX");
|
||||
else
|
||||
this->compressed_permx = std::vector<double>(this->compressed_satnum.size());
|
||||
this->compressed_permx = fp.has_double("PERMX")
|
||||
? fp.get_double("PERMX")
|
||||
: std::vector<double>(this->compressed_satnum.size());
|
||||
|
||||
if (fp.has_double("PERMY"))
|
||||
this->compressed_permy = fp.get_double("PERMY");
|
||||
else
|
||||
this->compressed_permy = this->compressed_permx;
|
||||
this->compressed_permy = fp.has_double("PERMY")
|
||||
? fp.get_double("PERMY") : this->compressed_permx;
|
||||
|
||||
if (fp.has_double("PERMZ"))
|
||||
this->compressed_permz = fp.get_double("PERMZ");
|
||||
else
|
||||
this->compressed_permz= this->compressed_permx;
|
||||
this->compressed_permz = fp.has_double("PERMZ")
|
||||
? fp.get_double("PERMZ") : this->compressed_permx;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -202,11 +195,11 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
|
||||
const double * satfunc(const std::vector<double>& data, std::size_t active_index) const {
|
||||
if (data.empty())
|
||||
return nullptr;
|
||||
return &(data[active_index]);
|
||||
const double *
|
||||
satfunc(const std::vector<double>& data,
|
||||
const std::size_t active_index) const
|
||||
{
|
||||
return data.empty() ? nullptr : &data[active_index];
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,13 +34,8 @@
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/SgfnTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/SgofTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/SlgofTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/Sof2Table.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/Sof3Table.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/SwfnTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/SwofTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
#endif
|
||||
|
||||
@ -66,24 +61,18 @@ template <class Scalar>
|
||||
struct EclEpsScalingPointsInfo
|
||||
{
|
||||
// connate saturations
|
||||
Scalar Swl; // oil
|
||||
Scalar Swl; // water
|
||||
Scalar Sgl; // gas
|
||||
Scalar Sowl; // oil for the oil-water system
|
||||
Scalar Sogl; // oil for the gas-oil system
|
||||
|
||||
// critical water and gas saturations
|
||||
Scalar krCriticalEps; // relative permeability below which a saturation is considered
|
||||
// to be critical
|
||||
Scalar Swcr; // oil
|
||||
// critical saturations
|
||||
Scalar Swcr; // water
|
||||
Scalar Sgcr; // gas
|
||||
Scalar Sowcr; // oil for the oil-water system
|
||||
Scalar Sogcr; // oil for the gas-oil system
|
||||
|
||||
// maximum saturations
|
||||
Scalar Swu; // oil
|
||||
Scalar Swu; // water
|
||||
Scalar Sgu; // gas
|
||||
Scalar Sowu; // oil for the oil-water system
|
||||
Scalar Sogu; // oil for the gas-oil system
|
||||
|
||||
// maximum capillary pressures
|
||||
Scalar maxPcow; // maximum capillary pressure of the oil-water system
|
||||
@ -104,17 +93,12 @@ struct EclEpsScalingPointsInfo
|
||||
{
|
||||
return Swl == data.Swl &&
|
||||
Sgl == data.Sgl &&
|
||||
Sowl == data.Sowl &&
|
||||
Sogl == data.Sogl &&
|
||||
krCriticalEps == data.krCriticalEps &&
|
||||
Swcr == data.Swcr &&
|
||||
Sgcr == data.Sgcr &&
|
||||
Sowcr == data.Sowcr &&
|
||||
Sogcr == data.Sogcr &&
|
||||
Swu == data.Swu &&
|
||||
Sgu == data.Sgu &&
|
||||
Sowu == data.Sowu &&
|
||||
Sogu == data.Sogu &&
|
||||
maxPcow == data.maxPcow &&
|
||||
maxPcgo == data.maxPcgo &&
|
||||
pcowLeverettFactor == data.pcowLeverettFactor &&
|
||||
@ -127,26 +111,22 @@ struct EclEpsScalingPointsInfo
|
||||
|
||||
void print() const
|
||||
{
|
||||
std::cout << " Swl: " << Swl << "\n"
|
||||
<< " Sgl: " << Sgl << "\n"
|
||||
<< " Sowl: " << Sowl << "\n"
|
||||
<< " Sogl: " << Sogl << "\n"
|
||||
<< " Swcr: " << Swcr << "\n"
|
||||
<< " Sgcr: " << Sgcr << "\n"
|
||||
<< " Sowcr: " << Sowcr << "\n"
|
||||
<< " Sogcr: " << Sogcr << "\n"
|
||||
<< " Swu: " << Swu << "\n"
|
||||
<< " Sgu: " << Sgu << "\n"
|
||||
<< " Sowu: " << Sowu << "\n"
|
||||
<< " Sogu: " << Sogu << "\n"
|
||||
<< " maxPcow: " << maxPcow << "\n"
|
||||
<< " maxPcgo: " << maxPcgo << "\n"
|
||||
<< " pcowLeverettFactor: " << pcowLeverettFactor << "\n"
|
||||
<< " pcgoLeverettFactor: " << pcgoLeverettFactor << "\n"
|
||||
<< " maxKrw: " << maxKrw << "\n"
|
||||
<< " maxKrg: " << maxKrg << "\n"
|
||||
<< " maxKrow: " << maxKrow << "\n"
|
||||
<< " maxKrog: " << maxKrog << "\n";
|
||||
std::cout << " Swl: " << Swl << '\n'
|
||||
<< " Sgl: " << Sgl << '\n'
|
||||
<< " Swcr: " << Swcr << '\n'
|
||||
<< " Sgcr: " << Sgcr << '\n'
|
||||
<< " Sowcr: " << Sowcr << '\n'
|
||||
<< " Sogcr: " << Sogcr << '\n'
|
||||
<< " Swu: " << Swu << '\n'
|
||||
<< " Sgu: " << Sgu << '\n'
|
||||
<< " maxPcow: " << maxPcow << '\n'
|
||||
<< " maxPcgo: " << maxPcgo << '\n'
|
||||
<< " pcowLeverettFactor: " << pcowLeverettFactor << '\n'
|
||||
<< " pcgoLeverettFactor: " << pcgoLeverettFactor << '\n'
|
||||
<< " maxKrw: " << maxKrw << '\n'
|
||||
<< " maxKrg: " << maxKrg << '\n'
|
||||
<< " maxKrow: " << maxKrow << '\n'
|
||||
<< " maxKrog: " << maxKrog << '\n';
|
||||
}
|
||||
|
||||
#if HAVE_ECL_INPUT
|
||||
@ -156,105 +136,38 @@ struct EclEpsScalingPointsInfo
|
||||
* I.e., the values which are used for the nested Fluid-Matrix interactions and which
|
||||
* are produced by them.
|
||||
*/
|
||||
void extractUnscaled(const Opm::EclipseState& eclState,
|
||||
unsigned satRegionIdx)
|
||||
void extractUnscaled(const Opm::satfunc::RawTableEndPoints& rtep,
|
||||
const Opm::satfunc::RawFunctionValues& rfunc,
|
||||
const Opm::SatFuncControls::KeywordFamily family,
|
||||
const std::vector<double>::size_type satRegionIdx)
|
||||
{
|
||||
// determine the value of the relative permeability below which the corresponding
|
||||
// saturation is considered to be critical
|
||||
const auto& satFuncCtrls = eclState.runspec().saturationFunctionControls();
|
||||
krCriticalEps = satFuncCtrls.minimumRelpermMobilityThreshold();
|
||||
this->Swl = rtep.connate.water[satRegionIdx];
|
||||
this->Sgl = rtep.connate.gas [satRegionIdx];
|
||||
|
||||
const auto& tables = eclState.getTableManager();
|
||||
const TableContainer& swofTables = tables.getSwofTables();
|
||||
const TableContainer& sgofTables = tables.getSgofTables();
|
||||
const TableContainer& slgofTables = tables.getSlgofTables();
|
||||
const TableContainer& swfnTables = tables.getSwfnTables();
|
||||
const TableContainer& sgfnTables = tables.getSgfnTables();
|
||||
const TableContainer& sof3Tables = tables.getSof3Tables();
|
||||
const TableContainer& sof2Tables = tables.getSof2Tables();
|
||||
|
||||
|
||||
bool hasWater = eclState.runspec().phases().active(Phase::WATER);
|
||||
bool hasGas = eclState.runspec().phases().active(Phase::GAS);
|
||||
bool hasOil = eclState.runspec().phases().active(Phase::OIL);
|
||||
|
||||
if (int(hasWater) + int(hasGas) + int(hasOil) == 1) {
|
||||
return;
|
||||
} else if (!hasWater) {
|
||||
Swl = 0.0;
|
||||
Swu = 0.0;
|
||||
Swcr = 0.0;
|
||||
bool family1 = (!sgofTables.empty() || !slgofTables.empty());
|
||||
bool family2 = !sgfnTables.empty() && !sof2Tables.empty();
|
||||
if (family1) {
|
||||
if (!sgofTables.empty())
|
||||
extractUnscaledSgof_(sgofTables.getTable<SgofTable>(satRegionIdx));
|
||||
else {
|
||||
assert(!slgofTables.empty());
|
||||
extractUnscaledSlgof_(slgofTables.getTable<SlgofTable>(satRegionIdx));
|
||||
}
|
||||
} else if (family2) {
|
||||
extractUnscaledSgfn_(sgfnTables.getTable<SgfnTable>(satRegionIdx));
|
||||
extractUnscaledSof2_(sof2Tables.getTable<Sof2Table>(satRegionIdx));
|
||||
}
|
||||
else {
|
||||
throw std::domain_error("No valid saturation keyword family specified");
|
||||
}
|
||||
return;
|
||||
} else if (!hasGas) {
|
||||
Sgl = 0.0;
|
||||
Sgu = 0.0;
|
||||
Sgcr = 0.0;
|
||||
bool family1 = !swofTables.empty();
|
||||
bool family2 = !swfnTables.empty() && !sof2Tables.empty();
|
||||
if (family1) {
|
||||
extractUnscaledSwof_(swofTables.getTable<SwofTable>(satRegionIdx));
|
||||
} else if (family2) {
|
||||
extractUnscaledSwfn_(swfnTables.getTable<SwfnTable>(satRegionIdx));
|
||||
extractUnscaledSof2_(sof2Tables.getTable<Sof2Table>(satRegionIdx));
|
||||
}
|
||||
else {
|
||||
throw std::domain_error("No valid saturation keyword family specified");
|
||||
}
|
||||
return;
|
||||
this->Swcr = rtep.critical.water [satRegionIdx];
|
||||
this->Sgcr = rtep.critical.gas [satRegionIdx];
|
||||
this->Sowcr = rtep.critical.oil_in_water[satRegionIdx];
|
||||
this->Sogcr = rtep.critical.oil_in_gas [satRegionIdx];
|
||||
if (family == SatFuncControls::KeywordFamily::Family_I) {
|
||||
// Hack. Papers over unknown problems elsewhere.
|
||||
this->Sogcr += this->Swl;
|
||||
}
|
||||
|
||||
bool family1 = (!sgofTables.empty() || !slgofTables.empty()) && !swofTables.empty();
|
||||
bool family2 = !swfnTables.empty() && !sgfnTables.empty() && !sof3Tables.empty();
|
||||
this->Swu = rtep.maximum.water[satRegionIdx];
|
||||
this->Sgu = rtep.maximum.gas [satRegionIdx];
|
||||
|
||||
// so far, only water-oil and oil-gas simulations are supported, i.e.,
|
||||
// there's no gas-water yet.
|
||||
if (!hasWater || !hasGas || !hasOil)
|
||||
throw std::domain_error("The specified phase configuration is not suppored");
|
||||
|
||||
if (family1) {
|
||||
extractUnscaledSwof_(swofTables.getTable<SwofTable>(satRegionIdx));
|
||||
|
||||
if (!sgofTables.empty()) {
|
||||
// gas-oil parameters are specified using the SGOF keyword
|
||||
extractUnscaledSgof_(sgofTables.getTable<SgofTable>(satRegionIdx));
|
||||
}
|
||||
else {
|
||||
// gas-oil parameters are specified using the SLGOF keyword
|
||||
assert(!slgofTables.empty());
|
||||
|
||||
extractUnscaledSlgof_(slgofTables.getTable<SlgofTable>(satRegionIdx));
|
||||
}
|
||||
}
|
||||
else if (family2) {
|
||||
extractUnscaledSwfn_(swfnTables.getTable<SwfnTable>(satRegionIdx));
|
||||
extractUnscaledSgfn_(sgfnTables.getTable<SgfnTable>(satRegionIdx));
|
||||
extractUnscaledSof3_(sof3Tables.getTable<Sof3Table>(satRegionIdx));
|
||||
}
|
||||
else {
|
||||
throw std::domain_error("No valid saturation keyword family specified");
|
||||
}
|
||||
this->maxPcgo = rfunc.pc.g[satRegionIdx];
|
||||
this->maxPcow = rfunc.pc.w[satRegionIdx];
|
||||
|
||||
// there are no "unscaled" Leverett factors, so we just set them to 1.0
|
||||
pcowLeverettFactor = 1.0;
|
||||
pcgoLeverettFactor = 1.0;
|
||||
}
|
||||
this->pcowLeverettFactor = 1.0;
|
||||
this->pcgoLeverettFactor = 1.0;
|
||||
|
||||
this->maxKrw = rfunc.krw.max[satRegionIdx];
|
||||
this->maxKrow = rfunc.kro.max[satRegionIdx];
|
||||
this->maxKrog = rfunc.kro.max[satRegionIdx];
|
||||
this->maxKrg = rfunc.krg.max[satRegionIdx];
|
||||
}
|
||||
|
||||
void update(Scalar& targetValue, const double * value_ptr) {
|
||||
if (value_ptr)
|
||||
@ -354,233 +267,6 @@ struct EclEpsScalingPointsInfo
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if HAVE_ECL_INPUT
|
||||
void extractUnscaledSgof_(const Opm::SgofTable& sgofTable)
|
||||
{
|
||||
// minimum gas and oil-in-gas-oil saturation
|
||||
Sgl = sgofTable.getSgColumn().front();
|
||||
Sogl = 1.0 - sgofTable.getSgColumn().back();
|
||||
|
||||
// maximum gas and oil-in-gas-oil saturation
|
||||
Sgu = sgofTable.getSgColumn().back();
|
||||
Sogu = 1.0 - sgofTable.getSgColumn().front();
|
||||
|
||||
// critical gas saturation
|
||||
Sgcr = 0.0;
|
||||
for (size_t rowIdx = 0; rowIdx < sgofTable.numRows(); ++ rowIdx) {
|
||||
if (sgofTable.getKrgColumn()[rowIdx] > krCriticalEps)
|
||||
break;
|
||||
|
||||
Sgcr = sgofTable.getSgColumn()[rowIdx];
|
||||
}
|
||||
|
||||
// critical oil saturation of gas-oil system
|
||||
Sogcr = 0.0;
|
||||
for (int rowIdx = static_cast<int>(sgofTable.numRows() - 1);
|
||||
rowIdx >= 0;
|
||||
-- rowIdx)
|
||||
{
|
||||
if (sgofTable.getKrogColumn()[static_cast<size_t>(rowIdx)] > krCriticalEps)
|
||||
break;
|
||||
|
||||
Sogcr = 1.0 - sgofTable.getSgColumn()[static_cast<size_t>(rowIdx)];
|
||||
}
|
||||
|
||||
// maximum gas-oil capillary pressure
|
||||
maxPcgo = sgofTable.getPcogColumn().back();
|
||||
|
||||
// maximum gas-* relperms
|
||||
maxKrg = sgofTable.getKrgColumn().back();
|
||||
maxKrog = sgofTable.getKrogColumn().front();
|
||||
}
|
||||
|
||||
void extractUnscaledSlgof_(const Opm::SlgofTable& slgofTable)
|
||||
{
|
||||
// minimum gas and oil-in-gas-oil saturation
|
||||
Sgl = 1.0 - slgofTable.getSlColumn().back();
|
||||
Sogl = slgofTable.getSlColumn().front();
|
||||
|
||||
// maximum gas and oil-in-gas-oil saturation
|
||||
Sgu = 1.0 - slgofTable.getSlColumn().front();
|
||||
Sogu = slgofTable.getSlColumn().back();
|
||||
|
||||
// critical gas saturation
|
||||
Sgcr = 0.0;
|
||||
for (int rowIdx = static_cast<int>(slgofTable.numRows()) - 1;
|
||||
rowIdx >= 0;
|
||||
-- rowIdx)
|
||||
{
|
||||
if (slgofTable.getKrgColumn()[static_cast<size_t>(rowIdx)] > krCriticalEps)
|
||||
break;
|
||||
|
||||
Sgcr = 1 - slgofTable.getSlColumn()[static_cast<size_t>(rowIdx)];
|
||||
}
|
||||
|
||||
// critical oil saturation of gas-oil system
|
||||
Sogcr = 0.0;
|
||||
for (size_t rowIdx = 0; rowIdx < slgofTable.numRows(); ++ rowIdx) {
|
||||
if (slgofTable.getKrogColumn()[rowIdx] > krCriticalEps)
|
||||
break;
|
||||
|
||||
Sogcr = slgofTable.getSlColumn()[rowIdx];
|
||||
}
|
||||
|
||||
// maximum gas-oil capillary pressure
|
||||
maxPcgo = slgofTable.getPcogColumn().front();
|
||||
|
||||
// maximum gas-* relperms
|
||||
maxKrg = slgofTable.getKrgColumn().front();
|
||||
maxKrog = slgofTable.getKrogColumn().back();
|
||||
}
|
||||
|
||||
void extractUnscaledSwof_(const Opm::SwofTable& swofTable)
|
||||
{
|
||||
// connate saturations
|
||||
Swl = swofTable.getSwColumn().front();
|
||||
Sowl = 1.0 - swofTable.getSwColumn().back();
|
||||
|
||||
// maximum water and oil-in-oil-water saturations
|
||||
Swu = swofTable.getSwColumn().back();
|
||||
Sowu = 1.0 - swofTable.getSwColumn().front();
|
||||
|
||||
// critical water saturation
|
||||
Swcr = 0.0;
|
||||
for (size_t rowIdx = 0; rowIdx < swofTable.numRows(); ++ rowIdx) {
|
||||
if (swofTable.getKrwColumn()[rowIdx] > krCriticalEps)
|
||||
break;
|
||||
|
||||
Swcr = swofTable.getSwColumn()[rowIdx];
|
||||
}
|
||||
|
||||
// critical oil saturation of oil-water system
|
||||
Sowcr = 0.0;
|
||||
for (int rowIdx = static_cast<int>(swofTable.numRows()) - 1;
|
||||
rowIdx >= 0;
|
||||
-- rowIdx)
|
||||
{
|
||||
if (swofTable.getKrowColumn()[static_cast<size_t>(rowIdx)] > krCriticalEps)
|
||||
break;
|
||||
|
||||
Sowcr = 1.0 - swofTable.getSwColumn()[static_cast<size_t>(rowIdx)];
|
||||
}
|
||||
|
||||
// maximum oil-water capillary pressures
|
||||
maxPcow = swofTable.getPcowColumn().front();
|
||||
|
||||
// maximum water-* relative permeabilities
|
||||
maxKrw = swofTable.getKrwColumn().back();
|
||||
maxKrow = swofTable.getKrowColumn().front();
|
||||
}
|
||||
|
||||
void extractUnscaledSwfn_(const Opm::SwfnTable& swfnTable)
|
||||
{
|
||||
// connate water saturation
|
||||
Swl = swfnTable.getSwColumn().front();
|
||||
|
||||
// maximum water saturation
|
||||
Swu = swfnTable.getSwColumn().back();
|
||||
|
||||
// critical water saturation
|
||||
Swcr = 0.0;
|
||||
for (size_t rowIdx = 0; rowIdx < swfnTable.numRows(); ++ rowIdx) {
|
||||
if (swfnTable.getKrwColumn()[rowIdx] > krCriticalEps)
|
||||
break;
|
||||
|
||||
Swcr = swfnTable.getSwColumn()[rowIdx];
|
||||
}
|
||||
|
||||
// maximum oil-water capillary pressure
|
||||
maxPcow = swfnTable.getPcowColumn().front();
|
||||
|
||||
// maximum water relative permeability
|
||||
maxKrw = swfnTable.getKrwColumn().back();
|
||||
}
|
||||
|
||||
void extractUnscaledSgfn_(const Opm::SgfnTable& sgfnTable)
|
||||
{
|
||||
// connate gas saturation
|
||||
Sgl = sgfnTable.getSgColumn().front();
|
||||
|
||||
// maximum gas saturations
|
||||
Sgu = sgfnTable.getSgColumn().back();
|
||||
Sogu = 1 - sgfnTable.getSgColumn().front();
|
||||
|
||||
// critical gas saturation
|
||||
Sgcr = 0.0;
|
||||
for (size_t rowIdx = 0; rowIdx < sgfnTable.numRows(); ++ rowIdx) {
|
||||
if (sgfnTable.getKrgColumn()[rowIdx] > krCriticalEps)
|
||||
break;
|
||||
|
||||
Sgcr = sgfnTable.getSgColumn()[rowIdx];
|
||||
}
|
||||
|
||||
// maximum capillary pressure
|
||||
maxPcgo = sgfnTable.getPcogColumn().back();
|
||||
|
||||
// maximum relative gas permeability
|
||||
maxKrg = sgfnTable.getKrgColumn().back();
|
||||
}
|
||||
|
||||
void extractUnscaledSof3_(const Opm::Sof3Table& sof3Table)
|
||||
{
|
||||
// connate oil saturations
|
||||
Sowl = sof3Table.getSoColumn().front() + Sgl;
|
||||
Sogl = sof3Table.getSoColumn().front() + Swl;
|
||||
|
||||
// maximum oil saturations
|
||||
Sowu = sof3Table.getSoColumn().back();
|
||||
|
||||
// critical oil saturation of oil-water system
|
||||
Sowcr = 0.0;
|
||||
for (size_t rowIdx = 0 ; rowIdx < sof3Table.numRows(); ++ rowIdx) {
|
||||
if (sof3Table.getKrowColumn()[rowIdx] > krCriticalEps) {
|
||||
break;
|
||||
}
|
||||
|
||||
Sowcr = sof3Table.getSoColumn()[rowIdx];
|
||||
}
|
||||
|
||||
// critical oil saturation of gas-oil system
|
||||
Sogcr = 0.0;
|
||||
for (size_t rowIdx = 0 ; rowIdx < sof3Table.numRows(); ++ rowIdx) {
|
||||
if (sof3Table.getKrogColumn()[rowIdx] > krCriticalEps)
|
||||
break;
|
||||
|
||||
Sogcr = sof3Table.getSoColumn()[rowIdx];
|
||||
}
|
||||
|
||||
// maximum relative oil permeabilities
|
||||
maxKrow = sof3Table.getKrowColumn().back();
|
||||
maxKrog = sof3Table.getKrogColumn().back();
|
||||
}
|
||||
|
||||
void extractUnscaledSof2_(const Opm::Sof2Table& sof2Table)
|
||||
{
|
||||
// connate oil saturations
|
||||
Sowl = sof2Table.getSoColumn().front() + Sgl;
|
||||
Sogl = sof2Table.getSoColumn().front() + Swl;
|
||||
|
||||
// maximum oil saturations
|
||||
Sowu = sof2Table.getSoColumn().back();
|
||||
|
||||
// critical oil saturation of oil-water system or critical oil saturation of
|
||||
// gas-oil system
|
||||
Sowcr = 0.0;
|
||||
for (size_t rowIdx = 0 ; rowIdx < sof2Table.numRows(); ++ rowIdx) {
|
||||
if (sof2Table.getKroColumn()[rowIdx] > krCriticalEps) {
|
||||
break;
|
||||
}
|
||||
|
||||
Sowcr = sof2Table.getSoColumn()[rowIdx];
|
||||
}
|
||||
Sogcr = Sowcr;
|
||||
|
||||
// maximum relative oil permeabilities
|
||||
maxKrow = sof2Table.getKroColumn().back();
|
||||
maxKrog = maxKrow;
|
||||
}
|
||||
#endif // HAVE_ECL_INPUT
|
||||
|
||||
void extractGridPropertyValue_(Scalar& targetValue,
|
||||
const std::vector<double>* propData,
|
||||
unsigned cartesianCellIdx)
|
||||
|
@ -50,7 +50,10 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@ -116,32 +119,57 @@ public:
|
||||
void initFromState(const Opm::EclipseState& eclState)
|
||||
{
|
||||
// get the number of saturation regions and the number of cells in the deck
|
||||
const size_t numSatRegions = eclState.runspec().tabdims().getNumSatTables();
|
||||
const auto& runspec = eclState.runspec();
|
||||
const size_t numSatRegions = runspec.tabdims().getNumSatTables();
|
||||
|
||||
const auto& ph = eclState.runspec().phases();
|
||||
hasGas = ph.active(Phase::GAS);
|
||||
hasOil = ph.active(Phase::OIL);
|
||||
hasWater = ph.active(Phase::WATER);
|
||||
const auto& ph = runspec.phases();
|
||||
this->hasGas = ph.active(Phase::GAS);
|
||||
this->hasOil = ph.active(Phase::OIL);
|
||||
this->hasWater = ph.active(Phase::WATER);
|
||||
|
||||
readGlobalEpsOptions_(eclState);
|
||||
readGlobalHysteresisOptions_(eclState);
|
||||
readGlobalThreePhaseOptions_(eclState.runspec());
|
||||
readGlobalThreePhaseOptions_(runspec);
|
||||
|
||||
// read the end point scaling configuration. this needs to be done only once per
|
||||
// deck.
|
||||
// Read the end point scaling configuration (once per run).
|
||||
gasOilConfig = std::make_shared<Opm::EclEpsConfig>();
|
||||
oilWaterConfig = std::make_shared<Opm::EclEpsConfig>();
|
||||
gasOilConfig->initFromState(eclState, Opm::EclGasOilSystem);
|
||||
oilWaterConfig->initFromState(eclState, Opm::EclOilWaterSystem);
|
||||
|
||||
unscaledEpsInfo_.resize(numSatRegions);
|
||||
const auto& stone1exTable = eclState.getTableManager().getStone1exTable();
|
||||
if (!stone1exTable.empty())
|
||||
stoneEtas.resize(numSatRegions);
|
||||
const auto& tables = eclState.getTableManager();
|
||||
|
||||
{
|
||||
const auto& stone1exTables = tables.getStone1exTable();
|
||||
|
||||
if (! stone1exTables.empty()) {
|
||||
stoneEtas.clear();
|
||||
stoneEtas.reserve(numSatRegions);
|
||||
|
||||
for (const auto& table : stone1exTables) {
|
||||
stoneEtas.push_back(table.eta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->unscaledEpsInfo_.resize(numSatRegions);
|
||||
|
||||
if (this->hasGas + this->hasOil + this->hasWater == 1) {
|
||||
// Single-phase simulation. Special case. Nothing to do here.
|
||||
return;
|
||||
}
|
||||
|
||||
// Multiphase simulation. Common case.
|
||||
const auto tolcrit = runspec.saturationFunctionControls()
|
||||
.minimumRelpermMobilityThreshold();
|
||||
|
||||
const auto family = runspec.saturationFunctionControls().family();
|
||||
const auto rtepPtr = satfunc::getRawTableEndpoints(tables, ph, tolcrit);
|
||||
const auto rfuncPtr = satfunc::getRawFunctionValues(tables, ph, *rtepPtr);
|
||||
|
||||
for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
|
||||
unscaledEpsInfo_[satRegionIdx].extractUnscaled(eclState, satRegionIdx);
|
||||
if (!stoneEtas.empty())
|
||||
stoneEtas[satRegionIdx] = stone1exTable[satRegionIdx].eta;
|
||||
this->unscaledEpsInfo_[satRegionIdx]
|
||||
.extractUnscaled(*rtepPtr, *rfuncPtr, family, satRegionIdx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +250,6 @@ public:
|
||||
eclState,
|
||||
epsGridProperties,
|
||||
elemIdx);
|
||||
|
||||
}
|
||||
|
||||
if (enableHysteresis()) {
|
||||
@ -661,65 +688,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// The saturation function family.
|
||||
// If SWOF and SGOF are specified in the deck it return FamilyI
|
||||
// If SWFN, SGFN and SOF3 are specified in the deck it return FamilyII
|
||||
// If keywords are missing or mixed, an error is given.
|
||||
enum SaturationFunctionFamily {
|
||||
noFamily,
|
||||
FamilyI,
|
||||
FamilyII
|
||||
};
|
||||
|
||||
SaturationFunctionFamily getSaturationFunctionFamily(const Opm::EclipseState& eclState) const
|
||||
{
|
||||
const auto& tableManager = eclState.getTableManager();
|
||||
const TableContainer& swofTables = tableManager.getSwofTables();
|
||||
const TableContainer& slgofTables= tableManager.getSlgofTables();
|
||||
const TableContainer& sgofTables = tableManager.getSgofTables();
|
||||
const TableContainer& swfnTables = tableManager.getSwfnTables();
|
||||
const TableContainer& sgfnTables = tableManager.getSgfnTables();
|
||||
const TableContainer& sof3Tables = tableManager.getSof3Tables();
|
||||
const TableContainer& sof2Tables = tableManager.getSof2Tables();
|
||||
|
||||
bool family1 = false;
|
||||
bool family2 = false;
|
||||
if (!hasGas) {
|
||||
// oil-water case
|
||||
family1 = !swofTables.empty();
|
||||
family2 = !swfnTables.empty() && !sof2Tables.empty();
|
||||
}
|
||||
else if (!hasWater) {
|
||||
// oil-gas case
|
||||
family1 = !sgofTables.empty();
|
||||
family2 = !sgfnTables.empty() && !sof2Tables.empty();
|
||||
}
|
||||
else if (!hasOil) {
|
||||
// water-gas case
|
||||
throw std::runtime_error("water-gas two-phase simulations are currently not supported");
|
||||
}
|
||||
else {
|
||||
// three-phase case
|
||||
family1 = (!sgofTables.empty() || !slgofTables.empty()) && !swofTables.empty();
|
||||
family2 = !swfnTables.empty() && !sgfnTables.empty() && !sof3Tables.empty();
|
||||
}
|
||||
|
||||
if (family1 && family2)
|
||||
throw std::invalid_argument("Saturation families should not be mixed \n"
|
||||
"Use either SGOF and SWOF or SGFN, SWFN and SOF3");
|
||||
|
||||
if (!family1 && !family2)
|
||||
throw std::invalid_argument("Saturations function must be specified using either "
|
||||
"family 1 or family 2 keywords \n"
|
||||
"Use either SGOF and SWOF or SGFN, SWFN and SOF3" );
|
||||
|
||||
if (family1 && !family2)
|
||||
return SaturationFunctionFamily::FamilyI;
|
||||
else if (family2 && !family1)
|
||||
return SaturationFunctionFamily::FamilyII;
|
||||
return SaturationFunctionFamily::noFamily; // no family or two families
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
void readGasOilEffectiveParameters_(Container& dest,
|
||||
const Opm::EclipseState& eclState,
|
||||
@ -735,11 +703,11 @@ private:
|
||||
|
||||
// the situation for the gas phase is complicated that all saturations are
|
||||
// shifted by the connate water saturation.
|
||||
Scalar Swco = unscaledEpsInfo_[satRegionIdx].Swl;
|
||||
const Scalar Swco = unscaledEpsInfo_[satRegionIdx].Swl;
|
||||
const auto& tableManager = eclState.getTableManager();
|
||||
|
||||
switch (getSaturationFunctionFamily(eclState)) {
|
||||
case FamilyI:
|
||||
switch (eclState.runspec().saturationFunctionControls().family()) {
|
||||
case SatFuncControls::KeywordFamily::Family_I:
|
||||
{
|
||||
const TableContainer& sgofTables = tableManager.getSgofTables();
|
||||
const TableContainer& slgofTables = tableManager.getSlgofTables();
|
||||
@ -754,7 +722,7 @@ private:
|
||||
break;
|
||||
}
|
||||
|
||||
case FamilyII:
|
||||
case SatFuncControls::KeywordFamily::Family_II:
|
||||
{
|
||||
const SgfnTable& sgfnTable = tableManager.getSgfnTables().getTable<SgfnTable>( satRegionIdx );
|
||||
if (!hasWater) {
|
||||
@ -774,8 +742,7 @@ private:
|
||||
break;
|
||||
}
|
||||
|
||||
//default:
|
||||
case noFamily:
|
||||
case SatFuncControls::KeywordFamily::Undefined:
|
||||
throw std::domain_error("No valid saturation keyword family specified");
|
||||
}
|
||||
}
|
||||
@ -866,8 +833,9 @@ private:
|
||||
const auto& tableManager = eclState.getTableManager();
|
||||
auto& effParams = *dest[satRegionIdx];
|
||||
|
||||
switch (getSaturationFunctionFamily(eclState)) {
|
||||
case FamilyI: {
|
||||
switch (eclState.runspec().saturationFunctionControls().family()) {
|
||||
case SatFuncControls::KeywordFamily::Family_I:
|
||||
{
|
||||
const auto& swofTable = tableManager.getSwofTables().getTable<SwofTable>(satRegionIdx);
|
||||
std::vector<double> SwColumn = swofTable.getColumn("SW").vectorCopy();
|
||||
|
||||
@ -877,7 +845,8 @@ private:
|
||||
effParams.finalize();
|
||||
break;
|
||||
}
|
||||
case FamilyII:
|
||||
|
||||
case SatFuncControls::KeywordFamily::Family_II:
|
||||
{
|
||||
const auto& swfnTable = tableManager.getSwfnTables().getTable<SwfnTable>(satRegionIdx);
|
||||
const auto& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>(satRegionIdx);
|
||||
@ -895,10 +864,8 @@ private:
|
||||
break;
|
||||
}
|
||||
|
||||
case noFamily:
|
||||
//default:
|
||||
case SatFuncControls::KeywordFamily::Undefined:
|
||||
throw std::domain_error("No valid saturation keyword family specified");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user