Example #1
0
    static void dRelativePermeabilities_dSaturation(ContainerT &values,
                                                    const Params &params,
                                                    const FluidState &state,
                                                    int satPhaseIdx)
    {
        for (int krPhaseIdx = 0; krPhaseIdx < numPhases; ++krPhaseIdx)
            values[krPhaseIdx] = 0.0;

        // -> linear relation between 0 and 1, else constant
        if (state.saturation(satPhaseIdx) >= 0 &&
            state.saturation(satPhaseIdx) <= 1)
        {
            values[satPhaseIdx] = 1.0;
        }
    }
Example #2
0
void guessInitial(FluidState& fluidState, unsigned phaseIdx)
{
    if (phaseIdx == FluidSystem::gasPhaseIdx) {
        fluidState.setMoleFraction(phaseIdx, FluidSystem::H2OIdx, 0.0);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C1Idx, 0.74785);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C3Idx, 0.0121364);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C6Idx, 0.00606028);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C10Idx, 0.00268136);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C15Idx, 0.000204256);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C20Idx, 8.78291e-06);
    }
    else if (phaseIdx == FluidSystem::oilPhaseIdx) {
        fluidState.setMoleFraction(phaseIdx, FluidSystem::H2OIdx, 0.0);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C1Idx, 0.50);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C3Idx, 0.03);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C6Idx, 0.07);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C10Idx, 0.20);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C15Idx, 0.15);
        fluidState.setMoleFraction(phaseIdx, FluidSystem::C20Idx, 0.05);
    }
    else {
        assert(phaseIdx == FluidSystem::waterPhaseIdx);
    }
}
    static void solveIdealMix_(FluidState &fluidState,
                               ParameterCache &paramCache,
                               unsigned phaseIdx,
                               const ComponentVector &fugacities)
    {
        for (unsigned i = 0; i < numComponents; ++ i) {
            const Evaluation& phi = FluidSystem::fugacityCoefficient(fluidState,
                                                                     paramCache,
                                                                     phaseIdx,
                                                                     i);
            const Evaluation& gamma = phi * fluidState.pressure(phaseIdx);
            Valgrind::CheckDefined(phi);
            Valgrind::CheckDefined(gamma);
            Valgrind::CheckDefined(fugacities[i]);
            fluidState.setFugacityCoefficient(phaseIdx, i, phi);
            fluidState.setMoleFraction(phaseIdx, i, fugacities[i]/gamma);
        };

        paramCache.updatePhase(fluidState, phaseIdx);

        const Evaluation& rho = FluidSystem::density(fluidState, paramCache, phaseIdx);
        fluidState.setDensity(phaseIdx, rho);
        return;
    }
Example #4
0
    static void relativePermeabilities(ContainerT &values,
                                       const Params &params,
                                       const FluidState &fluidState)
    {
        typedef typename std::remove_reference<decltype(values[0])>::type Evaluation;
        typedef MathToolbox<typename FluidState::Scalar> FsToolbox;

        switch (params.approach()) {
        case EclTwoPhaseGasOil: {
            const Evaluation& So =
                FsToolbox::template decay<Evaluation>(fluidState.saturation(oilPhaseIdx));

            values[oilPhaseIdx] = GasOilMaterialLaw::twoPhaseSatKrw(params.gasOilParams(), So);
            values[gasPhaseIdx] = GasOilMaterialLaw::twoPhaseSatKrn(params.gasOilParams(), So);
            break;
        }

        case EclTwoPhaseOilWater: {
            const Evaluation& Sw =
                FsToolbox::template decay<Evaluation>(fluidState.saturation(waterPhaseIdx));

            values[waterPhaseIdx] = OilWaterMaterialLaw::twoPhaseSatKrw(params.oilWaterParams(), Sw);
            values[oilPhaseIdx] = OilWaterMaterialLaw::twoPhaseSatKrn(params.oilWaterParams(), Sw);
            break;
        }

        case EclTwoPhaseGasWater: {
            const Evaluation& Sw =
                FsToolbox::template decay<Evaluation>(fluidState.saturation(waterPhaseIdx));

            values[waterPhaseIdx] = OilWaterMaterialLaw::twoPhaseSatKrw(params.oilWaterParams(), Sw);
            values[gasPhaseIdx] = GasOilMaterialLaw::twoPhaseSatKrn(params.gasOilParams(), Sw);
            break;
        }
        }
    }
    static void guessInitial(FluidState &fluidState,
                             ParameterCache &paramCache,
                             int phaseIdx,
                             const ComponentVector &fugVec)
    {
        if (FluidSystem::isIdealMixture(phaseIdx))
            return;

        // Pure component fugacities
        for (int i = 0; i < numComponents; ++ i) {
            //std::cout << f << " -> " << mutParams.fugacity(phaseIdx, i)/f << "\n";
            fluidState.setMoleFraction(phaseIdx,
                                       i,
                                       1.0/numComponents);
        }
    }
Example #6
0
    void assign(const FluidState& fs)
    {
        typedef typename FluidState::Scalar FsScalar;
        typedef Opm::MathToolbox<FsScalar> FsToolbox;

        for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
            averageMolarMass_[phaseIdx] = 0;
            sumMoleFractions_[phaseIdx] = 0;
            for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
                moleFraction_[phaseIdx][compIdx] =
                    FsToolbox::template decay<Scalar>(fs.moleFraction(phaseIdx, compIdx));

                averageMolarMass_[phaseIdx] += moleFraction_[phaseIdx][compIdx]*FluidSystem::molarMass(compIdx);
                sumMoleFractions_[phaseIdx] += moleFraction_[phaseIdx][compIdx];
            }
        }
    }
    static Evaluation krw(const Params &params, const FluidState &fluidState)
    {
        typedef MathToolbox<typename FluidState::Scalar> FsToolbox;
        typedef MathToolbox<Evaluation> Toolbox;

        const Evaluation& Sw =
            FsToolbox::template toLhs<Evaluation>(fluidState.saturation(wettingPhaseIdx));
        // transformation to effective saturation
        const Evaluation& Se = (Sw - params.Swr()) / (1-params.Swr());

        // regularization
        if(Se > 1.0) return 1.;
        if(Se < 0.0) return 0.;

        const Evaluation& r = 1. - Toolbox::pow(1 - Toolbox::pow(Se, 1/params.vgM()), params.vgM());
        return Toolbox::sqrt(Se)*r*r;
    }
Example #8
0
    static Evaluation krn(const Params &params, const FluidState &fs)
    {
        typedef Opm::SaturationOverlayFluidState<FluidState> OverlayFluidState;

        static_assert(FluidState::numPhases == numPhases,
                      "The fluid state and the material law must exhibit the same "
                      "number of phases!");

        OverlayFluidState overlayFs(fs);
        for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
            overlayFs.setSaturation(phaseIdx,
                                    effectiveSaturation(params,
                                                        fs.saturation(phaseIdx),
                                                        phaseIdx));
        }

        return EffLaw::template krn<OverlayFluidState, Evaluation>(params, overlayFs);
    }
