From a041e3ccffb62b181878ea70b221b63a264c65ca Mon Sep 17 00:00:00 2001 From: Tor Harald Sandve Date: Tue, 11 Aug 2015 07:41:27 +0200 Subject: [PATCH] Add support for saturation family 2 keywords Saturation functions can no be given using the family 2 keywords SWFN, SGFN and SOF3. --- .../EclEpsScalingPoints.hpp | 195 ++++++++++++------ .../EclMaterialLawManager.hpp | 84 ++++++-- .../PiecewiseLinearTwoPhaseMaterial.hpp | 13 +- .../PiecewiseLinearTwoPhaseMaterialParams.hpp | 68 ++++-- 4 files changed, 260 insertions(+), 100 deletions(-) diff --git a/opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp b/opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp index c9ea50438..b79f9f756 100644 --- a/opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp +++ b/opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp @@ -2,6 +2,7 @@ // vi: set et ts=4 sw=4 sts=4: /* Copyright (C) 2015 by Andreas Lauser + Copyright (C) 2015 by IRIS AS This file is part of the Open Porous Media project (OPM). @@ -181,68 +182,146 @@ struct EclEpsScalingPointsInfo Opm::EclipseStateConstPtr eclState, int satRegionIdx) { - // TODO: support for the SOF2/SOF3 keyword family - const auto& swofTable = eclState->getSwofTables()[satRegionIdx]; - const auto& sgofTable = eclState->getSgofTables()[satRegionIdx]; + // TODO: support for SOF2, SLGOF, SGWFN and 2d tables - // connate saturations - Swl = swofTable.getSwColumn().front(); - Sowl = 1.0 - swofTable.getSwColumn().back(); - Sgl = sgofTable.getSgColumn().front(); - Sogl = 1.0 - sgofTable.getSgColumn().back(); + size_t saturationFunctionFamily = eclState->getSaturationFunctionFamily(); + switch (saturationFunctionFamily) { + case 1: + { + const auto& swofTable = eclState->getSwofTables()[satRegionIdx]; + const auto& sgofTable = eclState->getSgofTables()[satRegionIdx]; - // critical water saturation - for (unsigned rowIdx = 0; rowIdx < swofTable.numRows(); ++ rowIdx) { - if (swofTable.getKrwColumn()[rowIdx] > 0) { - assert(rowIdx > 0); - Swcr = swofTable.getSwColumn()[rowIdx - 1]; - break; - }; + // connate saturations + Swl = swofTable.getSwColumn().front(); + Sowl = 1.0 - swofTable.getSwColumn().back(); + Sgl = sgofTable.getSgColumn().front(); + Sogl = 1.0 - sgofTable.getSgColumn().back(); + + // critical water saturation + for (unsigned rowIdx = 0; rowIdx < swofTable.numRows(); ++ rowIdx) { + if (swofTable.getKrwColumn()[rowIdx] > 0) { + assert(rowIdx > 0); + Swcr = swofTable.getSwColumn()[rowIdx - 1]; + break; + }; + } + + // critical oil saturation of oil-water system + for (int rowIdx = swofTable.numRows() - 1; rowIdx >= 0; -- rowIdx) { + if (swofTable.getKrowColumn()[rowIdx] > 0) { + assert(rowIdx < (int) swofTable.numRows() - 1); + Sowcr = 1.0 - swofTable.getSwColumn()[rowIdx + 1]; + break; + }; + } + + // critical gas saturation + for (unsigned rowIdx = 0; rowIdx < sgofTable.numRows(); ++ rowIdx) { + if (sgofTable.getKrgColumn()[rowIdx] > 0) { + assert(rowIdx > 0); + Sgcr = sgofTable.getSgColumn()[rowIdx - 1]; + break; + }; + } + + // critical oil saturation of gas-oil system + for (int rowIdx = sgofTable.numRows() - 1; rowIdx >= 0; -- rowIdx) { + if (sgofTable.getKrogColumn()[rowIdx] > 0) { + assert(rowIdx < (int) sgofTable.numRows() - 1); + Sogcr = 1.0 - sgofTable.getSgColumn()[rowIdx + 1]; + break; + }; + } + + // maximum saturations + Swu = swofTable.getSwColumn().back(); + Sowu = 1.0 - swofTable.getSwColumn().front(); + Sgu = sgofTable.getSgColumn().back(); + Sogu = 1.0 - sgofTable.getSgColumn().front(); + + // maximum capillary pressures + maxPcow = swofTable.getPcowColumn().front(); + maxPcgo = sgofTable.getPcogColumn().back(); + + // maximum relative permeabilities + maxKrw = swofTable.getKrwColumn().back(); + maxKrow = swofTable.getKrowColumn().front(); + + maxKrg = sgofTable.getKrgColumn().back(); + maxKrog = sgofTable.getKrogColumn().front(); + break; + } + case 2: + { + const auto& swfnTable = eclState->getSwfnTables()[satRegionIdx]; + const auto& sof3Table = eclState->getSof3Tables()[satRegionIdx]; + const auto& sgfnTable = eclState->getSgfnTables()[satRegionIdx]; + + // connate saturations + Swl = swfnTable.getSwColumn().front(); + Sowl = sof3Table.getSoColumn().front() + Sgl; + Sgl = sgfnTable.getSgColumn().front(); + Sogl = sof3Table.getSoColumn().front() + Swl; + + // critical water saturation + for (unsigned rowIdx = 0; rowIdx < swfnTable.numRows(); ++ rowIdx) { + if (swfnTable.getKrwColumn()[rowIdx] > 0) { + assert(rowIdx > 0); + Swcr = swfnTable.getSwColumn()[rowIdx - 1]; + break; + }; + } + + // critical oil saturation of oil-water system + for (int rowIdx = 0 ; rowIdx < sof3Table.numRows(); ++ rowIdx) { + if (sof3Table.getKrowColumn()[rowIdx] > 0) { + assert(rowIdx > 0); + Sowcr = sof3Table.getSoColumn()[rowIdx - 1]; + break; + }; + } + + // critical oil saturation of gas-oil system + for (int rowIdx = 0 ; rowIdx < sof3Table.numRows(); ++ rowIdx) { + if (sof3Table.getKrogColumn()[rowIdx] > 0) { + assert(rowIdx > 0); + Sogcr = sof3Table.getSoColumn()[rowIdx - 1]; + break; + }; + } + + // critical gas saturation + for (unsigned rowIdx = 0; rowIdx < sgfnTable.numRows(); ++ rowIdx) { + if (sgfnTable.getKrgColumn()[rowIdx] > 0) { + assert(rowIdx > 0); + Sgcr = sgfnTable.getSgColumn()[rowIdx - 1]; + break; + }; + } + // maximum saturations + Swu = swfnTable.getSwColumn().back(); + Sowu = sof3Table.getSoColumn().back(); + assert(Sowu == 1 - swfnTableSwColumn.front()); + Sgu = sgfnTable.getSgColumn().back(); + Sogu = 1 - sgfnTable.getSgColumn().front(); + + // maximum capillary pressures + maxPcow = swfnTable.getPcowColumn().front(); + maxPcgo = sgfnTable.getPcogColumn().back(); + + // maximum relative permeabilities + maxKrw = swfnTable.getKrwColumn().back(); + maxKrow = sof3Table.getKrowColumn().back(); + + maxKrg = sgfnTable.getKrgColumn().back(); + maxKrog = sof3Table.getKrogColumn().back(); + + assert(maxKrw == maxKrg); + + break; + } } - // critical oil saturation of oil-water system - for (int rowIdx = swofTable.numRows() - 1; rowIdx >= 0; -- rowIdx) { - if (swofTable.getKrowColumn()[rowIdx] > 0) { - assert(rowIdx < (int) swofTable.numRows() - 1); - Sowcr = 1.0 - swofTable.getSwColumn()[rowIdx + 1]; - break; - }; - } - - // critical gas saturation - for (unsigned rowIdx = 0; rowIdx < sgofTable.numRows(); ++ rowIdx) { - if (sgofTable.getKrgColumn()[rowIdx] > 0) { - assert(rowIdx > 0); - Sgcr = sgofTable.getSgColumn()[rowIdx - 1]; - break; - }; - } - - // critical oil saturation of gas-oil system - for (int rowIdx = sgofTable.numRows() - 1; rowIdx >= 0; -- rowIdx) { - if (sgofTable.getKrogColumn()[rowIdx] > 0) { - assert(rowIdx < (int) sgofTable.numRows() - 1); - Sogcr = 1.0 - sgofTable.getSgColumn()[rowIdx + 1]; - break; - }; - } - - // maximum saturations - Swu = swofTable.getSwColumn().back(); - Sowu = 1.0 - swofTable.getSwColumn().front(); - Sgu = sgofTable.getSgColumn().back(); - Sogu = 1.0 - sgofTable.getSgColumn().front(); - - // maximum capillary pressures - maxPcow = swofTable.getPcowColumn().front(); - maxPcgo = sgofTable.getPcogColumn().back(); - - // maximum relative permeabilities - maxKrw = swofTable.getKrwColumn().back(); - maxKrow = swofTable.getKrowColumn().front(); - - maxKrg = sgofTable.getKrgColumn().back(); - maxKrog = sgofTable.getKrogColumn().front(); } #endif diff --git a/opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp b/opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp index 1ec7b9d61..1c67c2290 100644 --- a/opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp +++ b/opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp @@ -2,6 +2,7 @@ // vi: set et ts=4 sw=4 sts=4: /* Copyright (C) 2015 by Andreas Lauser + Copyright (C) 2015 by IRIS AS This file is part of the Open Porous Media project (OPM). @@ -535,18 +536,47 @@ private: dest[satnumRegionIdx] = std::make_shared(); auto& effParams = *dest[satnumRegionIdx]; - const auto& sgofTable = eclState->getSgofTables()[satnumRegionIdx]; + size_t saturationFunctionFamily = eclState->getSaturationFunctionFamily(); - // convert the saturations of the SGOF keyword from gas to oil saturations - std::vector SoSamples(sgofTable.numRows()); - for (size_t sampleIdx = 0; sampleIdx < sgofTable.numRows(); ++ sampleIdx) - SoSamples[sampleIdx] = 1 - sgofTable.getSgColumn()[sampleIdx]; + switch (saturationFunctionFamily) { + case 1: + { + const auto& sgofTable = eclState->getSgofTables()[satnumRegionIdx]; + // convert the saturations of the SGOF keyword from gas to oil saturations + std::vector SoSamples(sgofTable.numRows()); + for (size_t sampleIdx = 0; sampleIdx < sgofTable.numRows(); ++ sampleIdx) + SoSamples[sampleIdx] = 1 - sgofTable.getSgColumn()[sampleIdx]; - effParams.setKrwSamples(SoSamples, sgofTable.getKrogColumn()); - effParams.setKrnSamples(SoSamples, sgofTable.getKrgColumn()); - effParams.setPcnwSamples(SoSamples, sgofTable.getPcogColumn()); - effParams.finalize(); + effParams.setKrwSamples(SoSamples, sgofTable.getKrogColumn()); + effParams.setKrnSamples(SoSamples, sgofTable.getKrgColumn()); + effParams.setPcnwSamples(SoSamples, sgofTable.getPcogColumn()); + effParams.finalize(); + break; + } + case 2: + { + const auto& sgfnTable = eclState->getSgfnTables()[satnumRegionIdx]; + const auto& sof3Table = eclState->getSof3Tables()[satnumRegionIdx]; + + const auto &SoColumn = sof3Table.getSoColumn(); + // convert the saturations of the SGFN keyword from gas to oil saturations + std::vector SoSamples(sgfnTable.numRows()); + for (size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx) + SoSamples[sampleIdx] = 1 - sgfnTable.getSgColumn()[sampleIdx]; + + for (size_t sampleIdx = 0; sampleIdx < sgfnTable.numRows(); ++ sampleIdx){ + std::cout << SoColumn[sampleIdx] << " " << SoSamples[sampleIdx] << std::endl; + + } + + effParams.setKrwSamples(SoColumn, sof3Table.getKrogColumn()); + effParams.setKrnSamples(SoSamples, sgfnTable.getKrgColumn()); + effParams.setPcnwSamples(SoSamples, sgfnTable.getPcogColumn()); + effParams.finalize(); + break; + } + } } template @@ -557,16 +587,40 @@ private: dest[satnumRegionIdx] = std::make_shared(); auto& effParams = *dest[satnumRegionIdx]; - const auto& swofTable = eclState->getSwofTables()[satnumRegionIdx]; + size_t saturationFunctionFamily = eclState->getSaturationFunctionFamily(); - const auto &SwColumn = swofTable.getSwColumn(); + switch (saturationFunctionFamily) { + case 1: { + const auto& swofTable = eclState->getSwofTables()[satnumRegionIdx]; + const auto &SwColumn = swofTable.getSwColumn(); - effParams.setKrwSamples(SwColumn, swofTable.getKrwColumn()); - effParams.setKrnSamples(SwColumn, swofTable.getKrowColumn()); - effParams.setPcnwSamples(SwColumn, swofTable.getPcowColumn()); - effParams.finalize(); + effParams.setKrwSamples(SwColumn, swofTable.getKrwColumn()); + effParams.setKrnSamples(SwColumn, swofTable.getKrowColumn()); + effParams.setPcnwSamples(SwColumn, swofTable.getPcowColumn()); + effParams.finalize(); + break; + } + case 2: + { + const auto& swfnTable = eclState->getSwfnTables()[satnumRegionIdx]; + const auto& sof3Table = eclState->getSof3Tables()[satnumRegionIdx]; + const auto &SwColumn = swfnTable.getSwColumn(); + + // convert the saturations of the SOF3 keyword from oil to water saturations + std::vector SwSamples(sof3Table.numRows()); + for (size_t sampleIdx = 0; sampleIdx < sof3Table.numRows(); ++ sampleIdx) + SwSamples[sampleIdx] = 1 - sof3Table.getSoColumn()[sampleIdx]; + + effParams.setKrwSamples(SwColumn, swfnTable.getKrwColumn()); + effParams.setKrnSamples(SwSamples, sof3Table.getKrowColumn()); + effParams.setPcnwSamples(SwColumn, swfnTable.getPcowColumn()); + effParams.finalize(); + break; + } + } } + template void readGasOilUnscaledPoints_(Container &dest, std::shared_ptr config, diff --git a/opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterial.hpp b/opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterial.hpp index cc1b9ebae..5b0b1dcff 100644 --- a/opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterial.hpp +++ b/opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterial.hpp @@ -2,6 +2,7 @@ // vi: set et ts=4 sw=4 sts=4: /* Copyright (C) 2009-2013 by Andreas Lauser + Copyright (C) 2015 by IRIS AS This file is part of the Open Porous Media project (OPM). @@ -141,13 +142,13 @@ public: */ template static Evaluation twoPhaseSatPcnw(const Params ¶ms, const Evaluation& Sw) - { return eval_(params.SwSamples(), params.pcnwSamples(), Sw); } + { return eval_(params.SwPcwnSamples(), params.pcnwSamples(), Sw); } template static Evaluation twoPhaseSatPcnwInv(const Params ¶ms, const Evaluation& pcnw) { return eval_(params.pcnwSamples(), - params.SwSamples(), + params.SwPcwnSamples(), pcnw); } @@ -193,7 +194,7 @@ public: { typedef MathToolbox Toolbox; - const auto& res = eval_(params.SwSamples(), params.krwSamples(), Sw); + const auto& res = eval_(params.SwKrwSamples(), params.krwSamples(), Sw); return Toolbox::max(0.0, Toolbox::min(1.0, res)); } @@ -201,7 +202,7 @@ public: static Evaluation twoPhaseSatKrwInv(const Params ¶ms, const Evaluation& krw) { return eval_(params.krwSamples(), - params.SwSamples(), + params.SwKrwSamples(), krw); } @@ -224,7 +225,7 @@ public: { typedef MathToolbox Toolbox; - return Toolbox::max(0.0, Toolbox::min(1.0, eval_(params.SwSamples(), + return Toolbox::max(0.0, Toolbox::min(1.0, eval_(params.SwKrnSamples(), params.krnSamples(), Sw))); } @@ -233,7 +234,7 @@ public: static Evaluation twoPhaseSatKrnInv(const Params ¶ms, const Evaluation& krn) { return eval_(params.krnSamples(), - params.SwSamples(), + params.SwKrnSamples(), krn); } diff --git a/opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterialParams.hpp b/opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterialParams.hpp index 1b844612d..f8a8802b0 100644 --- a/opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterialParams.hpp +++ b/opm/material/fluidmatrixinteractions/PiecewiseLinearTwoPhaseMaterialParams.hpp @@ -65,26 +65,35 @@ public: // revert the order of the sampling points if they were given // in reverse direction. - if (SwSamples_.front() > SwSamples_.back()) { - for (unsigned origSampleIdx = 0; - origSampleIdx < SwSamples_.size() / 2; - ++ origSampleIdx) - { - unsigned newSampleIdx = SwSamples_.size() - origSampleIdx - 1; + if (SwPcwnSamples_.front() > SwPcwnSamples_.back()) + swapOrder_(SwPcwnSamples_, pcwnSamples_); + + if (SwKrwSamples_.front() > SwKrwSamples_.back()) + swapOrder_(SwKrwSamples_, krwSamples_); + + + if (SwKrnSamples_.front() > SwKrnSamples_.back()) + swapOrder_(SwKrnSamples_, krnSamples_); - std::swap(SwSamples_[origSampleIdx], SwSamples_[newSampleIdx]); - std::swap(pcwnSamples_[origSampleIdx], pcwnSamples_[newSampleIdx]); - std::swap(krwSamples_[origSampleIdx], krwSamples_[newSampleIdx]); - std::swap(krnSamples_[origSampleIdx], krnSamples_[newSampleIdx]); - } - } } /*! * \brief Return the wetting-phase saturation values of all sampling points. */ - const ValueVector& SwSamples() const - { assertFinalized_(); return SwSamples_; } + const ValueVector& SwKrwSamples() const + { assertFinalized_(); return SwKrwSamples_; } + + /*! + * \brief Return the wetting-phase saturation values of all sampling points. + */ + const ValueVector& SwKrnSamples() const + { assertFinalized_(); return SwKrnSamples_; } + + /*! + * \brief Return the wetting-phase saturation values of all sampling points. + */ + const ValueVector& SwPcwnSamples() const + { assertFinalized_(); return SwPcwnSamples_; } /*! * \brief Return the sampling points for the capillary pressure curve. @@ -105,10 +114,10 @@ public: assert(SwValues.size() == values.size()); int n = SwValues.size(); - SwSamples_.resize(n); + SwPcwnSamples_.resize(n); pcwnSamples_.resize(n); - std::copy(SwValues.begin(), SwValues.end(), SwSamples_.begin()); + std::copy(SwValues.begin(), SwValues.end(), SwPcwnSamples_.begin()); std::copy(values.begin(), values.end(), pcwnSamples_.begin()); } @@ -133,10 +142,10 @@ public: assert(SwValues.size() == values.size()); int n = SwValues.size(); - SwSamples_.resize(n); + SwKrwSamples_.resize(n); krwSamples_.resize(n); - std::copy(SwValues.begin(), SwValues.end(), SwSamples_.begin()); + std::copy(SwValues.begin(), SwValues.end(), SwKrwSamples_.begin()); std::copy(values.begin(), values.end(), krwSamples_.begin()); } @@ -161,10 +170,10 @@ public: assert(SwValues.size() == values.size()); int n = SwValues.size(); - SwSamples_.resize(n); + SwKrnSamples_.resize(n); krnSamples_.resize(n); - std::copy(SwValues.begin(), SwValues.end(), SwSamples_.begin()); + std::copy(SwValues.begin(), SwValues.end(), SwKrnSamples_.begin()); std::copy(values.begin(), values.end(), krnSamples_.begin()); } @@ -179,7 +188,24 @@ private: { } #endif - ValueVector SwSamples_; + void swapOrder_(ValueVector& swValues, ValueVector& values) const + { + if (swValues.front() > values.back()) { + for (unsigned origSampleIdx = 0; + origSampleIdx < swValues.size() / 2; + ++ origSampleIdx) + { + unsigned newSampleIdx = swValues.size() - origSampleIdx - 1; + + std::swap(swValues[origSampleIdx], swValues[newSampleIdx]); + std::swap(values[origSampleIdx], values[newSampleIdx]); + } + } + } + + ValueVector SwPcwnSamples_; + ValueVector SwKrwSamples_; + ValueVector SwKrnSamples_; ValueVector pcwnSamples_; ValueVector krwSamples_; ValueVector krnSamples_;