void
GeneralVaporMixtureFluidProperties::p_T_from_v_e(Real v,
                                                 Real e,
                                                 std::vector<Real> x,
                                                 Real & p,
                                                 Real & dp_dv,
                                                 Real & dp_de,
                                                 std::vector<Real> & dp_dx,
                                                 Real & T,
                                                 Real & dT_dv,
                                                 Real & dT_de,
                                                 std::vector<Real> & dT_dx) const
{
  p_T_from_v_e(v, e, x, p, T);

  // specific volume residual and Jacobians from primary vapor and mixture
  Real v_unused, dv_dp, dv_dT;
  std::vector<Real> dv_dx;
  v_from_p_T(p, T, x, v_unused, dv_dp, dv_dT, dv_dx);

  // specific internal energy residual and Jacobians from primary vapor and mixture
  Real e_unused, de_dp, de_dT;
  std::vector<Real> de_dx;
  e_from_p_T(p, T, x, e_unused, de_dp, de_dT, de_dx);

  // Compute derivatives using the following rules:
  //   * Reciprocity:         da/db|_c = (db/da|_c)^{-1}
  //   * Chain rule:          da/db|_c = da/dc|_b * dc/db|_a
  //   * Triple product rule: da/db|_c * db/dc|_a * dc/da|_b = -1
  dp_dv = de_dT / (dv_dp * de_dT - dv_dT * de_dp);
  dp_de = dv_dT / (de_dp * dv_dT - de_dT * dv_dp);
  dT_dv = de_dp / (dv_dT * de_dp - dv_dp * de_dT);
  dT_de = dv_dp / (de_dT * dv_dp - de_dp * dv_dT);

  // Derivatives with respect to mass fractions are more complicated, so a
  // finite difference approximation is used (this is expensive of course).
  for (unsigned int i = 0; i < _n_secondary_vapors; ++i)
  {
    Real p_perturbed, T_perturbed;
    std::vector<Real> x_perturbed(x);
    x_perturbed[i] += 1e-6;
    p_T_from_v_e(v, e, x_perturbed, p_perturbed, T_perturbed);

    dp_dx[i] = (p_perturbed - p) / 1e-6;
    dT_dx[i] = (T_perturbed - T) / 1e-6;
  }
}
Real
IdealRealGasMixtureFluidProperties::T_from_v_e(Real v, Real e, const std::vector<Real> & x) const
{
  Real p, T;
  p_T_from_v_e(v, e, x, p, T);

  return T;
}
Real
GeneralVaporMixtureFluidProperties::T_from_v_e(Real v, Real e, std::vector<Real> x) const
{
  Real p, dp_dv, dp_de, T, dT_dv, dT_de;
  std::vector<Real> dp_dx(_n_secondary_vapors);
  std::vector<Real> dT_dx(_n_secondary_vapors);
  p_T_from_v_e(v, e, x, p, dp_dv, dp_de, dp_dx, T, dT_dv, dT_de, dT_dx);

  return T;
}
void
GeneralVaporMixtureFluidProperties::p_from_v_e(Real v,
                                               Real e,
                                               std::vector<Real> x,
                                               Real & p,
                                               Real & dp_dv,
                                               Real & dp_de,
                                               std::vector<Real> & dp_dx) const
{
  Real T, dT_dv, dT_de;
  std::vector<Real> dT_dx(_n_secondary_vapors);
  p_T_from_v_e(v, e, x, p, dp_dv, dp_de, dp_dx, T, dT_dv, dT_de, dT_dx);
}
void
IdealRealGasMixtureFluidProperties::T_from_v_e(Real v,
                                               Real e,
                                               const std::vector<Real> & x,
                                               Real & T,
                                               Real & dT_dv,
                                               Real & dT_de,
                                               std::vector<Real> & dT_dx) const
{
  Real p, dp_dv, dp_de;
  std::vector<Real> dp_dx(_n_secondary_vapors);
  p_T_from_v_e(v, e, x, p, dp_dv, dp_de, dp_dx, T, dT_dv, dT_de, dT_dx);
}
void
IdealRealGasMixtureFluidProperties::p_T_from_v_e(Real v,
                                                 Real e,
                                                 const std::vector<Real> & x,
                                                 Real & p,
                                                 Real & dp_dv,
                                                 Real & dp_de,
                                                 std::vector<Real> & dp_dx,
                                                 Real & T,
                                                 Real & dT_dv,
                                                 Real & dT_de,
                                                 std::vector<Real> & dT_dx) const
{
  p_T_from_v_e(v, e, x, p, T);

  // pressure and derivatives
  Real p_unused, dp_dT_v, dp_dv_T;
  std::vector<Real> dp_dx_Tv;
  p_from_T_v(T, v, x, p_unused, dp_dT_v, dp_dv_T, dp_dx_Tv);

  // internal energy and derivatives
  Real e_unused, de_dT_v, de_dv_T;
  std::vector<Real> de_dx_Tv;
  e_from_T_v(T, v, x, e_unused, de_dT_v, de_dv_T, de_dx_Tv);

  // Compute derivatives using the following rules:
  dp_dv = dp_dv_T - dp_dT_v * de_dv_T / de_dT_v;
  dp_de = dp_dT_v / de_dT_v;
  dT_dv = -de_dv_T / de_dT_v;
  dT_de = 1. / de_dT_v;

  // Derivatives with respect to mass fractions:
  for (unsigned int i = 0; i < _n_secondary_vapors; i++)
  {
    dT_dx[i] = -de_dx_Tv[i] / de_dT_v;
    dp_dx[i] = dp_dx_Tv[i] + dp_dT_v * dT_dx[i];
  }
}