Example #9
0
    static typename std::enable_if< (Traits::numPhases > 2), Evaluation>::type
    krg(const Params& params, const FluidState& fs)
    {
        typedef Opm::SaturationOverlayFluidState<FluidState> OverlayFluidState;

        static_assert(FluidState::numPhases == numPhases,
                      "The fluid state and the material law must exhibit the same "
                      "number of phases!");

        OverlayFluidState overlayFs(fs);
        for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
            overlayFs.setSaturation(phaseIdx,
                                    effectiveSaturation(params,
                                                        fs.saturation(phaseIdx),
                                                        phaseIdx));
        }

        return EffLaw::template krg<OverlayFluidState, Evaluation>(params, overlayFs);
    }
    static Evaluation pcnw(const Params &params, const FluidState &fluidState)
    {
        typedef MathToolbox<typename FluidState::Scalar> FsToolbox;
        typedef MathToolbox<Evaluation> Toolbox;

        const Evaluation& Sw =
            FsToolbox::template toLhs<Evaluation>(fluidState.saturation(wettingPhaseIdx));
        Evaluation Se = (Sw-params.Swr())/(1.-params.Snr());

        Scalar PC_VG_REG = 0.01;

        // regularization
        if (Se<0.0)
            Se=0.0;
        if (Se>1.0)
            Se=1.0;

        if (Se>PC_VG_REG && Se<1-PC_VG_REG) {
            Evaluation x = Toolbox::pow(Se,-1/params.vgM()) - 1.0;
            x = Toolbox::pow(x, 1 - params.vgM());
            return x/params.vgAlpha();
        }

        // value and derivative at regularization point
        Scalar Se_regu;
        if (Se<=PC_VG_REG)
            Se_regu = PC_VG_REG;
        else
            Se_regu = 1.0 - PC_VG_REG;

        const Evaluation& x = std::pow(Se_regu,-1/params.vgM())-1;
        const Evaluation& pc = Toolbox::pow(x, 1/params.vgN())/params.vgAlpha();
        const Evaluation& pc_prime =
            Toolbox::pow(x,1/params.vgN()-1)
            * std::pow(Se_regu, -1.0/params.vgM() - 1)
            / (-params.vgM())
            / params.vgAlpha()
            / (1-params.Snr()-params.Swr())
            / params.vgN();

        // evaluate tangential
        return ((Se-Se_regu)*pc_prime + pc)/params.betaNW();
    }
    static Scalar density(const FluidState &fluidState,
                          const ParameterCache &paramCache,
                          int phaseIdx)
    {
        assert(0 <= phaseIdx && phaseIdx < numPhases);

        Scalar temperature = fluidState.temperature(phaseIdx);
        Scalar pressure = fluidState.pressure(phaseIdx);

        if (phaseIdx == lPhaseIdx) {
            // use normalized composition for to calculate the density
            // (the relations don't seem to take non-normalized
            // compositions too well...)
            Scalar xlBrine = std::min(1.0, std::max(0.0, fluidState.moleFraction(lPhaseIdx, BrineIdx)));
            Scalar xlCO2 = std::min(1.0, std::max(0.0, fluidState.moleFraction(lPhaseIdx, CO2Idx)));
            Scalar sumx = xlBrine + xlCO2;
            xlBrine /= sumx;
            xlCO2 /= sumx;

            Scalar result = liquidDensity_(temperature,
                                           pressure,
                                           xlBrine,
                                           xlCO2);

            Valgrind::CheckDefined(result);
            return result;
        }

        assert(phaseIdx == gPhaseIdx);

        // use normalized composition for to calculate the density
        // (the relations don't seem to take non-normalized
        // compositions too well...)
        Scalar xgBrine = std::min(1.0, std::max(0.0, fluidState.moleFraction(gPhaseIdx, BrineIdx)));
        Scalar xgCO2 = std::min(1.0, std::max(0.0, fluidState.moleFraction(gPhaseIdx, CO2Idx)));
        Scalar sumx = xgBrine + xgCO2;
        xgBrine /= sumx;
        xgCO2 /= sumx;

        Scalar result = gasDensity_(temperature,
                                    pressure,
                                    xgBrine,
                                    xgCO2);
        Valgrind::CheckDefined(result);
        return result;
    }
Example #12
0
    static Scalar heatConductivity(const Params &params,
                                   const FluidState &fluidState)
    {
        Valgrind::CheckDefined(params.vacuumLambda());

        Scalar lambda = 0;
        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
            Valgrind::CheckDefined(params.fullySaturatedLambda(phaseIdx));

            if (FluidSystem::isLiquid(phaseIdx)) {
                lambda +=
                    regularizedSqrt_(std::max(0.0, std::min(1.0, fluidState.saturation(phaseIdx))))
                    * (params.fullySaturatedLambda(phaseIdx) - params.vacuumLambda());
            }
            else { // gas phase
                lambda += params.fullySaturatedLambda(phaseIdx) - params.vacuumLambda();
            }
        };

        lambda += params.vacuumLambda();
        assert(lambda >= 0);
        return lambda;
    }
    static Evaluation thermalConductivity(const Params& params,
                                       const FluidState& fluidState)
    {
        Valgrind::CheckDefined(params.vacuumLambda());

        Evaluation lambda = 0;
        for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
            Valgrind::CheckDefined(params.fullySaturatedLambda(phaseIdx));

            if (FluidSystem::isLiquid(phaseIdx)) {
                const auto& sat = Opm::decay<Evaluation>(fluidState.saturation(phaseIdx));
                lambda +=
                    regularizedSqrt_(Opm::max(0.0, Opm::min(1.0, sat)))
                    * (params.fullySaturatedLambda(phaseIdx) - params.vacuumLambda());
            }
            else { // gas phase
                lambda += params.fullySaturatedLambda(phaseIdx) - params.vacuumLambda();
            }
        };

        lambda += params.vacuumLambda();
        assert(lambda >= 0);
        return lambda;
    }
Example #14
0
    static LhsEval viscosity(const FluidState &fluidState,
                             const ParameterCache &/*paramCache*/,
                             unsigned phaseIdx)
    {
        typedef Opm::MathToolbox<LhsEval> LhsToolbox;
        typedef Opm::MathToolbox<typename FluidState::Scalar> FsToolbox;

        assert(0 <= phaseIdx  && phaseIdx < numPhases);

        const auto& T = FsToolbox::template toLhs<LhsEval>(fluidState.temperature(phaseIdx));
        const auto& p = FsToolbox::template toLhs<LhsEval>(fluidState.pressure(phaseIdx));

        if (phaseIdx == liquidPhaseIdx)
        {
            // assume pure water for the liquid phase
            // TODO: viscosity of mixture
            // couldn't find a way to solve the mixture problem
            return H2O::liquidViscosity(T, p);
        }
        else if (phaseIdx == gasPhaseIdx)
        {
            if(!useComplexRelations){
                return Air::gasViscosity(T, p);
            }
            else //using a complicated version of this fluid system
            {
                /* Wilke method. See:
                 *
                 * See: R. Reid, et al.: The Properties of Gases and Liquids,
                 * 4th edition, McGraw-Hill, 1987, 407-410 or
                 * 5th edition, McGraw-Hill, 2000, p. 9.21/22
                 *
                 */

                LhsEval muResult = 0;
                const LhsEval mu[numComponents] = {
                    H2O::gasViscosity(T, H2O::vaporPressure(T)),
                    Air::gasViscosity(T, p)
                };

                // molar masses
                const Scalar M[numComponents] =  {
                    H2O::molarMass(),
                    Air::molarMass()
                };

                for (unsigned i = 0; i < numComponents; ++i) {
                    LhsEval divisor = 0;
                    for (unsigned j = 0; j < numComponents; ++j) {
                        LhsEval phiIJ =
                            1 +
                            LhsToolbox::sqrt(mu[i]/mu[j]) * // 1 + (mu[i]/mu[j]^1/2
                            std::pow(M[j]/M[i], 1./4.0);   // (M[i]/M[j])^1/4

                        phiIJ *= phiIJ;
                        phiIJ /= std::sqrt(8*(1 + M[i]/M[j]));
                        divisor += FsToolbox::template toLhs<LhsEval>(fluidState.moleFraction(phaseIdx, j))*phiIJ;
                    }
                    const auto& xAlphaI = FsToolbox::template toLhs<LhsEval>(fluidState.moleFraction(phaseIdx, i));
                    muResult += xAlphaI*mu[i]/divisor;
                }
                return muResult;
            }
        }
        OPM_THROW(std::logic_error, "Invalid phase index " << phaseIdx);
    }
