Beispiel #1
0
    /*!
     * \brief Initialize the oil parameters via the data specified by the PVDO ECL keyword.
     */
    void initFromDeck(const Deck& deck, const EclipseState& eclState)
    {
        const auto& pvdoTables = eclState.getTableManager().getPvdoTables();
        const auto& densityKeyword = deck.getKeyword("DENSITY");

        assert(pvdoTables.size() == densityKeyword.size());

        size_t numRegions = pvdoTables.size();
        setNumRegions(numRegions);

        for (unsigned regionIdx = 0; regionIdx < numRegions; ++ regionIdx) {
            Scalar rhoRefO = densityKeyword.getRecord(regionIdx).getItem("OIL").getSIDouble(0);
            Scalar rhoRefG = densityKeyword.getRecord(regionIdx).getItem("GAS").getSIDouble(0);
            Scalar rhoRefW = densityKeyword.getRecord(regionIdx).getItem("WATER").getSIDouble(0);

            setReferenceDensities(regionIdx, rhoRefO, rhoRefG, rhoRefW);

            const auto& pvdoTable = pvdoTables.getTable<PvdoTable>(regionIdx);

            const auto& BColumn(pvdoTable.getFormationFactorColumn());
            std::vector<Scalar> invBColumn(BColumn.size());
            for (unsigned i = 0; i < invBColumn.size(); ++i)
                invBColumn[i] = 1/BColumn[i];

            inverseOilB_[regionIdx].setXYArrays(pvdoTable.numRows(),
                                                pvdoTable.getPressureColumn(),
                                                invBColumn);
            oilMu_[regionIdx].setXYArrays(pvdoTable.numRows(),
                                          pvdoTable.getPressureColumn(),
                                          pvdoTable.getViscosityColumn());
        }

        initEnd();
    }
Beispiel #2
0
    /*!
     * \brief Initialize the parameters for dry gas using an ECL deck.
     *
     * This method assumes that the deck features valid DENSITY and PVDG keywords.
     */
    void initFromDeck(DeckConstPtr deck, EclipseStateConstPtr eclState)
    {
        const auto& pvdgTables = eclState->getTableManager()->getPvdgTables();
        const auto& densityKeyword = deck->getKeyword("DENSITY");

        assert(pvdgTables.size() == densityKeyword.size());

        size_t numRegions = pvdgTables.size();
        setNumRegions(numRegions);

        for (unsigned regionIdx = 0; regionIdx < numRegions; ++ regionIdx) {
            Scalar rhoRefO = densityKeyword.getRecord(regionIdx).getItem("OIL").getSIDouble(0);
            Scalar rhoRefG = densityKeyword.getRecord(regionIdx).getItem("GAS").getSIDouble(0);
            Scalar rhoRefW = densityKeyword.getRecord(regionIdx).getItem("WATER").getSIDouble(0);

            setReferenceDensities(regionIdx, rhoRefO, rhoRefG, rhoRefW);

            // determine the molar masses of the components
            Scalar p = 1.01325e5; // surface pressure, [Pa]
            Scalar T = 273.15 + 15.56; // surface temperature, [K]
            Scalar MO = 175e-3; // [kg/mol]
            Scalar MG = Opm::Constants<Scalar>::R*T*rhoRefG / p; // [kg/mol], consequence of the ideal gas law
            Scalar MW = 18.0e-3; // [kg/mol]
            // TODO (?): the molar mass of the components can possibly specified
            // explicitly in the deck.
            setMolarMasses(regionIdx, MO, MG, MW);

            const auto& pvdgTable = pvdgTables.getTable<PvdgTable>(regionIdx);

            // say 99.97% of all time: "premature optimization is the root of all
            // evil". Eclipse does this "optimization" for apparently no good reason!
            std::vector<Scalar> invB(pvdgTable.numRows());
            const auto& Bg = pvdgTable.getFormationFactorColumn();
            for (unsigned i = 0; i < Bg.size(); ++ i) {
                invB[i] = 1.0/Bg[i];
            }

            size_t numSamples = invB.size();
            inverseGasB_[regionIdx].setXYArrays(numSamples, pvdgTable.getPressureColumn(), invB);
            gasMu_[regionIdx].setXYArrays(numSamples, pvdgTable.getPressureColumn(), pvdgTable.getViscosityColumn());
        }

        initEnd();
    }
