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]); \
136 const Real dx_primary_dxi = -1.0; \
137 dy_dx[i] += dx_primary_dxi * y_primary - \
138 x_primary * dy_dv_primary * v / (x_primary * x_primary) * dx_primary_dxi; \
145#define define_transport_prop_from_T_v(prop) \
146 Real IdealRealGasMixtureFluidProperties::prop##_from_T_v( \
147 Real T, Real v, const std::vector<Real> & x) const \
149 const Real x_primary = primaryMassFraction(x); \
150 Real M_primary = _fp_primary->molarMass(); \
152 Real sum = x_primary / M_primary; \
153 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
154 sum += x[i] / _fp_secondary[i]->molarMass(); \
155 const Real M_star = 1. / sum; \
157 const Real vp = v / x_primary; \
158 const Real ep = _fp_primary->e_from_T_v(T, vp); \
159 const Real yp = _fp_primary->prop##_from_v_e(vp, ep); \
160 Real y = x_primary * M_star / M_primary * yp; \
162 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
164 const Real vi = v / x[i]; \
165 const Real ei = _fp_secondary[i]->e_from_T_v(T, vi); \
166 const Real Mi = _fp_secondary[i]->molarMass(); \
167 const Real yi = _fp_secondary[i]->prop##_from_v_e(vi, ei); \
168 y += x[i] * M_star / Mi * yi; \
174 void IdealRealGasMixtureFluidProperties::prop##_from_T_v(Real T, \
176 const std::vector<Real> & x, \
180 std::vector<Real> & dy_dx) const \
182 const Real x_primary = primaryMassFraction(x); \
183 Real M_primary = _fp_primary->molarMass(); \
185 Real sum = x_primary / M_primary; \
186 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
187 sum += x[i] / _fp_secondary[i]->molarMass(); \
188 const Real M_star = 1. / sum; \
190 const Real vp = v / x_primary; \
191 const Real ep = _fp_primary->e_from_T_v(T, vp); \
192 const Real yp = _fp_primary->prop##_from_v_e(vp, ep); \
193 y = x_primary * M_star / M_primary * yp; \
195 imperfectJacobianMessage("The temperature and specific volume derivatives in the following " \
196 "function are currently neglected:\n\n", \
197 __PRETTY_FUNCTION__); \
202 dy_dx.resize(_n_secondary_vapors); \
203 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
205 const Real vi = v / x[i]; \
206 const Real ei = _fp_secondary[i]->e_from_T_v(T, vi); \
207 const Real Mi = _fp_secondary[i]->molarMass(); \
208 const Real yi = _fp_secondary[i]->prop##_from_v_e(vi, ei); \
209 y += x[i] * M_star / Mi * yi; \
210 dy_dx[i] = -M_star / M_primary * yp - \
211 x_primary * (1 / Mi - 1 / M_primary) * M_star * M_star / M_primary * yp + \
213 sum_yj += x[i] * yi / Mi; \
216 for (unsigned int i = 0; i < _n_secondary_vapors; i++) \
218 const Real Mi = _fp_secondary[i]->molarMass(); \
219 dy_dx[i] += -M_star * M_star * (1 / Mi - 1 / M_primary) * sum_yj; \
227define_transport_prop_from_T_v(
mu)
228define_transport_prop_from_T_v(k)
230define_from_p_T_using_T_v(e)
231define_from_p_T_using_T_v(s)
232define_from_p_T_using_T_v(
c)
233define_from_p_T_using_T_v(cp)
234define_from_p_T_using_T_v(cv)
235define_from_p_T_using_T_v(
mu)
236define_from_p_T_using_T_v(k)
238define_from_v_e_using_T_v(
p)
239define_from_v_e_using_T_v(
c)
250 "fp_primary",
"Name of fluid properties user object for primary vapor component");
252 "fp_secondary",
"Name of fluid properties user object(s) for secondary vapor component(s)");
253 params.
addParam<Real>(
"_T_mix_max", 1300.,
"Maximum temperature of the mixture");
264 _fp_secondary_names(getParam<
std::vector<UserObjectName>>(
"fp_secondary")),
265 _n_secondary_vapors(_fp_secondary_names.size()),
266 _T_mix_max(getParam<Real>(
"T_mix_max"))
282 mooseAssert(i < getNumberOfSecondaryVapors(),
"Requested secondary index too high.");
287IdealRealGasMixtureFluidProperties::T_from_v_e(Real
v, Real e,
const std::vector<Real> &
x)
const
294 Real lower_temperature, upper_temperature;
298 lower_temperature =
_fp_primary->T_from_v_e(v_primary, e_sat_primary);
301 lower_temperature =
_fp_primary->T_from_v_e(v_primary, ec);
306 auto energy_diff = [&
v, &e, &
x,
this](
Real T) {
return this->e_from_T_v(
T,
v,
x) - e; };
313IdealRealGasMixtureFluidProperties::T_from_v_e(Real
v,
315 const std::vector<Real> &
x,
319 std::vector<Real> & dT_dx)
const
321 T = T_from_v_e(
v, e,
x);
323 Real e_unused, de_dT_v, de_dv_T;
324 std::vector<Real> de_dx_Tv;
325 e_from_T_v(
T,
v,
x, e_unused, de_dT_v, de_dv_T, de_dx_Tv);
327 dT_dv = -de_dv_T / de_dT_v;
328 dT_de = 1.0 / de_dT_v;
331 dT_dx[i] = -de_dx_Tv[i] / de_dT_v;
335IdealRealGasMixtureFluidProperties::rho_from_p_T(Real
p, Real
T,
const std::vector<Real> &
x)
const
337 return 1.0 / v_from_p_T(
p,
T,
x);
341IdealRealGasMixtureFluidProperties::rho_from_p_T(Real
p,
343 const std::vector<Real> &
x,
347 std::vector<Real> & drho_dx)
const
349 Real v, dv_dp, dv_dT;
350 std::vector<Real> dv_dx;
351 v_from_p_T(
p,
T,
x,
v, dv_dp, dv_dT, dv_dx);
354 const Real drho_dv = -1.0 / (
v *
v);
355 drho_dp = drho_dv * dv_dp;
356 drho_dT = drho_dv * dv_dT;
359 drho_dx[i] = drho_dv * dv_dx[i];
363IdealRealGasMixtureFluidProperties::v_from_p_T(Real
p, Real
T,
const std::vector<Real> &
x)
const
368 Real sum = x_primary / M_primary;
371 Real M_star = 1. / sum;
377 Real v_spndl, e_spndl;
383 Real lower_spec_volume = v_spndl * x_primary;
384 Real upper_spec_volume = v_ideal;
387 Real p_max = p_from_T_v(
T, lower_spec_volume,
x);
388 if (
p > p_max || upper_spec_volume < lower_spec_volume)
392 auto pressure_diff = [&
T, &
p, &
x,
this](
Real v) {
return this->p_from_T_v(
T,
v,
x) -
p; };
399IdealRealGasMixtureFluidProperties::v_from_p_T(Real
p,
401 const std::vector<Real> &
x,
405 std::vector<Real> & dv_dx)
const
407 v = v_from_p_T(
p,
T,
x);
409 Real p_unused, dp_dT, dp_dv;
410 std::vector<Real> dp_dx;
411 p_from_T_v(
T,
v,
x, p_unused, dp_dT, dp_dv, dp_dx);
414 dv_dT = -dp_dT / dp_dv;
417 dv_dx[i] = -dp_dx[i] / dp_dv;
421IdealRealGasMixtureFluidProperties::e_from_p_rho(Real
p,
423 const std::vector<Real> &
x)
const
428 return e_from_T_v(
T,
v,
x);
432IdealRealGasMixtureFluidProperties::e_from_p_rho(Real
p,
434 const std::vector<Real> &
x,
438 std::vector<Real> & de_dx)
const
442 Real p_, dp_dT, dp_dv, de_dT, de_dv;
443 std::vector<Real> dp_dx_Tv;
444 std::vector<Real> de_dx_Tv;
446 p_from_T_v(
T,
v,
x, p_, dp_dT, dp_dv, dp_dx_Tv);
447 e_from_T_v(
T,
v,
x, e, de_dT, de_dv, de_dx_Tv);
449 de_dp = de_dT / dp_dT;
450 de_drho = (-
v *
v) * (de_dv - de_dT * dp_dv / dp_dT);
455 de_dx[i] = de_dx_Tv[i] - de_dT * dp_dx_Tv[i] / dp_dT;
460IdealRealGasMixtureFluidProperties::T_from_p_v(Real
p, Real
v,
const std::vector<Real> &
x)
const
467 Real lower_temperature, upper_temperature;
471 lower_temperature =
_fp_primary->T_from_v_e(v_primary, e_sat_primary);
474 lower_temperature =
_fp_primary->T_from_v_e(v_primary, ec);
479 auto pressure_diff = [&
p, &
v, &
x,
this](
Real T) {
return this->p_from_T_v(
T,
v,
x) -
p; };
486IdealRealGasMixtureFluidProperties::T_from_p_v(Real
p,
488 const std::vector<Real> &
x,
492 std::vector<Real> & dT_dx)
const
494 T = T_from_p_v(
p,
v,
x);
497 Real p_unused, dp_dT_v, dp_dv_T;
498 std::vector<Real> dp_dx_Tv;
499 p_from_T_v(
T,
v,
x, p_unused, dp_dT_v, dp_dv_T, dp_dx_Tv);
502 dT_dp = 1. / dp_dT_v;
503 dT_dv = -dp_dv_T / dp_dT_v;
507 dT_dx[i] = -dp_dx_Tv[i] / dp_dT_v;
511IdealRealGasMixtureFluidProperties::p_from_T_v(Real
T, Real
v,
const std::vector<Real> &
x)
const
523IdealRealGasMixtureFluidProperties::p_from_T_v(Real
T,
525 const std::vector<Real> &
x,
529 std::vector<Real> & dp_dx)
const
533 Real p_primary, dp_dT_primary, dp_dv_primary;
534 _fp_primary->p_from_T_v(
T,
v / x_primary, p_primary, dp_dT_primary, dp_dv_primary);
536 dp_dT = dp_dT_primary;
537 dp_dv = dp_dv_primary / x_primary;
540 Real p_sec, dp_dT_sec;
547 dp_dv += dp_dv_sec[i] /
x[i];
554 dp_dx[i] = -dp_dv_sec[i] *
v / (
x[i] *
x[i]);
556 const Real dx_primary_dxi = -1.0;
557 dp_dx[i] += -dp_dv_primary *
v / (x_primary * x_primary) * dx_primary_dxi;
562IdealRealGasMixtureFluidProperties::c_from_T_v(Real
T, Real
v,
const std::vector<Real> &
x)
const
564 Real p, dp_dT, dp_dv;
565 std::vector<Real> dp_dx;
566 p_from_T_v(
T,
v,
x,
p, dp_dT, dp_dv, dp_dx);
568 Real s, ds_dT, ds_dv;
569 std::vector<Real> ds_dx;
570 s_from_T_v(
T,
v,
x, s, ds_dT, ds_dv, ds_dx);
572 const Real dp_dv_s = dp_dv - dp_dT * ds_dv / ds_dT;
575 mooseWarning(
"c_from_T_v(): dp_dv_s = ", dp_dv_s,
". Should be negative.");
576 return v * std::sqrt(-dp_dv_s);
580IdealRealGasMixtureFluidProperties::c_from_T_v(Real
T,
582 const std::vector<Real> &
x,
586 std::vector<Real> & dc_dx)
const
588 c = c_from_T_v(
T,
v,
x);
592 const Real dT = 1.e-6;
593 const Real T_perturbed =
T + dT;
594 Real c_perturbed = c_from_T_v(T_perturbed,
v,
x);
595 dc_dT = (c_perturbed -
c) / dT;
597 const Real dv =
v * 1.e-6;
598 const Real v_perturbed =
v + dv;
599 c_perturbed = c_from_T_v(
T, v_perturbed,
x);
600 dc_dv = (c_perturbed -
c) / dv;
605 std::vector<Real> x_perturbed(
x);
606 const Real dx_i = 1e-6;
611 x[j] * (1.0 - (
x[i] + dx_i)) / (1.0 -
x[i]);
613 x_perturbed[i] += dx_i;
614 c_perturbed = c_from_T_v(
T,
v, x_perturbed);
615 dc_dx[i] = ((c_perturbed -
c) / dx_i);
620IdealRealGasMixtureFluidProperties::cp_from_T_v(Real
T, Real
v,
const std::vector<Real> &
x)
const
624 Real p, dp_dT, dp_dv;
625 std::vector<Real> dp_dx;
626 p_from_T_v(
T,
v,
x,
p, dp_dT, dp_dv, dp_dx);
628 Real h, dh_dT, dh_dv;
631 const Real cp_primary = dh_dT - dh_dv / x_primary * dp_dT / dp_dv;
632 Real cp = x_primary * cp_primary;
637 const Real cp_sec = dh_dT - dh_dv /
x[i] * dp_dT / dp_dv;
645IdealRealGasMixtureFluidProperties::cp_from_T_v(Real
T,
647 const std::vector<Real> &
x,
651 std::vector<Real> & dcp_dx)
const
655 Real p, dp_dT, dp_dv;
656 std::vector<Real> dp_dx;
657 p_from_T_v(
T,
v,
x,
p, dp_dT, dp_dv, dp_dx);
659 Real h, dh_dT, dh_dv;
662 const Real cp_primary = dh_dT - dh_dv / x_primary * dp_dT / dp_dv;
663 cp = x_primary * cp_primary;
668 "function are currently neglected:\n\n",
669 __PRETTY_FUNCTION__);
677 const Real cp_sec = dh_dT - dh_dv /
x[i] * dp_dT / dp_dv;
679 dcp_dx[i] = cp_sec - cp_primary;
684IdealRealGasMixtureFluidProperties::cv_from_T_v(Real
T, Real
v,
const std::vector<Real> &
x)
const
696IdealRealGasMixtureFluidProperties::cv_from_T_v(Real
T,
698 const std::vector<Real> &
x,
702 std::vector<Real> & dcv_dx)
const
706 cv = x_primary * cv_primary;
711 "function are currently neglected:\n\n",
712 __PRETTY_FUNCTION__);
721 dcv_dx[i] = cv_sec - cv_primary;
728 const std::vector<Real> &
x)
const
747 Real pp_sat_secondary =
p - pp_sat;
759 x_sec[i] =
x[i] / (1. - x_primary);
762 Real M_star = 1. / sum;
763 v_secondary =
R_molar *
T / (M_star * pp_sat_secondary);
765 double f = 1., df_dvs, pp_sec, p_sec, dp_dT_sec, dp_dv_sec, dp_dv;
766 double tol_p = 1.e-8;
767 while (std::fabs(
f / pp_sat_secondary) > tol_p)
773 _fp_secondary[i]->p_from_T_v(
T, v_secondary / x_sec[i], p_sec, dp_dT_sec, dp_dv_sec);
775 dp_dv += dp_dv_sec / x_sec[i];
777 f = pp_sec - pp_sat_secondary;
779 v_secondary -=
f / df_dvs;
785 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