Example #15
0
    static Scalar viscosity(const FluidState &fluidState,
                            const ParameterCache &paramCache,
                            int phaseIdx)
    {
        assert(0 <= phaseIdx  && phaseIdx < numPhases);

        Scalar T = fluidState.temperature(phaseIdx);
        Scalar p = fluidState.pressure(phaseIdx);

        if (phaseIdx == lPhaseIdx)
        {
            // assume pure water for the liquid phase
            // TODO: viscosity of mixture
            // couldn't find a way to solve the mixture problem
            return H2O::liquidViscosity(T, p);
        }
        else if (phaseIdx == gPhaseIdx)
        {
            if(!useComplexRelations){
                return Air::gasViscosity(T, p);
            }
            else //using a complicated version of this fluid system
            {
                /* Wilke method. See:
                 *
                 * See: R. Reid, et al.: The Properties of Gases and Liquids,
                 * 4th edition, McGraw-Hill, 1987, 407-410 or
                 * 5th edition, McGraw-Hill, 2000, p. 9.21/22
                 *
                 */

                Scalar muResult = 0;
                const Scalar mu[numComponents] = {
                    H2O::gasViscosity(T,
                                      H2O::vaporPressure(T)),
                    Air::gasViscosity(T, p)
                };

                // molar masses
                const Scalar M[numComponents] =  {
                    H2O::molarMass(),
                    Air::molarMass()
                };

                for (int i = 0; i < numComponents; ++i)
                {
                    Scalar divisor = 0;
                    for (int j = 0; j < numComponents; ++j)
                    {
                        Scalar phiIJ = 1 + std::sqrt(mu[i]/mu[j]) * // 1 + (mu[i]/mu[j]^1/2
                            std::pow(M[j]/M[i], 1./4.0);   // (M[i]/M[j])^1/4

                        phiIJ *= phiIJ;
                        phiIJ /= std::sqrt(8*(1 + M[i]/M[j]));
                        divisor += fluidState.moleFraction(phaseIdx, j)*phiIJ;
                    }
                    muResult += fluidState.moleFraction(phaseIdx, i)*mu[i] / divisor;
                }
                return muResult;
            }
        }
        OPM_THROW(std::logic_error, "Invalid phase index " << phaseIdx);
    }
Example #16
0
    static Scalar density(const FluidState &fluidState,
                          const ParameterCache &paramCache,
                          int phaseIdx)
    {
        assert(0 <= phaseIdx  && phaseIdx < numPhases);

        Scalar T = fluidState.temperature(phaseIdx);
        Scalar p;
        if (isCompressible(phaseIdx))
            p = fluidState.pressure(phaseIdx);
        else {
            // random value which will hopefully cause things to blow
            // up if it is used in a calculation!
            p = - 1e100;
            Valgrind::SetUndefined(p);
        }


        Scalar sumMoleFrac = 0;
        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
            sumMoleFrac += fluidState.moleFraction(phaseIdx, compIdx);

        if (phaseIdx == lPhaseIdx)
        {
            if (!useComplexRelations)
                // assume pure water
                return H2O::liquidDensity(T, p);
            else
            {
                // See: Ochs 2008 (2.6)
                Scalar rholH2O = H2O::liquidDensity(T, p);
                Scalar clH2O = rholH2O/H2O::molarMass();

                return
                    clH2O
                    * (H2O::molarMass()*fluidState.moleFraction(lPhaseIdx, H2OIdx)
                           +
                           Air::molarMass()*fluidState.moleFraction(lPhaseIdx, AirIdx))
                   / sumMoleFrac;
            }
        }
        else if (phaseIdx == gPhaseIdx)
        {
            if (!useComplexRelations)
                // for the gas phase assume an ideal gas
                return
                    IdealGas::molarDensity(T, p)
                    * fluidState.averageMolarMass(gPhaseIdx)
                    / std::max(1e-5, sumMoleFrac);

            Scalar partialPressureH2O =
                fluidState.moleFraction(gPhaseIdx, H2OIdx)  *
                fluidState.pressure(gPhaseIdx);

            Scalar partialPressureAir =
                fluidState.moleFraction(gPhaseIdx, AirIdx)  *
                fluidState.pressure(gPhaseIdx);

            return
                H2O::gasDensity(T, partialPressureH2O) +
                Air::gasDensity(T, partialPressureAir);
        }
        OPM_THROW(std::logic_error, "Invalid phase index " << phaseIdx);
    }
 static Evaluation krn(const Params& params, const FluidState& fs)
 {
     const Evaluation& Sw =
         1.0 - Opm::decay<Evaluation>(fs.saturation(Traits::nonWettingPhaseIdx));
     return twoPhaseSatKrn(params, Sw);
 }
 static Evaluation krw(const Params& params, const FluidState& fs)
 {
     const auto& Sw = Opm::decay<Evaluation>(fs.saturation(Traits::wettingPhaseIdx));
     return twoPhaseSatKrw(params, Sw);
 }