Beispiel #3
0
    /*!
     * \brief Initialize the oil parameters via the data specified by the PVTO ECL keyword.
     */
    void initFromDeck(const Deck& deck, const EclipseState& eclState)
    {
        const auto& pvtoTables = eclState.getTableManager().getPvtoTables();
        const auto& densityKeyword = deck.getKeyword("DENSITY");

        assert(pvtoTables.size() == densityKeyword.size());

        size_t numRegions = pvtoTables.size();
        setNumRegions(numRegions);

        for (unsigned regionIdx = 0; regionIdx < numRegions; ++ regionIdx) {
            Scalar rhoRefO = densityKeyword.getRecord(regionIdx).getItem("OIL").getSIDouble(0);
            Scalar rhoRefG = densityKeyword.getRecord(regionIdx).getItem("GAS").getSIDouble(0);
            Scalar rhoRefW = densityKeyword.getRecord(regionIdx).getItem("WATER").getSIDouble(0);

            setReferenceDensities(regionIdx, rhoRefO, rhoRefG, rhoRefW);
        }

        // initialize the internal table objects
        for (unsigned regionIdx = 0; regionIdx < numRegions; ++ regionIdx) {
            const auto& pvtoTable = pvtoTables[regionIdx];

            const auto& saturatedTable = pvtoTable.getSaturatedTable();
            assert(saturatedTable.numRows() > 1);

            auto& oilMu = oilMuTable_[regionIdx];
            auto& satOilMu = saturatedOilMuTable_[regionIdx];
            auto& invOilB = inverseOilBTable_[regionIdx];
            auto& invSatOilB = inverseSaturatedOilBTable_[regionIdx];
            auto& gasDissolutionFac = saturatedGasDissolutionFactorTable_[regionIdx];
            std::vector<Scalar> invSatOilBArray;
            std::vector<Scalar> satOilMuArray;

            // extract the table for the gas dissolution and the oil formation volume factors
            for (unsigned outerIdx = 0; outerIdx < saturatedTable.numRows(); ++ outerIdx) {
                Scalar Rs    = saturatedTable.get("RS", outerIdx);
                Scalar BoSat = saturatedTable.get("BO", outerIdx);
                Scalar muoSat = saturatedTable.get("MU", outerIdx);

                satOilMuArray.push_back(muoSat);
                invSatOilBArray.push_back(1.0/BoSat);

                invOilB.appendXPos(Rs);
                oilMu.appendXPos(Rs);

                assert(invOilB.numX() == outerIdx + 1);
                assert(oilMu.numX() == outerIdx + 1);

                const auto& underSaturatedTable = pvtoTable.getUnderSaturatedTable(outerIdx);
                size_t numRows = underSaturatedTable.numRows();
                for (unsigned innerIdx = 0; innerIdx < numRows; ++ innerIdx) {
                    Scalar po = underSaturatedTable.get("P", innerIdx);
                    Scalar Bo = underSaturatedTable.get("BO", innerIdx);
                    Scalar muo = underSaturatedTable.get("MU", innerIdx);

                    invOilB.appendSamplePoint(outerIdx, po, 1.0/Bo);
                    oilMu.appendSamplePoint(outerIdx, po, muo);
                }
            }

            // update the tables for the formation volume factor and for the gas
            // dissolution factor of saturated oil
            {
                const auto& tmpPressureColumn = saturatedTable.getColumn("P");
                const auto& tmpGasSolubilityColumn = saturatedTable.getColumn("RS");

                invSatOilB.setXYContainers(tmpPressureColumn, invSatOilBArray);
                satOilMu.setXYContainers(tmpPressureColumn, satOilMuArray);
                gasDissolutionFac.setXYContainers(tmpPressureColumn, tmpGasSolubilityColumn);
            }

            updateSaturationPressure_(regionIdx);
            // make sure to have at least two sample points per Rs value
            for (unsigned xIdx = 0; xIdx < invOilB.numX(); ++xIdx) {
                // a single sample point is definitely needed
                assert(invOilB.numY(xIdx) > 0);

                // everything is fine if the current table has two or more sampling points
                // for a given mole fraction
                if (invOilB.numY(xIdx) > 1)
                    continue;

                // find the master table which will be used as a template to extend the
                // current line. We define master table as the first table which has values
                // for undersaturated oil...
                size_t masterTableIdx = xIdx + 1;
                for (; masterTableIdx < saturatedTable.numRows(); ++masterTableIdx)
                {
                    if (pvtoTable.getUnderSaturatedTable(masterTableIdx).numRows() > 1)
                        break;
                }

                if (masterTableIdx >= saturatedTable.numRows())
                    throw std::runtime_error("PVTO tables are invalid: The last table must exhibit at least one "
                                             "entry for undersaturated oil!");

                // extend the current table using the master table.
                extendPvtoTable_(regionIdx,
                                 xIdx,
                                 pvtoTable.getUnderSaturatedTable(xIdx),
                                 pvtoTable.getUnderSaturatedTable(masterTableIdx));
            }
        }

        vapPar2_ = 0.0;
        if (deck.hasKeyword("VAPPARS")) {
            const auto& vapParsKeyword = deck.getKeyword("VAPPARS");
            vapPar2_ = vapParsKeyword.getRecord(0).getItem("OIL_DENSITY_PROPENSITY").template get<double>(0);
        }

        initEnd();
    }