EclMaterialLawManager: add saturation region-specific material law parameters

this is needed for the well model. Be aware that in the future this
will probably need to be changed to have one material parameter object
per connection instead of one per saturation region. This attitude
adjustment would be necessary to support endpoint scaling and
hysteresis in the well model, but so far it is unclear what the
reference simulator does.
This commit is contained in:
Andreas Lauser 2017-02-17 16:19:08 +01:00
parent 9d6a620680
commit 1f2d72aba1

View File

@ -138,8 +138,8 @@ public:
readGlobalThreePhaseOptions_(deck);
unscaledEpsInfo_.resize(numSatRegions);
for (unsigned satnumIdx = 0; satnumIdx < numSatRegions; ++satnumIdx)
unscaledEpsInfo_[satnumIdx].extractUnscaled(deck, eclState, satnumIdx);
for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx)
unscaledEpsInfo_[satRegionIdx].extractUnscaled(deck, eclState, satRegionIdx);
initParamsForElements_(deck, eclState, compressedToCartesianElemIdx, satnumRegionArray);
}
@ -213,6 +213,19 @@ public:
return *materialLawParams_[elemIdx];
}
/*!
* \brief Returns a material parameter object for a given saturation region.
*
* In the context of ECL reservoir simulators, this is required to properly handle
* wells. These objects cannot consider hysteresis and enpoint scaling because these
* two features need one material parameter object element/connection.
*/
const MaterialLawParams& satRegionMaterialLawParams(unsigned satRegionIdx) const
{
assert(0 <= satRegionIdx && satRegionIdx < satRegionMaterialLawParams_.size());
return *satRegionMaterialLawParams_[satRegionIdx];
}
std::shared_ptr<MaterialLawParams>& materialLawParamsPointerReferenceHack(unsigned elemIdx)
{
assert(0 <= elemIdx && elemIdx < materialLawParams_.size());
@ -335,17 +348,17 @@ private:
OilWaterScalingPointsVector oilWaterUnscaledPointsVector(numSatRegions);
GasOilEffectiveParamVector gasOilEffectiveParamVector(numSatRegions);
OilWaterEffectiveParamVector oilWaterEffectiveParamVector(numSatRegions);
for (unsigned satnumIdx = 0; satnumIdx < numSatRegions; ++satnumIdx) {
for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
// unscaled points for end-point scaling
readGasOilUnscaledPoints_(gasOilUnscaledPointsVector, gasOilConfig, deck, eclState, satnumIdx);
readOilWaterUnscaledPoints_(oilWaterUnscaledPointsVector, oilWaterConfig, deck, eclState, satnumIdx);
readGasOilUnscaledPoints_(gasOilUnscaledPointsVector, gasOilConfig, deck, eclState, satRegionIdx);
readOilWaterUnscaledPoints_(oilWaterUnscaledPointsVector, oilWaterConfig, deck, eclState, satRegionIdx);
// the parameters for the effective two-phase matererial laws
readGasOilEffectiveParameters_(gasOilEffectiveParamVector, deck, eclState, satnumIdx);
readOilWaterEffectiveParameters_(oilWaterEffectiveParamVector, deck, eclState, satnumIdx);
readGasOilEffectiveParameters_(gasOilEffectiveParamVector, deck, eclState, satRegionIdx);
readOilWaterEffectiveParameters_(oilWaterEffectiveParamVector, deck, eclState, satRegionIdx);
// read the end point scaling info for the saturation region
unscaledEpsInfo_[satnumIdx].extractUnscaled(deck, eclState, satnumIdx);
unscaledEpsInfo_[satRegionIdx].extractUnscaled(deck, eclState, satRegionIdx);
}
@ -425,7 +438,7 @@ private:
const auto& imbnumData = eclState.get3DProperties().getIntGridProperty("IMBNUM").getData();
assert(numCompressedElems == satnumRegionArray.size());
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
unsigned satnumIdx = static_cast<unsigned>(satnumRegionArray[elemIdx]);
unsigned satRegionIdx = static_cast<unsigned>(satnumRegionArray[elemIdx]);
gasOilParams[elemIdx] = std::make_shared<GasOilTwoPhaseHystParams>();
oilWaterParams[elemIdx] = std::make_shared<OilWaterTwoPhaseHystParams>();
@ -436,9 +449,9 @@ private:
if (hasGas && hasOil) {
auto gasOilDrainParams = std::make_shared<GasOilEpsTwoPhaseParams>();
gasOilDrainParams->setConfig(gasOilConfig);
gasOilDrainParams->setUnscaledPoints(gasOilUnscaledPointsVector[satnumIdx]);
gasOilDrainParams->setUnscaledPoints(gasOilUnscaledPointsVector[satRegionIdx]);
gasOilDrainParams->setScaledPoints(gasOilScaledPointsVector[elemIdx]);
gasOilDrainParams->setEffectiveLawParams(gasOilEffectiveParamVector[satnumIdx]);
gasOilDrainParams->setEffectiveLawParams(gasOilEffectiveParamVector[satRegionIdx]);
gasOilDrainParams->finalize();
gasOilParams[elemIdx]->setDrainageParams(gasOilDrainParams,
@ -449,9 +462,9 @@ private:
if (hasOil && hasWater) {
auto oilWaterDrainParams = std::make_shared<OilWaterEpsTwoPhaseParams>();
oilWaterDrainParams->setConfig(oilWaterConfig);
oilWaterDrainParams->setUnscaledPoints(oilWaterUnscaledPointsVector[satnumIdx]);
oilWaterDrainParams->setUnscaledPoints(oilWaterUnscaledPointsVector[satRegionIdx]);
oilWaterDrainParams->setScaledPoints(oilWaterScaledEpsPointsDrainage[elemIdx]);
oilWaterDrainParams->setEffectiveLawParams(oilWaterEffectiveParamVector[satnumIdx]);
oilWaterDrainParams->setEffectiveLawParams(oilWaterEffectiveParamVector[satRegionIdx]);
oilWaterDrainParams->finalize();
oilWaterParams[elemIdx]->setDrainageParams(oilWaterDrainParams,
@ -500,18 +513,65 @@ private:
materialLawParams_.resize(numCompressedElems);
for (unsigned elemIdx = 0; elemIdx < numCompressedElems; ++elemIdx) {
materialLawParams_[elemIdx] = std::make_shared<MaterialLawParams>();
unsigned satnumIdx = static_cast<unsigned>(satnumRegionArray[elemIdx]);
unsigned satRegionIdx = static_cast<unsigned>(satnumRegionArray[elemIdx]);
initThreePhaseParams_(deck,
eclState,
*materialLawParams_[elemIdx],
satnumIdx,
satRegionIdx,
*oilWaterScaledEpsInfoDrainage_[elemIdx],
oilWaterParams[elemIdx],
gasOilParams[elemIdx]);
materialLawParams_[elemIdx]->finalize();
}
// create the material parameter objects for the saturation regions
auto nohystConfig = std::make_shared<EclHysteresisConfig>();
auto noepsGasOilConfig = std::make_shared<Opm::EclEpsConfig>();
auto noepsOilWaterConfig = std::make_shared<Opm::EclEpsConfig>();
satRegionMaterialLawParams_.resize(numSatRegions);
for (unsigned satRegionIdx = 0; satRegionIdx < numSatRegions; ++satRegionIdx) {
satRegionMaterialLawParams_[satRegionIdx] = std::make_shared<MaterialLawParams>();
// set up the oil-water twophase objects
auto noepsNohystOilWaterParams = std::make_shared<OilWaterEpsTwoPhaseParams>();
noepsNohystOilWaterParams->setConfig(noepsOilWaterConfig);
noepsNohystOilWaterParams->setEffectiveLawParams(oilWaterEffectiveParamVector[satRegionIdx]);
noepsNohystOilWaterParams->finalize();
auto oilWaterParams = std::make_shared<OilWaterTwoPhaseHystParams>();
oilWaterParams->setConfig(nohystConfig);
oilWaterParams->setDrainageParams(noepsNohystOilWaterParams,
*gasOilScaledInfoVector[0], // don't care
EclOilWaterSystem);
oilWaterParams->finalize();
// set up the gas-oil twophase objects
auto noepsNohystGasOilParams = std::make_shared<GasOilEpsTwoPhaseParams>();
noepsNohystGasOilParams->setConfig(noepsGasOilConfig);
noepsNohystGasOilParams->setEffectiveLawParams(gasOilEffectiveParamVector[satRegionIdx]);
noepsNohystGasOilParams->finalize();
auto gasOilParams = std::make_shared<GasOilTwoPhaseHystParams>();
gasOilParams->setConfig(nohystConfig);
gasOilParams->setDrainageParams(noepsNohystGasOilParams,
*gasOilScaledInfoVector[0], // don't care
EclGasOilSystem);
gasOilParams->finalize();
// set up the threephase object for the saturation region
initThreePhaseParams_(deck,
eclState,
*satRegionMaterialLawParams_[satRegionIdx],
satRegionIdx,
*oilWaterScaledEpsInfoDrainage_[0], // don't care
oilWaterParams,
gasOilParams);
satRegionMaterialLawParams_[satRegionIdx]->finalize();
}
}
// The saturation function family.
@ -581,7 +641,7 @@ private:
void readGasOilEffectiveParameters_(Container& dest,
const Opm::Deck& deck,
const Opm::EclipseState& eclState,
unsigned satnumIdx)
unsigned satRegionIdx)
{
bool hasGas = deck.hasKeyword("GAS");
bool hasOil = deck.hasKeyword("OIL");
@ -590,13 +650,13 @@ private:
// we don't read anything if either the gas or the oil phase is not active
return;
dest[satnumIdx] = std::make_shared<GasOilEffectiveTwoPhaseParams>();
dest[satRegionIdx] = std::make_shared<GasOilEffectiveTwoPhaseParams>();
auto& effParams = *dest[satnumIdx];
auto& effParams = *dest[satRegionIdx];
// the situation for the gas phase is complicated that all saturations are
// shifted by the connate water saturation.
Scalar Swco = unscaledEpsInfo_[satnumIdx].Swl;
Scalar Swco = unscaledEpsInfo_[satRegionIdx].Swl;
const auto& tableManager = eclState.getTableManager();
switch (getSaturationFunctionFamily(deck, eclState)) {
@ -607,18 +667,18 @@ private:
if (!sgofTables.empty())
readGasOilEffectiveParametersSgof_(effParams,
Swco,
sgofTables.getTable<SgofTable>(satnumIdx));
sgofTables.getTable<SgofTable>(satRegionIdx));
else if (!slgofTables.empty())
readGasOilEffectiveParametersSlgof_(effParams,
Swco,
slgofTables.getTable<SlgofTable>(satnumIdx));
slgofTables.getTable<SlgofTable>(satRegionIdx));
break;
}
case FamilyII:
{
const Sof3Table& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>( satnumIdx );
const SgfnTable& sgfnTable = tableManager.getSgfnTables().getTable<SgfnTable>( satnumIdx );
const Sof3Table& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>( satRegionIdx );
const SgfnTable& sgfnTable = tableManager.getSgfnTables().getTable<SgfnTable>( satRegionIdx );
readGasOilEffectiveParametersFamily2_(effParams,
Swco,
sof3Table,
@ -691,7 +751,7 @@ private:
void readOilWaterEffectiveParameters_(Container& dest,
const Opm::Deck& deck,
const Opm::EclipseState& eclState,
unsigned satnumIdx)
unsigned satRegionIdx)
{
bool hasWater = deck.hasKeyword("WATER");
bool hasOil = deck.hasKeyword("OIL");
@ -700,14 +760,14 @@ private:
// we don't read anything if either the water or the oil phase is not active
return;
dest[satnumIdx] = std::make_shared<OilWaterEffectiveTwoPhaseParams>();
dest[satRegionIdx] = std::make_shared<OilWaterEffectiveTwoPhaseParams>();
const auto& tableManager = eclState.getTableManager();
auto& effParams = *dest[satnumIdx];
auto& effParams = *dest[satRegionIdx];
switch (getSaturationFunctionFamily(deck, eclState)) {
case FamilyI: {
const auto& swofTable = tableManager.getSwofTables().getTable<SwofTable>(satnumIdx);
const auto& swofTable = tableManager.getSwofTables().getTable<SwofTable>(satRegionIdx);
std::vector<double> SwColumn = swofTable.getColumn("SW").vectorCopy();
effParams.setKrwSamples(SwColumn, swofTable.getColumn("KRW").vectorCopy());
@ -718,8 +778,8 @@ private:
}
case FamilyII:
{
const auto& swfnTable = tableManager.getSwfnTables().getTable<SwfnTable>(satnumIdx);
const auto& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>(satnumIdx);
const auto& swfnTable = tableManager.getSwfnTables().getTable<SwfnTable>(satRegionIdx);
const auto& sof3Table = tableManager.getSof3Tables().getTable<Sof3Table>(satRegionIdx);
std::vector<double> SwColumn = swfnTable.getColumn("SW").vectorCopy();
// convert the saturations of the SOF3 keyword from oil to water saturations
@ -747,7 +807,7 @@ private:
std::shared_ptr<EclEpsConfig> config,
const Opm::Deck& deck,
const Opm::EclipseState& /* eclState */,
unsigned satnumIdx)
unsigned satRegionIdx)
{
bool hasGas = deck.hasKeyword("GAS");
bool hasOil = deck.hasKeyword("OIL");
@ -756,8 +816,8 @@ private:
// we don't read anything if either the gas or the oil phase is not active
return;
dest[satnumIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
dest[satnumIdx]->init(unscaledEpsInfo_[satnumIdx], *config, EclGasOilSystem);
dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config, EclGasOilSystem);
}
template <class Container>
@ -765,7 +825,7 @@ private:
std::shared_ptr<EclEpsConfig> config,
const Opm::Deck& deck,
const Opm::EclipseState& /* eclState */,
unsigned satnumIdx)
unsigned satRegionIdx)
{
bool hasWater = deck.hasKeyword("WATER");
bool hasOil = deck.hasKeyword("OIL");
@ -774,8 +834,8 @@ private:
// we don't read anything if either the water or the oil phase is not active
return;
dest[satnumIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
dest[satnumIdx]->init(unscaledEpsInfo_[satnumIdx], *config, EclOilWaterSystem);
dest[satRegionIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
dest[satRegionIdx]->init(unscaledEpsInfo_[satRegionIdx], *config, EclOilWaterSystem);
}
template <class InfoContainer, class PointsContainer>
@ -787,9 +847,9 @@ private:
unsigned elemIdx,
unsigned cartElemIdx)
{
unsigned satnumIdx = static_cast<unsigned>((*epsGridProperties.satnum)[cartElemIdx]) - 1; // ECL uses Fortran indices!
unsigned satRegionIdx = static_cast<unsigned>((*epsGridProperties.satnum)[cartElemIdx]) - 1; // ECL uses Fortran indices!
destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satnumIdx]);
destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satRegionIdx]);
destInfo[elemIdx]->extractScaled(eclState, epsGridProperties, cartElemIdx);
destPoints[elemIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
@ -805,9 +865,9 @@ private:
unsigned elemIdx,
unsigned cartElemIdx)
{
unsigned satnumIdx = static_cast<unsigned>((*epsGridProperties.satnum)[cartElemIdx]) - 1; // ECL uses Fortran indices!
unsigned satRegionIdx = static_cast<unsigned>((*epsGridProperties.satnum)[cartElemIdx]) - 1; // ECL uses Fortran indices!
destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satnumIdx]);
destInfo[elemIdx] = std::make_shared<EclEpsScalingPointsInfo<Scalar> >(unscaledEpsInfo_[satRegionIdx]);
destInfo[elemIdx]->extractScaled(eclState, epsGridProperties, cartElemIdx);
destPoints[elemIdx] = std::make_shared<EclEpsScalingPoints<Scalar> >();
@ -817,7 +877,7 @@ private:
void initThreePhaseParams_(const Opm::Deck& deck,
const Opm::EclipseState& /* eclState */,
MaterialLawParams& materialParams,
unsigned satnumIdx,
unsigned satRegionIdx,
const EclEpsScalingPointsInfo<Scalar>& epsInfo,
std::shared_ptr<OilWaterTwoPhaseHystParams> oilWaterParams,
std::shared_ptr<GasOilTwoPhaseHystParams> gasOilParams)
@ -833,7 +893,7 @@ private:
if (deck.hasKeyword("STONE1EX")) {
Scalar eta =
deck.getKeyword("STONE1EX").getRecord(satnumIdx).getItem(0).getSIDouble(0);
deck.getKeyword("STONE1EX").getRecord(satRegionIdx).getItem(0).getSIDouble(0);
realParams.setEta(eta);
}
else
@ -884,6 +944,7 @@ private:
enum EclTwoPhaseApproach twoPhaseApproach_;
std::vector<std::shared_ptr<MaterialLawParams> > materialLawParams_;
std::vector<std::shared_ptr<MaterialLawParams> > satRegionMaterialLawParams_;
};
} // namespace Opm