void checkSame(const FluidState &fsRef, const FluidState &fsFlash)
{
    enum { numPhases = FluidState::numPhases };
    enum { numComponents = FluidState::numComponents };

    for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
        Scalar error;

        // check the pressures
        error = 1 - fsRef.pressure(phaseIdx)/fsFlash.pressure(phaseIdx);
        if (std::abs(error) > 1e-6) {
            std::cout << "pressure error phase " << phaseIdx << ": "
                      << fsFlash.pressure(phaseIdx)  << " flash vs "
                      << fsRef.pressure(phaseIdx) << " reference"
                      << " error=" << error << "\n";
        }

        // check the saturations
        error = fsRef.saturation(phaseIdx) - fsFlash.saturation(phaseIdx);
        if (std::abs(error) > 1e-6)
            std::cout << "saturation error phase " << phaseIdx << ": "
                      << fsFlash.saturation(phaseIdx) << " flash vs "
                      << fsRef.saturation(phaseIdx) << " reference"
                      << " error=" << error << "\n";

        // check the compositions
        for (int compIdx = 0; compIdx < numComponents; ++ compIdx) {
            error = fsRef.moleFraction(phaseIdx, compIdx) - fsFlash.moleFraction(phaseIdx, compIdx);
            if (std::abs(error) > 1e-6)
                std::cout << "composition error phase " << phaseIdx << ", component " << compIdx << ": "
                          << fsFlash.moleFraction(phaseIdx, compIdx) << " flash vs "
                          << fsRef.moleFraction(phaseIdx, compIdx) << " reference"
                          << " error=" << error << "\n";
        }
    }
}
Example #20
0
void checkFluidSystem()
{
    std::cout << "Testing fluid system '" << Dune::className<FluidSystem>() << "'\n";

    // make sure the fluid system provides the number of phases and
    // the number of components
    enum { numPhases = FluidSystem::numPhases };
    enum { numComponents = FluidSystem::numComponents };

    typedef HairSplittingFluidState<RhsEval, FluidSystem> FluidState;
    FluidState fs;
    fs.allowTemperature(true);
    fs.allowPressure(true);
    fs.allowComposition(true);
    fs.restrictToPhase(-1);

    // initialize memory the fluid state
    fs.base().setTemperature(273.15 + 20.0);
    for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
        fs.base().setPressure(phaseIdx, 1e5);
        fs.base().setSaturation(phaseIdx, 1.0/numPhases);
        for (int compIdx = 0; compIdx < numComponents; ++ compIdx) {
            fs.base().setMoleFraction(phaseIdx, compIdx, 1.0/numComponents);
        }
    }

    static_assert(std::is_same<typename FluidSystem::Scalar, Scalar>::value,
                  "The type used for floating point used by the fluid system must be the same"
                  " as the one passed to the checkFluidSystem() function");

    // check whether the parameter cache adheres to the API
    typedef typename FluidSystem::template ParameterCache<LhsEval> ParameterCache;

    ParameterCache paramCache;
    try { paramCache.updateAll(fs); } catch (...) {};
    try { paramCache.updateAll(fs, /*except=*/ParameterCache::None); } catch (...) {};
    try { paramCache.updateAll(fs, /*except=*/ParameterCache::Temperature | ParameterCache::Pressure | ParameterCache::Composition); } catch (...) {};
    try { paramCache.updateAllPressures(fs); } catch (...) {};

    for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
        fs.restrictToPhase(static_cast<int>(phaseIdx));
        try { paramCache.updatePhase(fs, phaseIdx); } catch (...) {};
        try { paramCache.updatePhase(fs, phaseIdx, /*except=*/ParameterCache::None); } catch (...) {};
        try { paramCache.updatePhase(fs, phaseIdx, /*except=*/ParameterCache::Temperature | ParameterCache::Pressure | ParameterCache::Composition); } catch (...) {};
        try { paramCache.updateTemperature(fs, phaseIdx); } catch (...) {};
        try { paramCache.updatePressure(fs, phaseIdx); } catch (...) {};
        try { paramCache.updateComposition(fs, phaseIdx); } catch (...) {};
        try { paramCache.updateSingleMoleFraction(fs, phaseIdx, /*compIdx=*/0); } catch (...) {};
    }

    // some value to make sure the return values of the fluid system
    // are convertible to scalars
    LhsEval val = 0.0;
    Scalar scalarVal = 0.0;

    scalarVal = 2*scalarVal; // get rid of GCC warning (only occurs with paranoid warning flags)
    val = 2*val; // get rid of GCC warning (only occurs with paranoid warning flags)

    // actually check the fluid system API
    try { FluidSystem::init(); } catch (...) {};
    for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
        fs.restrictToPhase(static_cast<int>(phaseIdx));
        fs.allowPressure(FluidSystem::isCompressible(phaseIdx));
        fs.allowComposition(true);
        fs.allowDensity(false);
        try { auto tmpVal OPM_UNUSED = FluidSystem::density(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the scalar used by the fluid state!"); } catch (...) {};
        try { val = FluidSystem::template density<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
        try { scalarVal = FluidSystem::template density<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};

        fs.allowPressure(true);
        fs.allowDensity(true);
        try { auto tmpVal OPM_UNUSED = FluidSystem::viscosity(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the scalar used by the fluid state!"); } catch (...) {};
        try { auto tmpVal OPM_UNUSED = FluidSystem::enthalpy(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the scalar used by the fluid state!"); } catch (...) {};
        try { auto tmpVal OPM_UNUSED = FluidSystem::heatCapacity(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the scalar used by the fluid state!"); } catch (...) {};
        try { auto tmpVal OPM_UNUSED= FluidSystem::thermalConductivity(fs, paramCache, phaseIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the scalar used by the fluid state!"); } catch (...) {};
        try { val = FluidSystem::template viscosity<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
        try { val = FluidSystem::template enthalpy<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
        try { val = FluidSystem::template heatCapacity<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
        try { val = FluidSystem::template thermalConductivity<FluidState, LhsEval>(fs, paramCache, phaseIdx); } catch (...) {};
        try { scalarVal = FluidSystem::template viscosity<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};
        try { scalarVal = FluidSystem::template enthalpy<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};
        try { scalarVal = FluidSystem::template heatCapacity<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};
        try { scalarVal = FluidSystem::template thermalConductivity<FluidState, Scalar>(fs, paramCache, phaseIdx); } catch (...) {};

        for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx) {
            fs.allowComposition(!FluidSystem::isIdealMixture(phaseIdx));
            try { auto tmpVal OPM_UNUSED = FluidSystem::fugacityCoefficient(fs, paramCache, phaseIdx, compIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the scalar used by the fluid state!"); } catch (...) {};
            try { val = FluidSystem::template fugacityCoefficient<FluidState, LhsEval>(fs, paramCache, phaseIdx, compIdx); } catch (...) {};
            try { scalarVal = FluidSystem::template fugacityCoefficient<FluidState, Scalar>(fs, paramCache, phaseIdx, compIdx); } catch (...) {};
            fs.allowComposition(true);
            try { auto tmpVal OPM_UNUSED = FluidSystem::diffusionCoefficient(fs, paramCache, phaseIdx, compIdx); static_assert(std::is_same<decltype(tmpVal), RhsEval>::value, "The default return value must be the scalar used by the fluid state!"); } catch (...) {};
            try { val = FluidSystem::template diffusionCoefficient<FluidState, LhsEval>(fs, paramCache, phaseIdx, compIdx); } catch (...) {};
            try { scalarVal = FluidSystem::template fugacityCoefficient<FluidState, Scalar>(fs, paramCache, phaseIdx, compIdx); } catch (...) {};
        }
    }

    // test for phaseName(), isLiquid() and isIdealGas()
    for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
        std::string name OPM_UNUSED = FluidSystem::phaseName(phaseIdx);
        bool bVal = FluidSystem::isLiquid(phaseIdx);
        bVal = FluidSystem::isIdealGas(phaseIdx);
        bVal = !bVal; // get rid of GCC warning (only occurs with paranoid warning flags)
    }

    // test for molarMass() and componentName()
    for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx) {
        val = FluidSystem::molarMass(compIdx);
        std::string name = FluidSystem::componentName(compIdx);
    }

    std::cout << "----------------------------------\n";
}
 void assign(const FluidState& fs)
 {
     for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
         temperature_[phaseIdx] = fs.temperature(phaseIdx);
     }
 }
 /*!
  * \brief Constructor
  *
  * The overlay fluid state copies the saturations from the
  * argument, so it initially behaves exactly like the underlying
  * fluid state.
  */
 SaturationOverlayFluidState(const FluidState &fs)
     : fs_(&fs)
 {
     for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
         saturation_[phaseIdx] = fs.saturation(phaseIdx);
 }
    static Scalar computeFugacityCoefficient(const FluidState &fs,
                                             const Params &params,
                                             int phaseIdx,
                                             int compIdx)
    {
        // note that we normalize the component mole fractions, so
        // that their sum is 100%. This increases numerical stability
        // considerably if the fluid state is not physical.
        Scalar Vm = params.molarVolume(phaseIdx);

        // Calculate b_i / b
        Scalar bi_b = params.bPure(phaseIdx, compIdx) / params.b(phaseIdx);

        // Calculate the compressibility factor
        Scalar RT = R*fs.temperature(phaseIdx);
        Scalar p = fs.pressure(phaseIdx); // molar volume in [bar]
        Scalar Z = p*Vm/RT; // compressibility factor

        // Calculate A^* and B^* (see: Reid, p. 42)
        Scalar Astar = params.a(phaseIdx)*p/(RT*RT);
        Scalar Bstar = params.b(phaseIdx)*p/(RT);

        // calculate delta_i (see: Reid, p. 145)
        Scalar sumMoleFractions = 0.0;
        for (int compJIdx = 0; compJIdx < numComponents; ++compJIdx)
            sumMoleFractions += fs.moleFraction(phaseIdx, compJIdx);
        Scalar deltai = 2*std::sqrt(params.aPure(phaseIdx, compIdx))/params.a(phaseIdx);
        Scalar tmp = 0;
        for (int compJIdx = 0; compJIdx < numComponents; ++compJIdx) {
            tmp +=
                fs.moleFraction(phaseIdx, compJIdx)
                / sumMoleFractions
                * std::sqrt(params.aPure(phaseIdx, compJIdx))
                * (1.0 - StaticParameters::interactionCoefficient(compIdx, compJIdx));
        };
        deltai *= tmp;

        Scalar base =
            (2*Z + Bstar*(u + std::sqrt(u*u - 4*w))) /
            (2*Z + Bstar*(u - std::sqrt(u*u - 4*w)));
        Scalar expo =  Astar/(Bstar*std::sqrt(u*u - 4*w))*(bi_b - deltai);

        Scalar fugCoeff =
            std::exp(bi_b*(Z - 1))/std::max(1e-9, Z - Bstar) *
            std::pow(base, expo);

        ////////
        // limit the fugacity coefficient to a reasonable range:
        //
        // on one side, we want the mole fraction to be at
        // least 10^-3 if the fugacity is at the current pressure
        //
        fugCoeff = std::min(1e10, fugCoeff);
        //
        // on the other hand, if the mole fraction of the component is 100%, we want the
        // fugacity to be at least 10^-3 Pa
        //
        fugCoeff = std::max(1e-10, fugCoeff);
        ///////////

        return fugCoeff;
    }
    static Scalar linearize_(Dune::FieldMatrix<Evaluation, numComponents, numComponents> &J,
                             Dune::FieldVector<Evaluation, numComponents> &defect,
                             FluidState &fluidState,
                             ParameterCache &paramCache,
                             int phaseIdx,
                             const ComponentVector &targetFug)
    {
        typedef MathToolbox<Evaluation> Toolbox;

        // reset jacobian
        J = 0;

        Scalar absError = 0;
        // calculate the defect (deviation of the current fugacities
        // from the target fugacities)
        for (int i = 0; i < numComponents; ++ i) {
            const Evaluation& phi = FluidSystem::fugacityCoefficient(fluidState,
                                                          paramCache,
                                                          phaseIdx,
                                                          i);
            const Evaluation& f = phi*fluidState.pressure(phaseIdx)*fluidState.moleFraction(phaseIdx, i);
            fluidState.setFugacityCoefficient(phaseIdx, i, phi);

            defect[i] = targetFug[i] - f;
            absError = std::max(absError, std::abs(Toolbox::value(defect[i])));
        }

        // assemble jacobian matrix of the constraints for the composition
        static const Scalar eps = std::numeric_limits<Scalar>::epsilon()*1e6;
        for (int i = 0; i < numComponents; ++ i) {
            ////////
            // approximately calculate partial derivatives of the
            // fugacity defect of all components in regard to the mole
            // fraction of the i-th component. This is done via
            // forward differences

            // deviate the mole fraction of the i-th component
            Evaluation xI = fluidState.moleFraction(phaseIdx, i);
            fluidState.setMoleFraction(phaseIdx, i, xI + eps);
            paramCache.updateSingleMoleFraction(fluidState, phaseIdx, i);

            // compute new defect and derivative for all component
            // fugacities
            for (int j = 0; j < numComponents; ++j) {
                // compute the j-th component's fugacity coefficient ...
                const Evaluation& phi = FluidSystem::fugacityCoefficient(fluidState,
                                                                         paramCache,
                                                                         phaseIdx,
                                                                         j);
                // ... and its fugacity ...
                const Evaluation& f =
                    phi *
                    fluidState.pressure(phaseIdx) *
                    fluidState.moleFraction(phaseIdx, j);
                // as well as the defect for this fugacity
                const Evaluation& defJPlusEps = targetFug[j] - f;

                // use forward differences to calculate the defect's
                // derivative
                J[j][i] = (defJPlusEps - defect[j])/eps;
            }

            // reset composition to original value
            fluidState.setMoleFraction(phaseIdx, i, xI);
            paramCache.updateSingleMoleFraction(fluidState, phaseIdx, i);

            // end forward differences
            ////////
        }

        return absError;
    }
Example #25
0
inline void testAll()
{
    typedef Opm::FluidSystems::Spe5<Scalar> FluidSystem;

    enum {
        numPhases = FluidSystem::numPhases,
        waterPhaseIdx = FluidSystem::waterPhaseIdx,
        gasPhaseIdx = FluidSystem::gasPhaseIdx,
        oilPhaseIdx = FluidSystem::oilPhaseIdx,

        numComponents = FluidSystem::numComponents,
        H2OIdx = FluidSystem::H2OIdx,
        C1Idx = FluidSystem::C1Idx,
        C3Idx = FluidSystem::C3Idx,
        C6Idx = FluidSystem::C6Idx,
        C10Idx = FluidSystem::C10Idx,
        C15Idx = FluidSystem::C15Idx,
        C20Idx = FluidSystem::C20Idx
    };

    typedef Opm::NcpFlash<Scalar, FluidSystem> Flash;
    typedef Dune::FieldVector<Scalar, numComponents> ComponentVector;
    typedef Opm::CompositionalFluidState<Scalar, FluidSystem> FluidState;

    typedef Opm::ThreePhaseMaterialTraits<Scalar, waterPhaseIdx, oilPhaseIdx, gasPhaseIdx> MaterialTraits;
    typedef Opm::LinearMaterial<MaterialTraits> MaterialLaw;
    typedef typename MaterialLaw::Params MaterialLawParams;

    typedef typename FluidSystem::template ParameterCache<Scalar> ParameterCache;

    ////////////
    // Initialize the fluid system and create the capillary pressure
    // parameters
    ////////////
    Scalar T = 273.15 + 20; // 20 deg Celsius
    FluidSystem::init(/*minTemperature=*/T - 1,
                      /*maxTemperature=*/T + 1,
                      /*minPressure=*/1.0e4,
                      /*maxTemperature=*/40.0e6);

    // set the parameters for the capillary pressure law
    MaterialLawParams matParams;
    for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
        matParams.setPcMinSat(phaseIdx, 0.0);
        matParams.setPcMaxSat(phaseIdx, 0.0);
    }
    matParams.finalize();

    ////////////
    // Create a fluid state
    ////////////
    FluidState gasFluidState;
    createSurfaceGasFluidSystem<FluidSystem>(gasFluidState);

    FluidState fluidState;
    ParameterCache paramCache;

    // temperature
    fluidState.setTemperature(T);

    // oil pressure
    fluidState.setPressure(oilPhaseIdx, 4000 * 6894.7573); // 4000 PSI

    // oil saturation
    fluidState.setSaturation(oilPhaseIdx, 1.0);
    fluidState.setSaturation(gasPhaseIdx, 1.0 - fluidState.saturation(oilPhaseIdx));

    // oil composition: SPE-5 reservoir oil
    fluidState.setMoleFraction(oilPhaseIdx, H2OIdx, 0.0);
    fluidState.setMoleFraction(oilPhaseIdx, C1Idx, 0.50);
    fluidState.setMoleFraction(oilPhaseIdx, C3Idx, 0.03);
    fluidState.setMoleFraction(oilPhaseIdx, C6Idx, 0.07);
    fluidState.setMoleFraction(oilPhaseIdx, C10Idx, 0.20);
    fluidState.setMoleFraction(oilPhaseIdx, C15Idx, 0.15);
    fluidState.setMoleFraction(oilPhaseIdx, C20Idx, 0.05);

    //makeOilSaturated<Scalar, FluidSystem>(fluidState, gasFluidState);

    // set the saturations and pressures of the other phases
    for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
        if (phaseIdx != oilPhaseIdx) {
            fluidState.setSaturation(phaseIdx, 0.0);
            fluidState.setPressure(phaseIdx, fluidState.pressure(oilPhaseIdx));
        }

        // initial guess for the composition (needed by the ComputeFromReferencePhase
        // constraint solver. TODO: bug in ComputeFromReferencePhase?)
        guessInitial<FluidSystem>(fluidState, phaseIdx);
    }

    typedef Opm::ComputeFromReferencePhase<Scalar, FluidSystem> CFRP;
    CFRP::solve(fluidState,
                paramCache,
                /*refPhaseIdx=*/oilPhaseIdx,
                /*setViscosity=*/false,
                /*setEnthalpy=*/false);

    ////////////
    // Calculate the total molarities of the components
    ////////////
    ComponentVector totalMolarities;
    for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx)
        totalMolarities[compIdx] = fluidState.saturation(oilPhaseIdx)*fluidState.molarity(oilPhaseIdx, compIdx);

    ////////////
    // Gradually increase the volume for and calculate the gas
    // formation factor, oil formation volume factor and gas formation
    // volume factor.
    ////////////

    FluidState flashFluidState, surfaceFluidState;
    flashFluidState.assign(fluidState);
    //Flash::guessInitial(flashFluidState, totalMolarities);
    Flash::template solve<MaterialLaw>(flashFluidState, matParams, paramCache, totalMolarities);

    Scalar surfaceAlpha = 1;
    surfaceAlpha = bringOilToSurface<Scalar, FluidSystem>(surfaceFluidState, surfaceAlpha, flashFluidState, /*guessInitial=*/true);
    Scalar rho_gRef = surfaceFluidState.density(gasPhaseIdx);
    Scalar rho_oRef = surfaceFluidState.density(oilPhaseIdx);

    std::vector<std::array<Scalar, 10> > resultTable;

    Scalar minAlpha = 0.98;
    Scalar maxAlpha = surfaceAlpha;

    std::cout << "alpha[-] p[Pa] S_g[-] rho_o[kg/m^3] rho_g[kg/m^3] <M_o>[kg/mol] <M_g>[kg/mol] R_s[m^3/m^3] B_g[-] B_o[-]\n";
    int n = 300;
    for (int i = 0; i < n; ++i) {
        // ratio between the original and the current volume
        Scalar alpha = minAlpha + (maxAlpha - minAlpha)*i/(n - 1);

        // increasing the volume means decreasing the molartity
        ComponentVector curTotalMolarities = totalMolarities;
        curTotalMolarities /= alpha;

        // "flash" the modified reservoir oil
        Flash::template solve<MaterialLaw>(flashFluidState, matParams, paramCache, curTotalMolarities);

        surfaceAlpha = bringOilToSurface<Scalar, FluidSystem>(surfaceFluidState,
                                                              surfaceAlpha,
                                                              flashFluidState,
                                                              /*guessInitial=*/false);
        Scalar Rs =
            surfaceFluidState.saturation(gasPhaseIdx)
            / surfaceFluidState.saturation(oilPhaseIdx);
        std::cout << alpha << " "
                  << flashFluidState.pressure(oilPhaseIdx) << " "
                  << flashFluidState.saturation(gasPhaseIdx) << " "
                  << flashFluidState.density(oilPhaseIdx) << " "
                  << flashFluidState.density(gasPhaseIdx) << " "
                  << flashFluidState.averageMolarMass(oilPhaseIdx) << " "
                  << flashFluidState.averageMolarMass(gasPhaseIdx) << " "
                  << Rs << " "
                  << rho_gRef/flashFluidState.density(gasPhaseIdx) << " "
                  << rho_oRef/flashFluidState.density(oilPhaseIdx) << " "
                  << "\n";

        std::array<Scalar, 10> tmp;
        tmp[0] = alpha;
        tmp[1] = flashFluidState.pressure(oilPhaseIdx);
        tmp[2] = flashFluidState.saturation(gasPhaseIdx);
        tmp[3] = flashFluidState.density(oilPhaseIdx);
        tmp[4] = flashFluidState.density(gasPhaseIdx);
        tmp[5] = flashFluidState.averageMolarMass(oilPhaseIdx);
        tmp[6] = flashFluidState.averageMolarMass(gasPhaseIdx);
        tmp[7] = Rs;
        tmp[8] = rho_gRef/flashFluidState.density(gasPhaseIdx);
        tmp[9] = rho_oRef/flashFluidState.density(oilPhaseIdx);

        resultTable.push_back(tmp);
    }

    std::cout << "reference density oil [kg/m^3]: " << rho_oRef << "\n";
    std::cout << "reference density gas [kg/m^3]: " << rho_gRef << "\n";

    Scalar hiresThresholdPressure = resultTable[20][1];
    printResult(resultTable,
                "Bg", /*firstIdx=*/1, /*secondIdx=*/8,
                /*hiresThreshold=*/hiresThresholdPressure);
    printResult(resultTable,
                "Bo", /*firstIdx=*/1, /*secondIdx=*/9,
                /*hiresThreshold=*/hiresThresholdPressure);
    printResult(resultTable,
                "Rs", /*firstIdx=*/1, /*secondIdx=*/7,
                /*hiresThreshold=*/hiresThresholdPressure);
}
Example #26
0
Scalar bringOilToSurface(FluidState& surfaceFluidState, Scalar alpha, const FluidState& reservoirFluidState, bool guessInitial)
{
    enum {
        numPhases = FluidSystem::numPhases,
        waterPhaseIdx = FluidSystem::waterPhaseIdx,
        gasPhaseIdx = FluidSystem::gasPhaseIdx,
        oilPhaseIdx = FluidSystem::oilPhaseIdx,

        numComponents = FluidSystem::numComponents
    };

    typedef Opm::NcpFlash<Scalar, FluidSystem> Flash;
    typedef Opm::ThreePhaseMaterialTraits<Scalar, waterPhaseIdx, oilPhaseIdx, gasPhaseIdx> MaterialTraits;
    typedef Opm::LinearMaterial<MaterialTraits> MaterialLaw;
    typedef typename MaterialLaw::Params MaterialLawParams;
    typedef Dune::FieldVector<Scalar, numComponents> ComponentVector;

    const Scalar refPressure = 1.0135e5; // [Pa]

    // set the parameters for the capillary pressure law
    MaterialLawParams matParams;
    for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
        matParams.setPcMinSat(phaseIdx, 0.0);
        matParams.setPcMaxSat(phaseIdx, 0.0);
    }
    matParams.finalize();

    // retieve the global volumetric component molarities
    surfaceFluidState.setTemperature(273.15 + 20);

    ComponentVector molarities;
    for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx)
        molarities[compIdx] = reservoirFluidState.molarity(oilPhaseIdx, compIdx);

    if (guessInitial) {
        // we start at a fluid state with reservoir oil.
        for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
            for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx) {
                surfaceFluidState.setMoleFraction(phaseIdx,
                                                  compIdx,
                                                  reservoirFluidState.moleFraction(phaseIdx, compIdx));
            }
            surfaceFluidState.setDensity(phaseIdx, reservoirFluidState.density(phaseIdx));
            surfaceFluidState.setPressure(phaseIdx, reservoirFluidState.pressure(phaseIdx));
            surfaceFluidState.setSaturation(phaseIdx, 0.0);
        }
        surfaceFluidState.setSaturation(oilPhaseIdx, 1.0);
        surfaceFluidState.setSaturation(gasPhaseIdx, 1.0 - surfaceFluidState.saturation(oilPhaseIdx));
    }

    typename FluidSystem::template ParameterCache<Scalar> paramCache;
    paramCache.updateAll(surfaceFluidState);

    // increase volume until we are at surface pressure. use the
    // newton method for this
    ComponentVector tmpMolarities;
    for (int i = 0;; ++i) {
        if (i >= 20)
            throw Opm::NumericalIssue("Newton method did not converge after 20 iterations");

        // calculate the deviation from the standard pressure
        tmpMolarities = molarities;
        tmpMolarities /= alpha;
        Flash::template solve<MaterialLaw>(surfaceFluidState, matParams, paramCache, tmpMolarities);
        Scalar f = surfaceFluidState.pressure(gasPhaseIdx) - refPressure;

        // calculate the derivative of the deviation from the standard
        // pressure
        Scalar eps = alpha*1e-10;
        tmpMolarities = molarities;
        tmpMolarities /= alpha + eps;
        Flash::template solve<MaterialLaw>(surfaceFluidState, matParams, paramCache, tmpMolarities);
        Scalar fStar = surfaceFluidState.pressure(gasPhaseIdx) - refPressure;
        Scalar fPrime = (fStar - f)/eps;

        // newton update
        Scalar delta = f/fPrime;
        alpha -= delta;
        if (std::abs(delta) < std::abs(alpha)*1e-9) {
            break;
        }
    }

    // calculate the final result
    tmpMolarities = molarities;
    tmpMolarities /= alpha;
    Flash::template solve<MaterialLaw>(surfaceFluidState, matParams, paramCache, tmpMolarities);
    return alpha;
}
    static void solve(FluidState& fluidState,
                      typename FluidSystem::template ParameterCache<typename FluidState::Scalar>& paramCache,
                      unsigned refPhaseIdx,
                      bool setViscosity,
                      bool setEnthalpy)
    {
        typedef MathToolbox<typename FluidState::Scalar> FsToolbox;

        // compute the density and enthalpy of the
        // reference phase
        paramCache.updatePhase(fluidState, refPhaseIdx);
        fluidState.setDensity(refPhaseIdx,
                              FluidSystem::density(fluidState,
                                                   paramCache,
                                                   refPhaseIdx));

        if (setEnthalpy)
            fluidState.setEnthalpy(refPhaseIdx,
                                   FluidSystem::enthalpy(fluidState,
                                                         paramCache,
                                                         refPhaseIdx));

        if (setViscosity)
            fluidState.setViscosity(refPhaseIdx,
                                    FluidSystem::viscosity(fluidState,
                                                           paramCache,
                                                           refPhaseIdx));

        // compute the fugacities of all components in the reference phase
        for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
            fluidState.setFugacityCoefficient(refPhaseIdx,
                                              compIdx,
                                              FluidSystem::fugacityCoefficient(fluidState,
                                                                               paramCache,
                                                                               refPhaseIdx,
                                                                               compIdx));
        }

        // compute all quantities for the non-reference phases
        for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
            if (phaseIdx == refPhaseIdx)
                continue; // reference phase is already calculated

            ComponentVector fugVec;
            for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
                const auto& fug = fluidState.fugacity(refPhaseIdx, compIdx);
                fugVec[compIdx] = FsToolbox::template decay<Evaluation>(fug);
            }

            CompositionFromFugacities::solve(fluidState, paramCache, phaseIdx, fugVec);

            if (setViscosity)
                fluidState.setViscosity(phaseIdx,
                                        FluidSystem::viscosity(fluidState,
                                                               paramCache,
                                                               phaseIdx));

            if (setEnthalpy)
                fluidState.setEnthalpy(phaseIdx,
                                       FluidSystem::enthalpy(fluidState,
                                                             paramCache,
                                                             phaseIdx));
        }
    }
    static void solve(FluidState &fluidState,
                      ParameterCache &paramCache,
                      int phaseIdx,
                      const ComponentVector &targetFug)
    {
        typedef MathToolbox<Evaluation> Toolbox;

        // use a much more efficient method in case the phase is an
        // ideal mixture
        if (FluidSystem::isIdealMixture(phaseIdx)) {
            solveIdealMix_(fluidState, paramCache, phaseIdx, targetFug);
            return;
        }

        //Dune::FMatrixPrecision<Scalar>::set_singular_limit(1e-25);

        // save initial composition in case something goes wrong
        Dune::FieldVector<Evaluation, numComponents> xInit;
        for (int i = 0; i < numComponents; ++i) {
            xInit[i] = fluidState.moleFraction(phaseIdx, i);
        }

        /////////////////////////
        // Newton method
        /////////////////////////

        // Jacobian matrix
        Dune::FieldMatrix<Evaluation, numComponents, numComponents> J;
        // solution, i.e. phase composition
        Dune::FieldVector<Evaluation, numComponents> x;
        // right hand side
        Dune::FieldVector<Evaluation, numComponents> b;

        paramCache.updatePhase(fluidState, phaseIdx);

        // maximum number of iterations
        const int nMax = 25;
        for (int nIdx = 0; nIdx < nMax; ++nIdx) {
            // calculate Jacobian matrix and right hand side
            linearize_(J, b, fluidState, paramCache, phaseIdx, targetFug);
            Valgrind::CheckDefined(J);
            Valgrind::CheckDefined(b);

            /*
            std::cout << FluidSystem::phaseName(phaseIdx) << "Phase composition: ";
            for (int i = 0; i < FluidSystem::numComponents; ++i)
                std::cout << fluidState.moleFraction(phaseIdx, i) << " ";
            std::cout << "\n";
            std::cout << FluidSystem::phaseName(phaseIdx) << "Phase phi: ";
            for (int i = 0; i < FluidSystem::numComponents; ++i)
                std::cout << fluidState.fugacityCoefficient(phaseIdx, i) << " ";
            std::cout << "\n";
            */

            // Solve J*x = b
            x = Toolbox::createConstant(0.0);
            try { J.solve(x, b); }
            catch (Dune::FMatrixError e)
            { throw Opm::NumericalIssue(e.what()); }

            //std::cout << "original delta: " << x << "\n";

            Valgrind::CheckDefined(x);

            /*
            std::cout << FluidSystem::phaseName(phaseIdx) << "Phase composition: ";
            for (int i = 0; i < FluidSystem::numComponents; ++i)
                std::cout << fluidState.moleFraction(phaseIdx, i) << " ";
            std::cout << "\n";
            std::cout << "J: " << J << "\n";
            std::cout << "rho: " << fluidState.density(phaseIdx) << "\n";
            std::cout << "delta: " << x << "\n";
            std::cout << "defect: " << b << "\n";

            std::cout << "J: " << J << "\n";

            std::cout << "---------------------------\n";
            */

            // update the fluid composition. b is also used to store
            // the defect for the next iteration.
            Scalar relError = update_(fluidState, paramCache, x, b, phaseIdx, targetFug);

            if (relError < 1e-9) {
                const Evaluation& rho = FluidSystem::density(fluidState, paramCache, phaseIdx);
                fluidState.setDensity(phaseIdx, rho);

                //std::cout << "num iterations: " << nIdx << "\n";
                return;
            }
        }

        OPM_THROW(Opm::NumericalIssue,
                  "Calculating the " << FluidSystem::phaseName(phaseIdx)
                  << "Phase composition failed. Initial {x} = {"
                  << xInit
                  << "}, {fug_t} = {" << targetFug << "}, p = " << fluidState.pressure(phaseIdx)
                  << ", T = " << fluidState.temperature(phaseIdx));
    }
    static void solve(FluidState &fluidState,
                      ParameterCache &paramCache,
                      int phasePresence,
                      const MMPCAuxConstraint<Evaluation> *auxConstraints,
                      unsigned numAuxConstraints,
                      bool setViscosity,
                      bool setInternalEnergy)
    {
        typedef MathToolbox<typename FluidState::Scalar> FsToolbox;
        static_assert(std::is_same<typename FluidState::Scalar, Evaluation>::value,
                      "The scalar type of the fluid state must be 'Evaluation'");

#ifndef NDEBUG
        // currently this solver can only handle fluid systems which
        // assume ideal mixtures of all fluids. TODO: relax this
        // (requires solving a non-linear system of equations, i.e. using
        // newton method.)
        for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
            assert(FluidSystem::isIdealMixture(phaseIdx));
        }
