/* * Verify calculation of total mass fraction given a gas saturation */ TEST_F(PorousFlowWaterNCGTest, totalMassFraction) { const Real p = 1.0e6; const Real T = 350.0; const Real s = 0.2; Real Z = _fp->totalMassFraction(p, T, s); // Test that the saturation calculated in this fluid state using Z is equal to s FluidStatePhaseEnum phase_state; std::vector<FluidStateProperties> fsp(2, FluidStateProperties(2)); _fp->massFractions(p, T, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::TWOPHASE); _fp->gasProperties(p, T, fsp); Real liquid_pressure = p + _pc->capillaryPressure(1.0 - s); _fp->liquidProperties(liquid_pressure, T, fsp); _fp->saturationTwoPhase(p, T, Z, fsp); ABS_TEST(fsp[1].saturation, s, 1.0e-8); }
Real PorousFlowWaterNCG::totalMassFraction( Real pressure, Real temperature, Real /* Xnacl */, Real saturation, unsigned int qp) const { // Check whether the input temperature is within the region of validity checkVariables(temperature); // FluidStateProperties data structure std::vector<FluidStateProperties> fsp(_num_phases, FluidStateProperties(_num_components)); FluidStateProperties & liquid = fsp[_aqueous_phase_number]; FluidStateProperties & gas = fsp[_gas_phase_number]; // Calculate equilibrium mass fractions in the two-phase state Real Xncg, dXncg_dp, dXncg_dT, Yh2o, dYh2o_dp, dYh2o_dT; equilibriumMassFractions( pressure, temperature, Xncg, dXncg_dp, dXncg_dT, Yh2o, dYh2o_dp, dYh2o_dT); // Save the mass fractions in the FluidStateMassFractions object const Real Yncg = 1.0 - Yh2o; liquid.mass_fraction[_aqueous_fluid_component] = 1.0 - Xncg; liquid.mass_fraction[_gas_fluid_component] = Xncg; gas.mass_fraction[_aqueous_fluid_component] = Yh2o; gas.mass_fraction[_gas_fluid_component] = Yncg; // Gas properties gasProperties(pressure, temperature, fsp); // Liquid properties const Real liquid_saturation = 1.0 - saturation; const Real liquid_pressure = pressure - _pc.capillaryPressure(liquid_saturation, qp); liquidProperties(liquid_pressure, temperature, fsp); // The total mass fraction of ncg (Z) can now be calculated const Real Z = (saturation * gas.density * Yncg + liquid_saturation * liquid.density * Xncg) / (saturation * gas.density + liquid_saturation * liquid.density); return Z; }
/* * Verify calculation of total mass fraction given a gas saturation */ TEST_F(PorousFlowBrineCO2Test, totalMassFraction) { const Real p = 1.0e6; const Real T = 350.0; const Real Xnacl = 0.1; const Real s = 0.2; Real Z = _fp->totalMassFraction(p, T, Xnacl, s); // Test that the saturation calculated in this fluid state using Z is equal to s FluidStatePhaseEnum phase_state; const unsigned int np = _fp->numPhases(); const unsigned int nc = _fp->numComponents(); std::vector<FluidStateProperties> fsp(np, FluidStateProperties(nc)); _fp->massFractions(p, T, Xnacl, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::TWOPHASE); _fp->gasProperties(p, T, fsp); Real liquid_pressure = p + _pc->capillaryPressure(1.0 - s); _fp->liquidProperties(liquid_pressure, T, Xnacl, fsp); _fp->saturationTwoPhase(p, T, Xnacl, Z, fsp); ABS_TEST(fsp[1].saturation, s, 1.0e-8); }
/* * Verify calculation of actual mass fraction and derivatives depending on value of * total mass fraction */ TEST_F(PorousFlowWaterNCGTest, MassFraction) { const Real p = 1.0e6; const Real T = 350.0; FluidStatePhaseEnum phase_state; std::vector<FluidStateProperties> fsp(2, FluidStateProperties(2)); // Liquid region Real Z = 0.0001; _fp->massFractions(p, T, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::LIQUID); // Verfify mass fraction values Real Xncg = fsp[0].mass_fraction[1]; Real Yncg = fsp[1].mass_fraction[1]; Real Xh2o = fsp[0].mass_fraction[0]; Real Yh2o = fsp[1].mass_fraction[0]; ABS_TEST(Xncg, Z, 1.0e-8); ABS_TEST(Yncg, 0.0, 1.0e-8); ABS_TEST(Xh2o, 1.0 - Z, 1.0e-8); ABS_TEST(Yh2o, 0.0, 1.0e-8); // Verify derivatives Real dXncg_dp = fsp[0].dmass_fraction_dp[1]; Real dXncg_dT = fsp[0].dmass_fraction_dT[1]; Real dXncg_dZ = fsp[0].dmass_fraction_dZ[1]; Real dYncg_dp = fsp[1].dmass_fraction_dp[1]; Real dYncg_dT = fsp[1].dmass_fraction_dT[1]; Real dYncg_dZ = fsp[1].dmass_fraction_dZ[1]; ABS_TEST(dXncg_dp, 0.0, 1.0e-8); ABS_TEST(dXncg_dT, 0.0, 1.0e-8); ABS_TEST(dXncg_dZ, 1.0, 1.0e-8); ABS_TEST(dYncg_dp, 0.0, 1.0e-8); ABS_TEST(dYncg_dT, 0.0, 1.0e-8); ABS_TEST(dYncg_dZ, 0.0, 1.0e-8); // Gas region Z = 0.995; _fp->massFractions(p, T, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::GAS); // Verfify mass fraction values Xncg = fsp[0].mass_fraction[1]; Yncg = fsp[1].mass_fraction[1]; Xh2o = fsp[0].mass_fraction[0]; Yh2o = fsp[1].mass_fraction[0]; ABS_TEST(Xncg, 0.0, 1.0e-8); ABS_TEST(Yncg, Z, 1.0e-8); ABS_TEST(Xh2o, 0.0, 1.0e-8); ABS_TEST(Yh2o, 1.0 - Z, 1.0e-8); // Verify derivatives dXncg_dp = fsp[0].dmass_fraction_dp[1]; dXncg_dT = fsp[0].dmass_fraction_dT[1]; dXncg_dZ = fsp[0].dmass_fraction_dZ[1]; dYncg_dp = fsp[1].dmass_fraction_dp[1]; dYncg_dT = fsp[1].dmass_fraction_dT[1]; dYncg_dZ = fsp[1].dmass_fraction_dZ[1]; ABS_TEST(dXncg_dp, 0.0, 1.0e-8); ABS_TEST(dXncg_dT, 0.0, 1.0e-8); ABS_TEST(dXncg_dZ, 0.0, 1.0e-8); ABS_TEST(dYncg_dp, 0.0, 1.0e-8); ABS_TEST(dYncg_dT, 0.0, 1.0e-8); ABS_TEST(dYncg_dZ, 1.0, 1.0e-8); // Two phase region. In this region, the mass fractions and derivatives can // be verified using the equilibrium mass fraction derivatives that have // been verified above Z = 0.45; _fp->massFractions(p, T, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::TWOPHASE); // Equilibrium mass fractions and derivatives Real Xncg_eq, dXncg_dp_eq, dXncg_dT_eq, Yh2o_eq, dYh2o_dp_eq, dYh2o_dT_eq; _fp->equilibriumMassFractions( p, T, Xncg_eq, dXncg_dp_eq, dXncg_dT_eq, Yh2o_eq, dYh2o_dp_eq, dYh2o_dT_eq); // Verfify mass fraction values Xncg = fsp[0].mass_fraction[1]; Yncg = fsp[1].mass_fraction[1]; Xh2o = fsp[0].mass_fraction[0]; Yh2o = fsp[1].mass_fraction[0]; ABS_TEST(Xncg, Xncg_eq, 1.0e-8); ABS_TEST(Yncg, 1.0 - Yh2o_eq, 1.0e-8); ABS_TEST(Xh2o, 1.0 - Xncg_eq, 1.0e-8); ABS_TEST(Yh2o, Yh2o_eq, 1.0e-8); // Verify derivatives wrt p and T dXncg_dp = fsp[0].dmass_fraction_dp[1]; dXncg_dT = fsp[0].dmass_fraction_dT[1]; dXncg_dZ = fsp[0].dmass_fraction_dZ[1]; dYncg_dp = fsp[1].dmass_fraction_dp[1]; dYncg_dT = fsp[1].dmass_fraction_dT[1]; dYncg_dZ = fsp[1].dmass_fraction_dZ[1]; ABS_TEST(dXncg_dp, dXncg_dp_eq, 1.0e-8); ABS_TEST(dXncg_dT, dXncg_dT_eq, 1.0e-8); ABS_TEST(dXncg_dZ, 0.0, 1.0e-8); ABS_TEST(dYncg_dp, -dYh2o_dp_eq, 1.0e-8); ABS_TEST(dYncg_dT, -dYh2o_dT_eq, 1.0e-8); ABS_TEST(dYncg_dZ, 0.0, 1.0e-8); // Use finite differences to verify derivative wrt Z is unaffected by Z const Real dZ = 1.0e-8; _fp->massFractions(p, T, Z + dZ, phase_state, fsp); Real Xncg1 = fsp[0].mass_fraction[1]; Real Yncg1 = fsp[1].mass_fraction[1]; _fp->massFractions(p, T, Z - dZ, phase_state, fsp); Real Xncg2 = fsp[0].mass_fraction[1]; Real Yncg2 = fsp[1].mass_fraction[1]; ABS_TEST(dXncg_dZ, (Xncg1 - Xncg2) / (2.0 * dZ), 1.0e-8); ABS_TEST(dYncg_dZ, (Yncg1 - Yncg2) / (2.0 * dZ), 1.0e-8); }
/* * Verify calculation of gas saturation and derivatives in the two-phase region */ TEST_F(PorousFlowWaterNCGTest, twoPhase) { const Real p = 1.0e6; const Real T = 350.0; FluidStatePhaseEnum phase_state; std::vector<FluidStateProperties> fsp(2, FluidStateProperties(2)); // In the two-phase region, the mass fractions are the equilibrium values, so // a temporary value of Z can be used (as long as it corresponds to the two-phase // region) Real Z = 0.45; _fp->massFractions(p, T, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::TWOPHASE); // Calculate Z that gives a saturation of 0.25 Real gas_saturation = 0.25; Real liquid_pressure = p + _pc->capillaryPressure(1.0 - gas_saturation); // Calculate gas density and liquid density _fp->gasProperties(p, T, fsp); _fp->liquidProperties(liquid_pressure, T, fsp); // The mass fraction that corresponds to a gas_saturation = 0.25 Z = (gas_saturation * fsp[1].density * fsp[1].mass_fraction[1] + (1.0 - gas_saturation) * fsp[0].density * fsp[0].mass_fraction[1]) / (gas_saturation * fsp[1].density + (1.0 - gas_saturation) * fsp[0].density); // Calculate the gas saturation and derivatives _fp->saturationTwoPhase(p, T, Z, fsp); ABS_TEST(fsp[1].saturation, gas_saturation, 1.0e-8); // Test the derivatives const Real dp = 1.0e-1; gas_saturation = fsp[1].saturation; Real dgas_saturation_dp = fsp[1].dsaturation_dp; Real dgas_saturation_dT = fsp[1].dsaturation_dT; Real dgas_saturation_dZ = fsp[1].dsaturation_dZ; _fp->massFractions(p + dp, T, Z, phase_state, fsp); _fp->gasProperties(p + dp, T, fsp); _fp->saturationTwoPhase(p + dp, T, Z, fsp); Real gsat1 = fsp[1].saturation; _fp->massFractions(p - dp, T, Z, phase_state, fsp); _fp->gasProperties(p - dp, T, fsp); _fp->saturationTwoPhase(p - dp, T, Z, fsp); Real gsat2 = fsp[1].saturation; REL_TEST(dgas_saturation_dp, (gsat1 - gsat2) / (2.0 * dp), 1.0e-6); // Derivative wrt T const Real dT = 1.0e-4; _fp->massFractions(p, T + dT, Z, phase_state, fsp); _fp->gasProperties(p, T + dT, fsp); _fp->saturationTwoPhase(p, T + dT, Z, fsp); gsat1 = fsp[1].saturation; _fp->massFractions(p, T - dT, Z, phase_state, fsp); _fp->gasProperties(p, T - dT, fsp); _fp->saturationTwoPhase(p, T - dT, Z, fsp); gsat2 = fsp[1].saturation; REL_TEST(dgas_saturation_dT, (gsat1 - gsat2) / (2.0 * dT), 1.0e-6); // Derivative wrt Z const Real dZ = 1.0e-8; _fp->massFractions(p, T, Z, phase_state, fsp); _fp->gasProperties(p, T, fsp); _fp->saturationTwoPhase(p, T, Z + dZ, fsp); gsat1 = fsp[1].saturation; _fp->saturationTwoPhase(p, T, Z - dZ, fsp); gsat2 = fsp[1].saturation; REL_TEST(dgas_saturation_dZ, (gsat1 - gsat2) / (2.0 * dZ), 1.0e-6); }
/* * Verify calculation of liquid density, viscosity, enthalpy and derivatives. Note that as * density and viscosity don't depend on mass fraction, only the liquid region needs to be * tested (the calculations are identical in the two phase region). The enthalpy does depend * on mass fraction, so should be tested in the two phase region as well as the liquid region */ TEST_F(PorousFlowWaterNCGTest, liquidProperties) { const Real p = 1.0e6; const Real T = 350.0; std::vector<FluidStateProperties> fsp(2, FluidStateProperties(2)); // Verify fluid density and viscosity _fp->liquidProperties(p, T, fsp); Real liquid_density = fsp[0].density; Real liquid_viscosity = fsp[0].viscosity; Real density = _water_fp->rho_from_p_T(p, T); Real viscosity = _water_fp->mu(p, T); ABS_TEST(liquid_density, density, 1.0e-12); ABS_TEST(liquid_viscosity, viscosity, 1.0e-12); // Verify derivatives Real ddensity_dp = fsp[0].ddensity_dp; Real ddensity_dT = fsp[0].ddensity_dT; Real ddensity_dZ = fsp[0].ddensity_dZ; Real dviscosity_dp = fsp[0].dviscosity_dp; Real dviscosity_dT = fsp[0].dviscosity_dT; Real dviscosity_dZ = fsp[0].dviscosity_dZ; Real denthalpy_dp = fsp[0].denthalpy_dp; Real denthalpy_dT = fsp[0].denthalpy_dT; Real denthalpy_dZ = fsp[0].denthalpy_dZ; const Real dp = 1.0; _fp->liquidProperties(p + dp, T, fsp); Real rho1 = fsp[0].density; Real mu1 = fsp[0].viscosity; Real h1 = fsp[0].enthalpy; _fp->liquidProperties(p - dp, T, fsp); Real rho2 = fsp[0].density; Real mu2 = fsp[0].viscosity; Real h2 = fsp[0].enthalpy; REL_TEST(ddensity_dp, (rho1 - rho2) / (2.0 * dp), 1.0e-6); REL_TEST(dviscosity_dp, (mu1 - mu2) / (2.0 * dp), 1.0e-5); REL_TEST(denthalpy_dp, (h1 - h2) / (2.0 * dp), 1.0e-5); const Real dT = 1.0e-4; _fp->liquidProperties(p, T + dT, fsp); rho1 = fsp[0].density; mu1 = fsp[0].viscosity; h1 = fsp[0].enthalpy; _fp->liquidProperties(p, T - dT, fsp); rho2 = fsp[0].density; mu2 = fsp[0].viscosity; h2 = fsp[0].enthalpy; REL_TEST(ddensity_dT, (rho1 - rho2) / (2.0 * dT), 1.0e-6); REL_TEST(dviscosity_dT, (mu1 - mu2) / (2.0 * dT), 1.0e-6); REL_TEST(denthalpy_dT, (h1 - h2) / (2.0 * dT), 1.0e-5); Real Z = 0.0001; const Real dZ = 1.0e-8; FluidStatePhaseEnum phase_state; _fp->massFractions(p, T, Z, phase_state, fsp); _fp->liquidProperties(p, T, fsp); denthalpy_dp = fsp[0].denthalpy_dp; denthalpy_dT = fsp[0].denthalpy_dT; denthalpy_dZ = fsp[0].denthalpy_dZ; _fp->massFractions(p, T, Z + dZ, phase_state, fsp); _fp->liquidProperties(p, T, fsp); h1 = fsp[0].enthalpy; _fp->massFractions(p, T, Z - dZ, phase_state, fsp); _fp->liquidProperties(p, T, fsp); h2 = fsp[0].enthalpy; REL_TEST(denthalpy_dZ, (h1 - h2) / (2.0 * dZ), 1.0e-6); // Density and viscosity don't depend on Z, so derivatives should be 0 ABS_TEST(ddensity_dZ, 0.0, 1.0e-12); ABS_TEST(dviscosity_dZ, 0.0, 1.0e-12); // Check enthalpy calculations in the two phase region as well. Note that the mass fractions // vary with pressure and temperature in this region Z = 0.45; _fp->massFractions(p, T, Z, phase_state, fsp); _fp->liquidProperties(p, T, fsp); denthalpy_dp = fsp[0].denthalpy_dp; denthalpy_dT = fsp[0].denthalpy_dT; denthalpy_dZ = fsp[0].denthalpy_dZ; _fp->massFractions(p + dp, T, Z, phase_state, fsp); _fp->liquidProperties(p + dp, T, fsp); h1 = fsp[0].enthalpy; _fp->massFractions(p - dp, T, Z, phase_state, fsp); _fp->liquidProperties(p - dp, T, fsp); h2 = fsp[0].enthalpy; REL_TEST(denthalpy_dp, (h1 - h2) / (2.0 * dp), 1.0e-5); _fp->massFractions(p, T + dT, Z, phase_state, fsp); _fp->liquidProperties(p, T + dT, fsp); h1 = fsp[0].enthalpy; _fp->massFractions(p, T - dT, Z, phase_state, fsp); _fp->liquidProperties(p, T - dT, fsp); h2 = fsp[0].enthalpy; REL_TEST(denthalpy_dT, (h1 - h2) / (2.0 * dT), 1.0e-5); _fp->massFractions(p, T, Z + dZ, phase_state, fsp); _fp->liquidProperties(p, T, fsp); h1 = fsp[0].enthalpy; _fp->massFractions(p, T, Z - dZ, phase_state, fsp); _fp->liquidProperties(p, T, fsp); h2 = fsp[0].enthalpy; ABS_TEST(denthalpy_dZ, (h1 - h2) / (2.0 * dZ), 1.0e-5); }
/* * Verify calculation of gas density, viscosity, enthalpy and derivatives */ TEST_F(PorousFlowWaterNCGTest, gasProperties) { const Real p = 1.0e6; const Real T = 350.0; FluidStatePhaseEnum phase_state; std::vector<FluidStateProperties> fsp(2, FluidStateProperties(2)); // Gas region Real Z = 0.995; _fp->massFractions(p, T, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::GAS); // Verify fluid density, viscosity and enthalpy _fp->gasProperties(p, T, fsp); Real gas_density = fsp[1].density; Real gas_viscosity = fsp[1].viscosity; Real gas_enthalpy = fsp[1].enthalpy; Real density = _ncg_fp->rho_from_p_T(Z * p, T) + _water_fp->rho_from_p_T(_water_fp->vaporPressure(T), T); Real viscosity = Z * _ncg_fp->mu(Z * p, T) + (1.0 - Z) * _water_fp->mu(_water_fp->vaporPressure(T), T); Real enthalpy = Z * _ncg_fp->h(Z * p, T) + (1.0 - Z) * _water_fp->h(_water_fp->vaporPressure(T), T); ABS_TEST(gas_density, density, 1.0e-8); ABS_TEST(gas_viscosity, viscosity, 1.0e-8); ABS_TEST(gas_enthalpy, enthalpy, 1.0e-8); // Verify derivatives Real ddensity_dp = fsp[1].ddensity_dp; Real ddensity_dT = fsp[1].ddensity_dT; Real ddensity_dZ = fsp[1].ddensity_dZ; Real dviscosity_dp = fsp[1].dviscosity_dp; Real dviscosity_dT = fsp[1].dviscosity_dT; Real dviscosity_dZ = fsp[1].dviscosity_dZ; Real denthalpy_dp = fsp[1].denthalpy_dp; Real denthalpy_dT = fsp[1].denthalpy_dT; Real denthalpy_dZ = fsp[1].denthalpy_dZ; const Real dp = 1.0e-1; _fp->gasProperties(p + dp, T, fsp); Real rho1 = fsp[1].density; Real mu1 = fsp[1].viscosity; Real h1 = fsp[1].enthalpy; _fp->gasProperties(p - dp, T, fsp); Real rho2 = fsp[1].density; Real mu2 = fsp[1].viscosity; Real h2 = fsp[1].enthalpy; REL_TEST(ddensity_dp, (rho1 - rho2) / (2.0 * dp), 1.0e-6); REL_TEST(dviscosity_dp, (mu1 - mu2) / (2.0 * dp), 1.0e-6); REL_TEST(denthalpy_dp, (h1 - h2) / (2.0 * dp), 1.0e-6); const Real dT = 1.0e-3; _fp->gasProperties(p, T + dT, fsp); rho1 = fsp[1].density; mu1 = fsp[1].viscosity; h1 = fsp[1].enthalpy; _fp->gasProperties(p, T - dT, fsp); rho2 = fsp[1].density; mu2 = fsp[1].viscosity; h2 = fsp[1].enthalpy; REL_TEST(ddensity_dT, (rho1 - rho2) / (2.0 * dT), 1.0e-6); REL_TEST(dviscosity_dT, (mu1 - mu2) / (2.0 * dT), 1.0e-6); REL_TEST(denthalpy_dT, (h1 - h2) / (2.0 * dT), 1.0e-6); // Note: mass fraction changes with Z const Real dZ = 1.0e-8; _fp->massFractions(p, T, Z + dZ, phase_state, fsp); _fp->gasProperties(p, T, fsp); rho1 = fsp[1].density; mu1 = fsp[1].viscosity; h1 = fsp[1].enthalpy; _fp->massFractions(p, T, Z - dZ, phase_state, fsp); _fp->gasProperties(p, T, fsp); rho2 = fsp[1].density; mu2 = fsp[1].viscosity; h2 = fsp[1].enthalpy; REL_TEST(ddensity_dZ, (rho1 - rho2) / (2.0 * dZ), 1.0e-6); REL_TEST(dviscosity_dZ, (mu1 - mu2) / (2.0 * dZ), 1.0e-6); REL_TEST(denthalpy_dZ, (h1 - h2) / (2.0 * dZ), 1.0e-6); // Check derivatives in the two phase region as well. Note that the mass fractions // vary with pressure and temperature in this region Z = 0.45; _fp->massFractions(p, T, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::TWOPHASE); _fp->gasProperties(p, T, fsp); ddensity_dp = fsp[1].ddensity_dp; ddensity_dT = fsp[1].ddensity_dT; ddensity_dZ = fsp[1].ddensity_dZ; dviscosity_dp = fsp[1].dviscosity_dp; dviscosity_dT = fsp[1].dviscosity_dT; dviscosity_dZ = fsp[1].dviscosity_dZ; denthalpy_dp = fsp[1].denthalpy_dp; denthalpy_dT = fsp[1].denthalpy_dT; denthalpy_dZ = fsp[1].denthalpy_dZ; _fp->massFractions(p + dp, T, Z, phase_state, fsp); _fp->gasProperties(p + dp, T, fsp); rho1 = fsp[1].density; mu1 = fsp[1].viscosity; h1 = fsp[1].enthalpy; _fp->massFractions(p - dp, T, Z, phase_state, fsp); _fp->gasProperties(p - dp, T, fsp); rho2 = fsp[1].density; mu2 = fsp[1].viscosity; h2 = fsp[1].enthalpy; REL_TEST(ddensity_dp, (rho1 - rho2) / (2.0 * dp), 1.0e-6); REL_TEST(dviscosity_dp, (mu1 - mu2) / (2.0 * dp), 1.0e-6); REL_TEST(denthalpy_dp, (h1 - h2) / (2.0 * dp), 1.0e-6); _fp->massFractions(p, T + dT, Z, phase_state, fsp); _fp->gasProperties(p, T + dT, fsp); rho1 = fsp[1].density; mu1 = fsp[1].viscosity; h1 = fsp[1].enthalpy; _fp->massFractions(p, T - dT, Z, phase_state, fsp); _fp->gasProperties(p, T - dT, fsp); rho2 = fsp[1].density; mu2 = fsp[1].viscosity; h2 = fsp[1].enthalpy; REL_TEST(ddensity_dT, (rho1 - rho2) / (2.0 * dT), 1.0e-6); REL_TEST(dviscosity_dT, (mu1 - mu2) / (2.0 * dT), 1.0e-6); REL_TEST(denthalpy_dT, (h1 - h2) / (2.0 * dT), 1.0e-6); _fp->massFractions(p, T, Z + dZ, phase_state, fsp); _fp->gasProperties(p, T, fsp); rho1 = fsp[1].density; mu1 = fsp[1].viscosity; h1 = fsp[1].enthalpy; _fp->massFractions(p, T, Z - dZ, phase_state, fsp); _fp->gasProperties(p, T, fsp); rho2 = fsp[1].density; mu2 = fsp[1].viscosity; h2 = fsp[1].enthalpy; ABS_TEST(ddensity_dZ, (rho1 - rho2) / (2.0 * dZ), 1.0e-6); ABS_TEST(dviscosity_dT, (mu1 - mu2) / (2.0 * dZ), 1.0e-6); ABS_TEST(denthalpy_dZ, (h1 - h2) / (2.0 * dZ), 1.0e-6); }
/* * Verify calculation of liquid density, viscosity, enthalpy, and derivatives */ TEST_F(PorousFlowBrineCO2Test, liquidProperties) { const Real p = 1.0e6; const Real T = 350.0; const Real Xnacl = 0.1; FluidStatePhaseEnum phase_state; const unsigned int np = _fp->numPhases(); const unsigned int nc = _fp->numComponents(); std::vector<FluidStateProperties> fsp(np, FluidStateProperties(nc)); // Liquid region Real Z = 0.0001; _fp->massFractions(p, T, Xnacl, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::LIQUID); // Verify fluid density and viscosity _fp->liquidProperties(p, T, Xnacl, fsp); Real liquid_density = fsp[0].density; Real liquid_viscosity = fsp[0].viscosity; Real liquid_enthalpy = fsp[0].enthalpy; Real co2_partial_density, dco2_partial_density_dT; _fp->partialDensityCO2(T, co2_partial_density, dco2_partial_density_dT); Real brine_density = _brine_fp->rho(p, T, Xnacl); Real density = 1.0 / (Z / co2_partial_density + (1.0 - Z) / brine_density); Real viscosity = _brine_fp->mu(p, T, Xnacl); Real brine_enthalpy = _brine_fp->h(p, T, Xnacl); Real hdis, dhdis_dT; _fp->enthalpyOfDissolution(T, hdis, dhdis_dT); Real co2_enthalpy = _co2_fp->h(p, T); Real enthalpy = (1.0 - Z) * brine_enthalpy + Z * (co2_enthalpy + hdis); ABS_TEST(liquid_density, density, 1.0e-12); ABS_TEST(liquid_viscosity, viscosity, 1.0e-12); ABS_TEST(liquid_enthalpy, enthalpy, 1.0e-12); // Verify fluid density and viscosity derivatives Real ddensity_dp = fsp[0].ddensity_dp; Real ddensity_dT = fsp[0].ddensity_dT; Real ddensity_dZ = fsp[0].ddensity_dZ; Real ddensity_dX = fsp[0].ddensity_dX; Real dviscosity_dp = fsp[0].dviscosity_dp; Real dviscosity_dT = fsp[0].dviscosity_dT; Real dviscosity_dZ = fsp[0].dviscosity_dZ; Real dviscosity_dX = fsp[0].dviscosity_dX; Real denthalpy_dp = fsp[0].denthalpy_dp; Real denthalpy_dT = fsp[0].denthalpy_dT; Real denthalpy_dZ = fsp[0].denthalpy_dZ; Real denthalpy_dX = fsp[0].denthalpy_dX; // Derivatives wrt pressure const Real dp = 1.0; _fp->liquidProperties(p + dp, T, Xnacl, fsp); Real rho1 = fsp[0].density; Real mu1 = fsp[0].viscosity; Real h1 = fsp[0].enthalpy; _fp->liquidProperties(p - dp, T, Xnacl, fsp); Real rho2 = fsp[0].density; Real mu2 = fsp[0].viscosity; Real h2 = fsp[0].enthalpy; REL_TEST(ddensity_dp, (rho1 - rho2) / (2.0 * dp), 1.0e-4); REL_TEST(dviscosity_dp, (mu1 - mu2) / (2.0 * dp), 1.0e-5); REL_TEST(denthalpy_dp, (h1 - h2) / (2.0 * dp), 1.0e-4); // Derivatives wrt temperature const Real dT = 1.0e-4; _fp->liquidProperties(p, T + dT, Xnacl, fsp); rho1 = fsp[0].density; mu1 = fsp[0].viscosity; h1 = fsp[0].enthalpy; _fp->liquidProperties(p, T - dT, Xnacl, fsp); rho2 = fsp[0].density; mu2 = fsp[0].viscosity; h2 = fsp[0].enthalpy; REL_TEST(ddensity_dT, (rho1 - rho2) / (2.0 * dT), 1.0e-6); REL_TEST(dviscosity_dT, (mu1 - mu2) / (2.0 * dT), 1.0e-6); REL_TEST(denthalpy_dT, (h1 - h2) / (2.0 * dT), 1.0e-6); // Derivatives wrt Xnacl const Real dx = 1.0e-8; _fp->liquidProperties(p, T, Xnacl + dx, fsp); rho1 = fsp[0].density; mu1 = fsp[0].viscosity; h1 = fsp[0].enthalpy; _fp->liquidProperties(p, T, Xnacl - dx, fsp); rho2 = fsp[0].density; mu2 = fsp[0].viscosity; h2 = fsp[0].enthalpy; REL_TEST(ddensity_dX, (rho1 - rho2) / (2.0 * dx), 1.0e-6); REL_TEST(dviscosity_dX, (mu1 - mu2) / (2.0 * dx), 1.0e-6); REL_TEST(denthalpy_dX, (h1 - h2) / (2.0 * dx), 1.0e-6); // Derivatives wrt Z const Real dZ = 1.0e-8; _fp->massFractions(p, T, Xnacl, Z + dZ, phase_state, fsp); _fp->liquidProperties(p, T, Xnacl, fsp); rho1 = fsp[0].density; mu1 = fsp[0].viscosity; h1 = fsp[0].enthalpy; _fp->massFractions(p, T, Xnacl, Z - dZ, phase_state, fsp); _fp->liquidProperties(p, T, Xnacl, fsp); rho2 = fsp[0].density; mu2 = fsp[0].viscosity; h2 = fsp[0].enthalpy; REL_TEST(ddensity_dZ, (rho1 - rho2) / (2.0 * dZ), 1.0e-6); ABS_TEST(dviscosity_dZ, (mu1 - mu2) / (2.0 * dZ), 1.0e-6); REL_TEST(denthalpy_dZ, (h1 - h2) / (2.0 * dZ), 1.0e-6); // Two-phase region Z = 0.045; _fp->massFractions(p, T, Xnacl, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::TWOPHASE); // Verify fluid density and viscosity derivatives _fp->liquidProperties(p, T, Xnacl, fsp); ddensity_dp = fsp[0].ddensity_dp; ddensity_dT = fsp[0].ddensity_dT; ddensity_dX = fsp[0].ddensity_dX; ddensity_dZ = fsp[0].ddensity_dZ; dviscosity_dp = fsp[0].dviscosity_dp; dviscosity_dT = fsp[0].dviscosity_dT; dviscosity_dX = fsp[0].dviscosity_dX; dviscosity_dZ = fsp[0].dviscosity_dZ; denthalpy_dp = fsp[0].denthalpy_dp; denthalpy_dT = fsp[0].denthalpy_dT; denthalpy_dZ = fsp[0].denthalpy_dZ; denthalpy_dX = fsp[0].denthalpy_dX; // Derivatives wrt pressure _fp->massFractions(p + dp, T, Xnacl, Z, phase_state, fsp); _fp->liquidProperties(p + dp, T, Xnacl, fsp); rho1 = fsp[0].density; mu1 = fsp[0].viscosity; h1 = fsp[0].enthalpy; _fp->massFractions(p - dp, T, Xnacl, Z, phase_state, fsp); _fp->liquidProperties(p - dp, T, Xnacl, fsp); rho2 = fsp[0].density; mu2 = fsp[0].viscosity; h2 = fsp[0].enthalpy; REL_TEST(ddensity_dp, (rho1 - rho2) / (2.0 * dp), 1.0e-4); REL_TEST(dviscosity_dp, (mu1 - mu2) / (2.0 * dp), 1.0e-5); REL_TEST(denthalpy_dp, (h1 - h2) / (2.0 * dp), 1.0e-4); // Derivatives wrt temperature _fp->massFractions(p, T + dT, Xnacl, Z, phase_state, fsp); _fp->liquidProperties(p, T + dT, Xnacl, fsp); rho1 = fsp[0].density; mu1 = fsp[0].viscosity; h1 = fsp[0].enthalpy; _fp->massFractions(p, T - dT, Xnacl, Z, phase_state, fsp); _fp->liquidProperties(p, T - dT, Xnacl, fsp); rho2 = fsp[0].density; mu2 = fsp[0].viscosity; h2 = fsp[0].enthalpy; REL_TEST(ddensity_dT, (rho1 - rho2) / (2.0 * dT), 1.0e-6); REL_TEST(dviscosity_dT, (mu1 - mu2) / (2.0 * dT), 1.0e-6); REL_TEST(denthalpy_dT, (h1 - h2) / (2.0 * dT), 1.0e-6); // Derivatives wrt Xnacl _fp->massFractions(p, T, Xnacl + dx, Z, phase_state, fsp); _fp->liquidProperties(p, T, Xnacl + dx, fsp); rho1 = fsp[0].density; mu1 = fsp[0].viscosity; h1 = fsp[0].enthalpy; _fp->massFractions(p, T, Xnacl - dx, Z, phase_state, fsp); _fp->liquidProperties(p, T, Xnacl - dx, fsp); rho2 = fsp[0].density; mu2 = fsp[0].viscosity; h2 = fsp[0].enthalpy; REL_TEST(ddensity_dX, (rho1 - rho2) / (2.0 * dx), 1.0e-6); REL_TEST(dviscosity_dX, (mu1 - mu2) / (2.0 * dx), 1.0e-6); REL_TEST(denthalpy_dX, (h1 - h2) / (2.0 * dx), 1.0e-6); // Derivatives wrt Z _fp->massFractions(p, T, Xnacl, Z + dZ, phase_state, fsp); _fp->liquidProperties(p, T, Xnacl, fsp); rho1 = fsp[0].density; mu1 = fsp[0].viscosity; h1 = fsp[0].enthalpy; _fp->massFractions(p, T, Xnacl, Z - dZ, phase_state, fsp); _fp->liquidProperties(p, T, Xnacl, fsp); rho2 = fsp[0].density; mu2 = fsp[0].viscosity; h2 = fsp[0].enthalpy; ABS_TEST(ddensity_dZ, (rho1 - rho2) / (2.0 * dZ), 1.0e-6); ABS_TEST(dviscosity_dZ, (mu1 - mu2) / (2.0 * dZ), 1.0e-6); ABS_TEST(denthalpy_dZ, (h1 - h2) / (2.0 * dZ), 1.0e-6); }
/* * Verify calculation of gas density, viscosity enthalpy, and derivatives. Note that as * these properties don't depend on mass fraction, only the gas region needs to be * tested (the calculations are identical in the two phase region) */ TEST_F(PorousFlowBrineCO2Test, gasProperties) { const Real p = 1.0e6; const Real T = 350.0; const Real Xnacl = 0.1; FluidStatePhaseEnum phase_state; const unsigned int np = _fp->numPhases(); const unsigned int nc = _fp->numComponents(); std::vector<FluidStateProperties> fsp(np, FluidStateProperties(nc)); // Gas region Real Z = 0.995; _fp->massFractions(p, T, Xnacl, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::GAS); // Verify fluid density, viscosity and enthalpy _fp->gasProperties(p, T, fsp); Real gas_density = fsp[1].density; Real gas_viscosity = fsp[1].viscosity; Real gas_enthalpy = fsp[1].enthalpy; Real density = _co2_fp->rho(p, T); Real viscosity = _co2_fp->mu(p, T); Real enthalpy = _co2_fp->h(p, T); ABS_TEST(gas_density, density, 1.0e-8); ABS_TEST(gas_viscosity, viscosity, 1.0e-8); ABS_TEST(gas_enthalpy, enthalpy, 1.0e-8); // Verify derivatives Real ddensity_dp = fsp[1].ddensity_dp; Real ddensity_dT = fsp[1].ddensity_dT; Real ddensity_dZ = fsp[1].ddensity_dZ; Real dviscosity_dp = fsp[1].dviscosity_dp; Real dviscosity_dT = fsp[1].dviscosity_dT; Real dviscosity_dZ = fsp[1].dviscosity_dZ; Real denthalpy_dp = fsp[1].denthalpy_dp; Real denthalpy_dT = fsp[1].denthalpy_dT; Real denthalpy_dZ = fsp[1].denthalpy_dZ; const Real dp = 1.0e-1; _fp->gasProperties(p + dp, T, fsp); Real rho1 = fsp[1].density; Real mu1 = fsp[1].viscosity; Real h1 = fsp[1].enthalpy; _fp->gasProperties(p - dp, T, fsp); Real rho2 = fsp[1].density; Real mu2 = fsp[1].viscosity; Real h2 = fsp[1].enthalpy; REL_TEST(ddensity_dp, (rho1 - rho2) / (2.0 * dp), 1.0e-6); REL_TEST(dviscosity_dp, (mu1 - mu2) / (2.0 * dp), 1.0e-6); REL_TEST(denthalpy_dp, (h1 - h2) / (2.0 * dp), 1.0e-6); const Real dT = 1.0e-3; _fp->gasProperties(p, T + dT, fsp); rho1 = fsp[1].density; mu1 = fsp[1].viscosity; h1 = fsp[1].enthalpy; _fp->gasProperties(p, T - dT, fsp); rho2 = fsp[1].density; mu2 = fsp[1].viscosity; h2 = fsp[1].enthalpy; REL_TEST(ddensity_dT, (rho1 - rho2) / (2.0 * dT), 1.0e-6); REL_TEST(dviscosity_dT, (mu1 - mu2) / (2.0 * dT), 1.0e-6); REL_TEST(denthalpy_dT, (h1 - h2) / (2.0 * dT), 1.0e-6); // Note: mass fraction changes with Z const Real dZ = 1.0e-8; _fp->massFractions(p, T, Xnacl, Z + dZ, phase_state, fsp); _fp->gasProperties(p, T, fsp); rho1 = fsp[1].density; mu1 = fsp[1].viscosity; h1 = fsp[1].enthalpy; _fp->massFractions(p, T, Xnacl, Z - dZ, phase_state, fsp); _fp->gasProperties(p, T, fsp); rho2 = fsp[1].density; mu2 = fsp[1].viscosity; h2 = fsp[1].enthalpy; ABS_TEST(ddensity_dZ, (rho1 - rho2) / (2.0 * dZ), 1.0e-8); ABS_TEST(dviscosity_dZ, (mu1 - mu2) / (2.0 * dZ), 1.0e-8); ABS_TEST(denthalpy_dZ, (h1 - h2) / (2.0 * dZ), 1.0e-6); }
/* * Verify calculation of actual mass fraction and derivatives depending on value of * total mass fraction */ TEST_F(PorousFlowBrineCO2Test, MassFraction) { const Real p = 1.0e6; const Real T = 350.0; const Real Xnacl = 0.1; FluidStatePhaseEnum phase_state; const unsigned int np = _fp->numPhases(); const unsigned int nc = _fp->numComponents(); std::vector<FluidStateProperties> fsp(np, FluidStateProperties(nc)); // Liquid region Real Z = 0.0001; _fp->massFractions(p, T, Xnacl, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::LIQUID); // Verfify mass fraction values Real Xco2 = fsp[0].mass_fraction[1]; Real Yco2 = fsp[1].mass_fraction[1]; Real Xh2o = fsp[0].mass_fraction[0]; Real Yh2o = fsp[1].mass_fraction[0]; Real Xnacl2 = fsp[0].mass_fraction[2]; ABS_TEST(Xco2, Z, 1.0e-8); ABS_TEST(Yco2, 0.0, 1.0e-8); ABS_TEST(Xh2o, 1.0 - Z, 1.0e-8); ABS_TEST(Yh2o, 0.0, 1.0e-8); ABS_TEST(Xnacl2, Xnacl, 1.0e-8); // Verify derivatives Real dXco2_dp = fsp[0].dmass_fraction_dp[1]; Real dXco2_dT = fsp[0].dmass_fraction_dT[1]; Real dXco2_dX = fsp[0].dmass_fraction_dX[1]; Real dXco2_dZ = fsp[0].dmass_fraction_dZ[1]; Real dYco2_dp = fsp[1].dmass_fraction_dp[1]; Real dYco2_dT = fsp[1].dmass_fraction_dT[1]; Real dYco2_dX = fsp[1].dmass_fraction_dX[1]; Real dYco2_dZ = fsp[1].dmass_fraction_dZ[1]; Real dXnacl_dX = fsp[0].dmass_fraction_dX[2]; ABS_TEST(dXco2_dp, 0.0, 1.0e-8); ABS_TEST(dXco2_dT, 0.0, 1.0e-8); ABS_TEST(dXco2_dX, 0.0, 1.0e-8); ABS_TEST(dXco2_dZ, 1.0, 1.0e-8); ABS_TEST(dYco2_dp, 0.0, 1.0e-8); ABS_TEST(dYco2_dT, 0.0, 1.0e-8); ABS_TEST(dYco2_dX, 0.0, 1.0e-8); ABS_TEST(dYco2_dZ, 0.0, 1.0e-8); ABS_TEST(dXnacl_dX, 1.0, 1.0e-8); // Gas region Z = 0.995; _fp->massFractions(p, T, Xnacl, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::GAS); // Verfify mass fraction values Xco2 = fsp[0].mass_fraction[1]; Yco2 = fsp[1].mass_fraction[1]; Xh2o = fsp[0].mass_fraction[0]; Yh2o = fsp[1].mass_fraction[0]; Real Ynacl = fsp[1].mass_fraction[2]; ABS_TEST(Xco2, 0.0, 1.0e-8); ABS_TEST(Yco2, Z, 1.0e-8); ABS_TEST(Xh2o, 0.0, 1.0e-8); ABS_TEST(Yh2o, 1.0 - Z, 1.0e-8); ABS_TEST(Ynacl, 0.0, 1.0e-8); // Verify derivatives dXco2_dp = fsp[0].dmass_fraction_dp[1]; dXco2_dT = fsp[0].dmass_fraction_dT[1]; dXco2_dX = fsp[0].dmass_fraction_dX[1]; dXco2_dZ = fsp[0].dmass_fraction_dZ[1]; dYco2_dp = fsp[1].dmass_fraction_dp[1]; dYco2_dT = fsp[1].dmass_fraction_dT[1]; dYco2_dX = fsp[1].dmass_fraction_dX[1]; dYco2_dZ = fsp[1].dmass_fraction_dZ[1]; Real dYnacl_dX = fsp[1].dmass_fraction_dX[2]; ABS_TEST(dXco2_dp, 0.0, 1.0e-8); ABS_TEST(dXco2_dT, 0.0, 1.0e-8); ABS_TEST(dXco2_dX, 0.0, 1.0e-8); ABS_TEST(dXco2_dZ, 0.0, 1.0e-8); ABS_TEST(dYco2_dp, 0.0, 1.0e-8); ABS_TEST(dYco2_dT, 0.0, 1.0e-8); ABS_TEST(dYco2_dX, 0.0, 1.0e-8); ABS_TEST(dYnacl_dX, 0.0, 1.0e-8); ABS_TEST(dYco2_dX, 0.0, 1.0e-8); // Two phase region. In this region, the mass fractions and derivatives can // be verified using the equilibrium mass fraction derivatives that have // been verified above Z = 0.45; _fp->massFractions(p, T, Xnacl, Z, phase_state, fsp); EXPECT_EQ(phase_state, FluidStatePhaseEnum::TWOPHASE); // Equilibrium mass fractions and derivatives Real Xco2_eq, dXco2_dp_eq, dXco2_dT_eq, dXco2_dX_eq, Yh2o_eq, dYh2o_dp_eq, dYh2o_dT_eq, dYh2o_dX_eq; _fp->equilibriumMassFractions(p, T, Xnacl, Xco2_eq, dXco2_dp_eq, dXco2_dT_eq, dXco2_dX_eq, Yh2o_eq, dYh2o_dp_eq, dYh2o_dT_eq, dYh2o_dX_eq); // Verfify mass fraction values Xco2 = fsp[0].mass_fraction[1]; Yco2 = fsp[1].mass_fraction[1]; Xh2o = fsp[0].mass_fraction[0]; Yh2o = fsp[1].mass_fraction[0]; ABS_TEST(Xco2, Xco2_eq, 1.0e-8); ABS_TEST(Yco2, 1.0 - Yh2o_eq, 1.0e-8); ABS_TEST(Xh2o, 1.0 - Xco2_eq, 1.0e-8); ABS_TEST(Yh2o, Yh2o_eq, 1.0e-8); // Verify derivatives wrt p, T dXco2_dp = fsp[0].dmass_fraction_dp[1]; dXco2_dT = fsp[0].dmass_fraction_dT[1]; dXco2_dX = fsp[0].dmass_fraction_dX[1]; dXco2_dZ = fsp[0].dmass_fraction_dZ[1]; dYco2_dp = fsp[1].dmass_fraction_dp[1]; dYco2_dT = fsp[1].dmass_fraction_dT[1]; dYco2_dX = fsp[1].dmass_fraction_dX[1]; dYco2_dZ = fsp[1].dmass_fraction_dZ[1]; ABS_TEST(dXco2_dp, dXco2_dp_eq, 1.0e-8); ABS_TEST(dXco2_dT, dXco2_dT_eq, 1.0e-8); ABS_TEST(dXco2_dX, dXco2_dX_eq, 1.0e-8); ABS_TEST(dXco2_dZ, 0.0, 1.0e-8); ABS_TEST(dYco2_dp, -dYh2o_dp_eq, 1.0e-8); ABS_TEST(dYco2_dT, -dYh2o_dT_eq, 1.0e-8); ABS_TEST(dYco2_dX, -dYh2o_dX_eq, 1.0e-8); ABS_TEST(dYco2_dZ, 0.0, 1.0e-8); // Use finite differences to verify derivative wrt Z is unaffected by Z const Real dZ = 1.0e-8; _fp->massFractions(p, T, Xnacl, Z + dZ, phase_state, fsp); Real Xco21 = fsp[0].mass_fraction[1]; Real Yco21 = fsp[1].mass_fraction[1]; _fp->massFractions(p, T, Xnacl, Z - dZ, phase_state, fsp); Real Xco22 = fsp[0].mass_fraction[1]; Real Yco22 = fsp[1].mass_fraction[1]; ABS_TEST(dXco2_dZ, (Xco21 - Xco22) / (2.0 * dZ), 1.0e-8); ABS_TEST(dYco2_dZ, (Yco21 - Yco22) / (2.0 * dZ), 1.0e-8); }