Scalar computeSumxg(FluidState& resultFluidState, const FluidState& prestineFluidState, const FluidState& gasFluidState, Scalar additionalGas) { static const int oilPhaseIdx = FluidSystem::oilPhaseIdx; static const int gasPhaseIdx = FluidSystem::gasPhaseIdx; static const int numComponents = FluidSystem::numComponents; typedef Dune::FieldVector<Scalar, numComponents> ComponentVector; typedef Opm::NcpFlash<Scalar, FluidSystem> Flash; resultFluidState.assign(prestineFluidState); // add a bit of additional gas components ComponentVector totalMolarities; for (unsigned compIdx = 0; compIdx < FluidSystem::numComponents; ++ compIdx) totalMolarities = prestineFluidState.molarity(oilPhaseIdx, compIdx) + additionalGas*gasFluidState.moleFraction(gasPhaseIdx, compIdx); // "flash" the modified fluid state typename FluidSystem::ParameterCache paramCache; Flash::solve(resultFluidState, totalMolarities); Scalar sumxg = 0; for (unsigned compIdx = 0; compIdx < FluidSystem::numComponents; ++compIdx) sumxg += resultFluidState.moleFraction(gasPhaseIdx, compIdx); return sumxg; }
void makeOilSaturated(FluidState& fluidState, const FluidState& gasFluidState) { static const int gasPhaseIdx = FluidSystem::gasPhaseIdx; FluidState prestineFluidState; prestineFluidState.assign(fluidState); Scalar sumxg = 0; for (unsigned compIdx = 0; compIdx < FluidSystem::numComponents; ++compIdx) sumxg += fluidState.moleFraction(gasPhaseIdx, compIdx); // Newton method Scalar tol = 1e-8; Scalar additionalGas = 0; // [mol] for (int i = 0; std::abs(sumxg - 1) > tol; ++i) { if (i > 50) throw std::runtime_error("Newton method did not converge after 50 iterations"); Scalar eps = std::max(1e-8, additionalGas*1e-8); Scalar f = 1 - computeSumxg<Scalar, FluidSystem>(prestineFluidState, fluidState, gasFluidState, additionalGas); Scalar fStar = 1 - computeSumxg<Scalar, FluidSystem>(prestineFluidState, fluidState, gasFluidState, additionalGas + eps); Scalar fPrime = (fStar - f)/eps; additionalGas -= f/fPrime; }; }