#endif

        // compute all fugacity coefficients
        for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
            paramCache.updatePhase(fluidState, phaseIdx);

            // since we assume ideal mixtures, the fugacity
            // coefficients of the components cannot depend on
            // composition, i.e. the parameters in the cache are valid
            for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
                Evaluation fugCoeff = FsToolbox::template toLhs<Evaluation>(
                    FluidSystem::fugacityCoefficient(fluidState, paramCache, phaseIdx, compIdx));
                fluidState.setFugacityCoefficient(phaseIdx, compIdx, fugCoeff);
            }
        }

        // create the linear system of equations which defines the
        // mole fractions
        static const int numEq = numComponents*numPhases;
        Dune::FieldMatrix<Evaluation, numEq, numEq> M(Toolbox::createConstant(0.0));
        Dune::FieldVector<Evaluation, numEq> x(Toolbox::createConstant(0.0));
        Dune::FieldVector<Evaluation, numEq> b(Toolbox::createConstant(0.0));

        // assemble the equations expressing the fact that the
        // fugacities of each component are equal in all phases
        for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
            const Evaluation& entryCol1 =
                fluidState.fugacityCoefficient(/*phaseIdx=*/0, compIdx)
                *fluidState.pressure(/*phaseIdx=*/0);
            unsigned col1Idx = compIdx;

            for (unsigned phaseIdx = 1; phaseIdx < numPhases; ++phaseIdx) {
                unsigned rowIdx = (phaseIdx - 1)*numComponents + compIdx;
                unsigned col2Idx = phaseIdx*numComponents + compIdx;

                const Evaluation& entryCol2 =
                    fluidState.fugacityCoefficient(phaseIdx, compIdx)
                    *fluidState.pressure(phaseIdx);

                M[rowIdx][col1Idx] = entryCol1;
                M[rowIdx][col2Idx] = -entryCol2;
            }
        }

        // assemble the equations expressing the assumption that the
        // sum of all mole fractions in each phase must be 1 for the
        // phases present.
        unsigned presentPhases = 0;
        for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
            if (!(phasePresence & (1 << phaseIdx)))
                continue;

            unsigned rowIdx = numComponents*(numPhases - 1) + presentPhases;
            presentPhases += 1;

            b[rowIdx] = Toolbox::createConstant(1.0);
            for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
                unsigned colIdx = phaseIdx*numComponents + compIdx;

                M[rowIdx][colIdx] = Toolbox::createConstant(1.0);
            }
        }

        assert(presentPhases + numAuxConstraints == numComponents);

        // incorperate the auxiliary equations, i.e., the explicitly given mole fractions
        for (unsigned auxEqIdx = 0; auxEqIdx < numAuxConstraints; ++auxEqIdx) {
            unsigned rowIdx = numComponents*(numPhases - 1) + presentPhases + auxEqIdx;
            b[rowIdx] = auxConstraints[auxEqIdx].value();

            unsigned colIdx = auxConstraints[auxEqIdx].phaseIdx()*numComponents + auxConstraints[auxEqIdx].compIdx();
            M[rowIdx][colIdx] = 1.0;
        }

        // solve for all mole fractions
        try {
            Dune::FMatrixPrecision<Scalar>::set_singular_limit(1e-50);
            M.solve(x, b);
        }
        catch (const Dune::FMatrixError &e) {
            OPM_THROW(NumericalProblem,
                      "Numerical problem in MiscibleMultiPhaseComposition::solve(): " << e.what() << "; M="<<M);
        }
        catch (...) {
            throw;
        }


        // set all mole fractions and the additional quantities in
        // the fluid state
        for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
            for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
                unsigned rowIdx = phaseIdx*numComponents + compIdx;
                fluidState.setMoleFraction(phaseIdx, compIdx, x[rowIdx]);
            }
            paramCache.updateComposition(fluidState, phaseIdx);

            const Evaluation& rho = FluidSystem::density(fluidState, paramCache, phaseIdx);
            fluidState.setDensity(phaseIdx, rho);

            if (setViscosity) {
                const Evaluation& mu = FluidSystem::viscosity(fluidState, paramCache, phaseIdx);
                fluidState.setViscosity(phaseIdx, mu);
            }

            if (setInternalEnergy) {
                const Evaluation& h =  FluidSystem::enthalpy(fluidState, paramCache, phaseIdx);
                fluidState.setEnthalpy(phaseIdx, h);
            }
        }
    }
