21#define define_from_v_e_using_T_v(prop) \
22 Real IdealRealGasMixtureFluidProperties::prop##_from_v_e( \
23 Real v, Real e, const std::vector<Real> & x) const \
25 const Real T = T_from_v_e(v, e, x); \
26 return prop##_from_T_v(T, v, x); \
29 void IdealRealGasMixtureFluidProperties::prop##_from_v_e(Real v, \
31 const std::vector<Real> & x, \
35 std::vector<Real> & dy_dx) const \
37 Real T, dT_dv_e, dT_de_v; \
38 std::vector<Real> dT_dx_ve(_n_secondary_vapors); \
39 T_from_v_e(v, e, x, T, dT_dv_e, dT_de_v, dT_dx_ve); \
41 Real dy_dT_v, dy_dv_T; \
42 std::vector<Real> dy_dx_Tv; \
43 prop##_from_T_v(T, v, x, y, dy_dT_v, dy_dv_T, dy_dx_Tv); \
45 dy_dv = dy_dv_T + dy_dT_v * dT_dv_e; \
46 dy_de = dy_dT_v * dT_de_v; \
47 dy_dx.resize(_n_secondary_vapors); \
48 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
49 dy_dx[i] = dy_dx_Tv[i] + dy_dT_v * dT_dx_ve[i]; \
56#define define_from_p_T_using_T_v(prop) \
57 Real IdealRealGasMixtureFluidProperties::prop##_from_p_T( \
58 Real p, Real T, const std::vector<Real> & x) const \
60 const Real v = v_from_p_T(p, T, x); \
61 return prop##_from_T_v(T, v, x); \
64 void IdealRealGasMixtureFluidProperties::prop##_from_p_T(Real p, \
66 const std::vector<Real> & x, \
70 std::vector<Real> & dy_dx) const \
72 Real v, dv_dp_T, dv_dT_p; \
73 std::vector<Real> dv_dx_pT; \
74 v_from_p_T(p, T, x, v, dv_dp_T, dv_dT_p, dv_dx_pT); \
76 Real dy_dT_v, dy_dv_T; \
77 std::vector<Real> dy_dx_Tv; \
78 prop##_from_T_v(T, v, x, y, dy_dT_v, dy_dv_T, dy_dx_Tv); \
80 dy_dp = dy_dv_T * dv_dp_T; \
81 dy_dT = dy_dT_v + dy_dv_T * dv_dT_p; \
82 dy_dx.resize(_n_secondary_vapors); \
83 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
84 dy_dx[i] = dy_dx_Tv[i] + dy_dv_T * dv_dx_pT[i]; \
90#define define_mass_specific_prop_from_T_v(prop) \
91 Real IdealRealGasMixtureFluidProperties::prop##_from_T_v( \
92 Real T, Real v, const std::vector<Real> & x) const \
94 const Real x_primary = primaryMassFraction(x); \
95 Real y = x_primary * _fp_primary->prop##_from_T_v(T, v / x_primary); \
97 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
98 y += x[i] * _fp_secondary[i]->prop##_from_T_v(T, v / x[i]); \
103 void IdealRealGasMixtureFluidProperties::prop##_from_T_v(Real T, \
105 const std::vector<Real> & x, \
109 std::vector<Real> & dy_dx) const \
111 const Real x_primary = primaryMassFraction(x); \
112 mooseAssert(!MooseUtils::absoluteFuzzyEqual(x_primary, 0.0), "Mass fraction may not be zero"); \
114 Real y_primary, dy_dT_primary, dy_dv_primary; \
115 _fp_primary->prop##_from_T_v(T, v / x_primary, y_primary, dy_dT_primary, dy_dv_primary); \
116 y = x_primary * y_primary; \
117 dy_dT = x_primary * dy_dT_primary; \
118 dy_dv = dy_dv_primary; \
121 std::vector<Real> y_sec(_n_secondary_vapors), dy_dv_sec(_n_secondary_vapors); \
122 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
124 mooseAssert(!MooseUtils::absoluteFuzzyEqual(x[i], 0.0), "Mass fraction may not be zero"); \
125 _fp_secondary[i]->prop##_from_T_v(T, v / x[i], y_sec[i], dy_dT_sec, dy_dv_sec[i]); \
126 y += x[i] * y_sec[i]; \
127 dy_dT += x[i] * dy_dT_sec; \
128 dy_dv += dy_dv_sec[i]; \
131 dy_dx.resize(_n_secondary_vapors); \
132 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
134 dy_dx[i] = y_sec[i] - x[i] * dy_dv_sec[i] * v / (x[i] * x[i]); \
135 for (unsigned int j = 0; j < _n_secondary_vapors; j++) \
139 if (_n_secondary_vapors > 1) \
140 imperfectJacobianMessage( \
141 "The mass fraction derivatives in the following " \
142 "function have not been tested for mixtures of 3 or more components:\n\n", \
143 __PRETTY_FUNCTION__); \
144 const Real dxj_dxi = 0; \
145 dy_dx[i] += dxj_dxi * y_sec[j] - x[j] * dy_dv_sec[j] * v / (x[j] * x[j]) * dxj_dxi; \
147 const Real dx_primary_dxi = -x_primary / (1. - x[i]); \
148 dy_dx[i] += dx_primary_dxi * y_primary - \
149 x_primary * dy_dv_primary * v / (x_primary * x_primary) * dx_primary_dxi; \
156#define define_transport_prop_from_T_v(prop) \
157 Real IdealRealGasMixtureFluidProperties::prop##_from_T_v( \
158 Real T, Real v, const std::vector<Real> & x) const \
160 const Real x_primary = primaryMassFraction(x); \
161 Real M_primary = _fp_primary->molarMass(); \
163 Real sum = x_primary / M_primary; \
164 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
165 sum += x[i] / _fp_secondary[i]->molarMass(); \
166 const Real M_star = 1. / sum; \
168 const Real vp = v / x_primary; \
169 const Real ep = _fp_primary->e_from_T_v(T, vp); \
170 const Real yp = _fp_primary->prop##_from_v_e(vp, ep); \
171 Real y = x_primary * M_star / M_primary * yp; \
173 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
175 const Real vi = v / x[i]; \
176 const Real ei = _fp_secondary[i]->e_from_T_v(T, vp); \
177 const Real Mi = _fp_secondary[i]->molarMass(); \
178 const Real yi = _fp_secondary[i]->prop##_from_v_e(vi, ei); \
179 y += x[i] * M_star / Mi * yi; \
185 void IdealRealGasMixtureFluidProperties::prop##_from_T_v(Real T, \
187 const std::vector<Real> & x, \
191 std::vector<Real> & dy_dx) const \
193 const Real x_primary = primaryMassFraction(x); \
194 Real M_primary = _fp_primary->molarMass(); \
196 Real sum = x_primary / M_primary; \
197 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
198 sum += x[i] / _fp_secondary[i]->molarMass(); \
199 const Real M_star = 1. / sum; \
201 const Real vp = v / x_primary; \
202 const Real ep = _fp_primary->e_from_T_v(T, vp); \
203 const Real yp = _fp_primary->prop##_from_v_e(vp, ep); \
204 y = x_primary * M_star / M_primary * yp; \
206 imperfectJacobianMessage("The temperature and specific volume derivatives in the following " \
207 "function are currently neglected:\n\n", \
208 __PRETTY_FUNCTION__); \
213 dy_dx.resize(_n_secondary_vapors); \
214 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
216 const Real vi = v / x[i]; \
217 const Real ei = _fp_secondary[i]->e_from_T_v(T, vi); \
218 const Real Mi = _fp_secondary[i]->molarMass(); \
219 const Real yi = _fp_secondary[i]->prop##_from_v_e(vi, ei); \
220 y += x[i] * M_star / Mi * yi; \
221 dy_dx[i] = -M_star / M_primary * yp - \
222 x_primary * (1 / Mi - 1 / M_primary) * M_star * M_star / M_primary * yp + \
224 sum_yj += x[i] * yi / Mi; \
227 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
229 const Real Mi = _fp_secondary[i]->molarMass(); \
230 dy_dx[i] += -M_star * M_star * (1 / Mi - 1 / M_primary) * sum_yj; \
238define_transport_prop_from_T_v(
mu)
239define_transport_prop_from_T_v(k)
241define_from_p_T_using_T_v(e)
242define_from_p_T_using_T_v(s)
243define_from_p_T_using_T_v(
c)
244define_from_p_T_using_T_v(cp)
245define_from_p_T_using_T_v(cv)
246define_from_p_T_using_T_v(
mu)
247define_from_p_T_using_T_v(k)
249define_from_v_e_using_T_v(
p)
250define_from_v_e_using_T_v(
c)
261 "fp_primary",
"Name of fluid properties user object for primary vapor component");
263 "fp_secondary",
"Name of fluid properties user object(s) for secondary vapor component(s)");
264 params.
addParam<Real>(
"_T_mix_max", 1300.,
"Maximum temperature of the mixture");
274 _fp_secondary_names(getParam<
std::vector<UserObjectName>>(
"fp_secondary")),
275 _n_secondary_vapors(_fp_secondary_names.size()),
276 _T_mix_max(getParam<Real>(
"_T_mix_max"))
292 mooseAssert(i < getNumberOfSecondaryVapors(),
"Requested secondary index too high.");
297IdealRealGasMixtureFluidProperties::T_from_v_e(Real
v, Real e,
const std::vector<Real> &
x)
const
304 Real lower_temperature, upper_temperature;
308 lower_temperature =
_fp_primary->T_from_v_e(v_primary, e_sat_primary);
311 lower_temperature =
_fp_primary->T_from_v_e(v_primary, ec);
316 auto energy_diff = [&
v, &e, &
x,
this](
Real T) {
return this->e_from_T_v(
T,
v,
x) - e; };
323IdealRealGasMixtureFluidProperties::T_from_v_e(Real
v,
325 const std::vector<Real> &
x,
329 std::vector<Real> & dT_dx)
const
331 T = T_from_v_e(
v, e,
x);
333 Real e_unused, de_dT_v, de_dv_T;
334 std::vector<Real> de_dx_Tv;
335 e_from_T_v(
T,
v,
x, e_unused, de_dT_v, de_dv_T, de_dx_Tv);
337 dT_dv = -de_dv_T / de_dT_v;
338 dT_de = 1.0 / de_dT_v;
341 dT_dx[i] = -de_dx_Tv[i] / de_dT_v;
345IdealRealGasMixtureFluidProperties::rho_from_p_T(Real
p, Real
T,
const std::vector<Real> &
x)
const
347 return 1.0 / v_from_p_T(
p,
T,
x);
351IdealRealGasMixtureFluidProperties::rho_from_p_T(Real
p,
353 const std::vector<Real> &
x,
357 std::vector<Real> & drho_dx)
const
359 Real v, dv_dp, dv_dT;
360 std::vector<Real> dv_dx;
361 v_from_p_T(
p,
T,
x,
v, dv_dp, dv_dT, dv_dx);
364 const Real drho_dv = -1.0 / (
v *
v);
365 drho_dp = drho_dv * dv_dp;
366 drho_dT = drho_dv * dv_dT;
369 drho_dx[i] = drho_dv * dv_dx[i];
373IdealRealGasMixtureFluidProperties::v_from_p_T(Real
p, Real
T,
const std::vector<Real> &
x)
const
378 Real sum = x_primary / M_primary;
381 Real M_star = 1. / sum;
387 Real v_spndl, e_spndl;
393 Real lower_spec_volume = v_spndl * x_primary;
394 Real upper_spec_volume = v_ideal;
397 Real p_max = p_from_T_v(
T, lower_spec_volume,
x);
398 if (
p > p_max || upper_spec_volume < lower_spec_volume)
402 auto pressure_diff = [&
T, &
p, &
x,
this](
Real v) {
return this->p_from_T_v(
T,
v,
x) -
p; };
409IdealRealGasMixtureFluidProperties::v_from_p_T(Real
p,
411 const std::vector<Real> &
x,
415 std::vector<Real> & dv_dx)
const
417 v = v_from_p_T(
p,
T,
x);
419 Real p_unused, dp_dT, dp_dv;
420 std::vector<Real> dp_dx;
421 p_from_T_v(
T,
v,
x, p_unused, dp_dT, dp_dv, dp_dx);
424 dv_dT = -dp_dT / dp_dv;
427 dv_dx[i] = -dp_dx[i] / dp_dv;
431IdealRealGasMixtureFluidProperties::e_from_p_rho(Real
p,
433 const std::vector<Real> &
x)
const
438 return e_from_T_v(
T,
v,
x);
442IdealRealGasMixtureFluidProperties::e_from_p_rho(Real
p,
444 const std::vector<Real> &
x,
448 std::vector<Real> & de_dx)
const
452 Real p_, dp_dT, dp_dv, de_dT, de_dv;
453 std::vector<Real> dp_dx_Tv;
454 std::vector<Real> de_dx_Tv;
456 p_from_T_v(
T,
v,
x, p_, dp_dT, dp_dv, dp_dx_Tv);
457 e_from_T_v(
T,
v,
x, e, de_dT, de_dv, de_dx_Tv);
459 de_dp = de_dT / dp_dT;
460 de_drho = (-
v *
v) * (de_dv - de_dT * dp_dv / dp_dT);
465 de_dx[i] = de_dx_Tv[i] - de_dT * dp_dx_Tv[i] / dp_dT;
470IdealRealGasMixtureFluidProperties::T_from_p_v(Real
p, Real
v,
const std::vector<Real> &
x)
const
477 Real lower_temperature, upper_temperature;
481 lower_temperature =
_fp_primary->T_from_v_e(v_primary, e_sat_primary);
484 lower_temperature =
_fp_primary->T_from_v_e(v_primary, ec);
489 auto pressure_diff = [&
p, &
v, &
x,
this](
Real T) {
return this->p_from_T_v(
T,
v,
x) -
p; };
496IdealRealGasMixtureFluidProperties::T_from_p_v(Real
p,
498 const std::vector<Real> &
x,
502 std::vector<Real> & dT_dx)
const
504 T = T_from_p_v(
p,
v,
x);
507 Real p_unused, dp_dT_v, dp_dv_T;
508 std::vector<Real> dp_dx_Tv;
509 p_from_T_v(
T,
v,
x, p_unused, dp_dT_v, dp_dv_T, dp_dx_Tv);
512 dT_dp = 1. / dp_dT_v;
513 dT_dv = -dp_dv_T / dp_dT_v;
517 dT_dx[i] = -dp_dx_Tv[i] / dp_dT_v;
521IdealRealGasMixtureFluidProperties::p_from_T_v(Real
T, Real
v,
const std::vector<Real> &
x)
const
533IdealRealGasMixtureFluidProperties::p_from_T_v(Real
T,
535 const std::vector<Real> &
x,
539 std::vector<Real> & dp_dx)
const
543 Real p_primary, dp_dT_primary, dp_dv_primary;
544 _fp_primary->p_from_T_v(
T,
v / x_primary, p_primary, dp_dT_primary, dp_dv_primary);
546 dp_dT = dp_dT_primary;
547 dp_dv = dp_dv_primary / x_primary;
550 Real p_sec, dp_dT_sec, dxj_dxi;
557 dp_dv += dp_dv_sec[i] /
x[i];
564 dp_dx[i] = -dp_dv_sec[i] *
v / (
x[i] *
x[i]);
575 "The mass fraction derivatives in the following "
576 "function have not been tested for mixtures of 3 or more components:\n\n",
577 __PRETTY_FUNCTION__);
579 dp_dx[i] += -dp_dv_sec[j] *
v / (
x[j] *
x[j]) * dxj_dxi;
581 dp_dx[i] += -dp_dv_primary *
v / (x_primary * x_primary) * (-x_primary / (1. -
x[i]));
586IdealRealGasMixtureFluidProperties::c_from_T_v(Real
T, Real
v,
const std::vector<Real> &
x)
const
588 Real p, dp_dT, dp_dv;
589 std::vector<Real> dp_dx;
590 p_from_T_v(
T,
v,
x,
p, dp_dT, dp_dv, dp_dx);
592 Real s, ds_dT, ds_dv;
593 std::vector<Real> ds_dx;
594 s_from_T_v(
T,
v,
x, s, ds_dT, ds_dv, ds_dx);
596 const Real dp_dv_s = dp_dv - dp_dT * ds_dv / ds_dT;
599 mooseWarning(
"c_from_T_v(): dp_dv_s = ", dp_dv_s,
". Should be negative.");
600 return v * std::sqrt(-dp_dv_s);
604IdealRealGasMixtureFluidProperties::c_from_T_v(Real
T,
606 const std::vector<Real> &
x,
610 std::vector<Real> & dc_dx)
const
612 c = c_from_T_v(
T,
v,
x);
616 const Real dT = 1.e-6;
617 const Real T_perturbed =
T + dT;
618 Real c_perturbed = c_from_T_v(T_perturbed,
v,
x);
619 dc_dT = (c_perturbed -
c) / dT;
621 const Real dv =
v * 1.e-6;
622 const Real v_perturbed =
v + dv;
623 c_perturbed = c_from_T_v(
T, v_perturbed,
x);
624 dc_dv = (c_perturbed -
c) / dv;
629 std::vector<Real> x_perturbed(
x);
630 const Real dx_i = 1e-6;
635 x[j] * (1.0 - (
x[i] + dx_i)) / (1.0 -
x[i]);
637 x_perturbed[i] += dx_i;
638 c_perturbed = c_from_T_v(
T,
v, x_perturbed);
639 dc_dx[i] = ((c_perturbed -
c) / dx_i);
644IdealRealGasMixtureFluidProperties::cp_from_T_v(Real
T, Real
v,
const std::vector<Real> &
x)
const
648 Real p, dp_dT, dp_dv;
649 std::vector<Real> dp_dx;
650 p_from_T_v(
T,
v,
x,
p, dp_dT, dp_dv, dp_dx);
652 Real h, dh_dT, dh_dv;
654 const Real cp_primary = dh_dT - dh_dv * dp_dT / dp_dv;
655 Real cp = x_primary * cp_primary;
660 const Real cp_sec = dh_dT - dh_dv * dp_dT / dp_dv;
668IdealRealGasMixtureFluidProperties::cp_from_T_v(Real
T,
670 const std::vector<Real> &
x,
674 std::vector<Real> & dcp_dx)
const
678 Real p, dp_dT, dp_dv;
679 std::vector<Real> dp_dx;
680 p_from_T_v(
T,
v,
x,
p, dp_dT, dp_dv, dp_dx);
682 Real h, dh_dT, dh_dv;
684 const Real cp_primary = dh_dT - dh_dv * dp_dT / dp_dv;
685 cp = x_primary * cp_primary;
690 "function are currently neglected:\n\n",
691 __PRETTY_FUNCTION__);
699 const Real cp_sec = dh_dT - dh_dv * dp_dT / dp_dv;
701 dcp_dx[i] = cp_sec - cp_primary;
706IdealRealGasMixtureFluidProperties::cv_from_T_v(Real
T, Real
v,
const std::vector<Real> &
x)
const
718IdealRealGasMixtureFluidProperties::cv_from_T_v(Real
T,
720 const std::vector<Real> &
x,
724 std::vector<Real> & dcv_dx)
const
728 cv = x_primary * cv_primary;
733 "function are currently neglected:\n\n",
734 __PRETTY_FUNCTION__);
743 dcv_dx[i] = cv_sec - cv_primary;
750 const std::vector<Real> &
x)
const
769 Real pp_sat_secondary =
p - pp_sat;
781 x_sec[i] =
x[i] / (1. - x_primary);
784 Real M_star = 1. / sum;
785 v_secondary =
R_molar *
T / (M_star * pp_sat_secondary);
787 double f = 1., df_dvs, pp_sec, p_sec, dp_dT_sec, dp_dv_sec, dp_dv;
788 double tol_p = 1.e-8;
789 while (std::fabs(
f / pp_sat_secondary) > tol_p)
795 _fp_secondary[i]->p_from_T_v(
T, v_secondary / x_sec[i], p_sec, dp_dT_sec, dp_dv_sec);
797 dp_dv += dp_dv_sec / x_sec[i];
799 f = pp_sec - pp_sat_secondary;
801 v_secondary -=
f / df_dvs;
807 xs = v_secondary / (v_primary + v_secondary);
Real f(Real x)
Test function for Brents method.
const std::vector< double > x
define_mass_specific_prop_from_T_v(e)
registerMooseObject("FluidPropertiesApp", IdealRealGasMixtureFluidProperties)
Class for fluid properties of an arbitrary vapor mixture.
static constexpr const Real R_molar
molar (or universal) gas constant
virtual const SinglePhaseFluidProperties & getSecondaryFluidProperties(unsigned int i=0) const override
Gets a secondary component single-phase fluid properties.
const Real _T_mix_max
maximum temperature of all components
Real xs_prim_from_p_T(Real p, Real T, const std::vector< Real > &x) const
Mass fraction of primary (condensable) component at saturation from pressure and temperature.
const unsigned int _n_secondary_vapors
Number of secondary vapors.
IdealRealGasMixtureFluidProperties(const InputParameters ¶meters)
std::vector< const SinglePhaseFluidProperties * > _fp_secondary
Secondary vapor fluid properties.
const SinglePhaseFluidProperties *const _fp_primary
Primary vapor fluid properties.
virtual const SinglePhaseFluidProperties & getPrimaryFluidProperties() const override
Gets the primary component single-phase fluid properties.
static InputParameters validParams()
const std::vector< UserObjectName > _fp_secondary_names
Names of secondary vapor fluid properties.
void mooseWarning(Args &&... args) const
Interface class for producing errors, warnings, or just quiet NaNs.
Real getNaN() const
Throws an error or returns a NaN with or without a warning, with a default message.
static InputParameters validParams()
Common class for single phase fluid properties.
virtual Real criticalInternalEnergy() const
Critical specific internal energy.
virtual void v_e_spndl_from_T(Real T, Real &v, Real &e) const
Specific internal energy from temperature and specific volume.
virtual Real e_spndl_from_v(Real v) const
Specific internal energy from temperature and specific volume.
virtual Real criticalDensity() const
Critical density.
virtual Real molarMass() const
Molar mass [kg/mol].
virtual Real criticalTemperature() const
Critical temperature.
Base class for fluid properties of vapor mixtures.
Real primaryMassFraction(const std::vector< Real > &x) const
Computes the mass fraction of the primary vapor given mass fractions of the secondary vapors.
void imperfectJacobianMessage(Args... args) const
static InputParameters validParams()
Real root(std::function< Real(Real)> const &f, Real x1, Real x2, Real tol=1.0e-12)
Finds the root of a function using Brent's method.
void bracket(std::function< Real(Real)> const &f, Real &x1, Real &x2)
Function to bracket a root of a given function.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real