//! \brief Setup preconditioner
 //! \param[in] pre The number of pre-smoothing steps
 //! \param[in] post The number of post-smoothing steps
 //! \param[in] target The coarsening target
 //! \param[in] zcells The wanted number of cells to collapse in z per level
 //! \param[in] op The linear operator
 //! \param[in] gv The cornerpoint grid
 //! \param[out] thread Whether or not to clone for threads
 static std::shared_ptr<type>
               setup(int pre, int post, int target, int zcells,
                     std::shared_ptr<Operator>& op, const Dune::CpGrid& gv,
                     ASMHandler<Dune::CpGrid>& A, bool& copy)
 {
   typename AMG1<Smoother>::Criterion crit;
   SmootherArgs args;
   args.relaxationFactor = 1.0;
   crit.setCoarsenTarget(target);
   crit.setGamma(1);
   crit.setNoPreSmoothSteps(pre);
   crit.setNoPostSmoothSteps(post);
   crit.setDefaultValuesIsotropic(3, zcells);
   CoarsePolicy coarsePolicy(args, crit);
   TransferPolicy policy(crit);
   Dune::shared_ptr<Schwarz::type> fsp(Schwarz::setup2(op, gv, A, copy));
   copy = true;
   return std::shared_ptr<type>(new type(*op, fsp, policy, coarsePolicy, pre, post));
 }
/*
 * 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);
}
Exemple #3
0
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);
}
void IntermediateCode::updateFunction(std::string funcLabel, int funcSize) {
	FSizePair fsp(funcLabel, funcSize);
	fSize.insert( fsp );
}
/*
 * 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);
}