Example #30
0
    static LhsEval density(const FluidState &fluidState,
                           const ParameterCache &/*paramCache*/,
                           unsigned phaseIdx)
    {
        typedef Opm::MathToolbox<typename FluidState::Scalar> FsToolbox;
        typedef Opm::MathToolbox<LhsEval> LhsToolbox;

        assert(0 <= phaseIdx  && phaseIdx < numPhases);

        const auto& T = FsToolbox::template toLhs<LhsEval>(fluidState.temperature(phaseIdx));
        LhsEval p;
        if (isCompressible(phaseIdx))
            p = FsToolbox::template toLhs<LhsEval>(fluidState.pressure(phaseIdx));
        else {
            // random value which will hopefully cause things to blow
            // up if it is used in a calculation!
            p = - 1e100;
            Valgrind::SetUndefined(p);
        }


        LhsEval sumMoleFrac = 0;
        for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx)
            sumMoleFrac += FsToolbox::template toLhs<LhsEval>(fluidState.moleFraction(phaseIdx, compIdx));

        if (phaseIdx == liquidPhaseIdx)
        {
            if (!useComplexRelations)
                // assume pure water
                return H2O::liquidDensity(T, p);
            else
            {
                // See: Ochs 2008 (2.6)
                const LhsEval& rholH2O = H2O::liquidDensity(T, p);
                const LhsEval& clH2O = rholH2O/H2O::molarMass();

                const auto& xlH2O = FsToolbox::template toLhs<LhsEval>(fluidState.moleFraction(liquidPhaseIdx, H2OIdx));
                const auto& xlAir = FsToolbox::template toLhs<LhsEval>(fluidState.moleFraction(liquidPhaseIdx, AirIdx));

                return clH2O*(H2O::molarMass()*xlH2O + Air::molarMass()*xlAir)/sumMoleFrac;
            }
        }
        else if (phaseIdx == gasPhaseIdx)
        {
            if (!useComplexRelations)
                // for the gas phase assume an ideal gas
                return
                    IdealGas::molarDensity(T, p)
                    * FsToolbox::template toLhs<LhsEval>(fluidState.averageMolarMass(gasPhaseIdx))
                    / LhsToolbox::max(1e-5, sumMoleFrac);

            LhsEval partialPressureH2O =
                FsToolbox::template toLhs<LhsEval>(fluidState.moleFraction(gasPhaseIdx, H2OIdx))
                *FsToolbox::template toLhs<LhsEval>(fluidState.pressure(gasPhaseIdx));

            LhsEval partialPressureAir =
                FsToolbox::template toLhs<LhsEval>(fluidState.moleFraction(gasPhaseIdx, AirIdx))
                *FsToolbox::template toLhs<LhsEval>(fluidState.pressure(gasPhaseIdx));

            return H2O::gasDensity(T, partialPressureH2O) + Air::gasDensity(T, partialPressureAir);
        }
        OPM_THROW(std::logic_error, "Invalid phase index " << phaseIdx);
    }