https://mooseframework.inl.gov
IdealGasMixtureFluidProperties.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
12 
14 
18 #define define_mass_specific_prop_from_p_T(prop) \
19  Real IdealGasMixtureFluidProperties::prop##_from_p_T( \
20  Real p, Real T, const std::vector<Real> & x_secondary) const \
21  { \
22  const auto x = secondaryToAllMassFractions(x_secondary); \
23  mooseAssert(x.size() == _n_components, "Size mismatch"); \
24  \
25  Real z = 0; \
26  for (const auto i : make_range(_n_components)) \
27  z += x[i] * _component_fps[i]->prop##_from_p_T(p, T); \
28  \
29  return z; \
30  } \
31  ADReal IdealGasMixtureFluidProperties::prop##_from_p_T( \
32  const ADReal & p, const ADReal & T, const std::vector<ADReal> & x_secondary) const \
33  { \
34  const auto x = secondaryToAllMassFractions(x_secondary); \
35  mooseAssert(x.size() == _n_components, "Size mismatch"); \
36  \
37  ADReal z = 0; \
38  for (const auto i : make_range(_n_components)) \
39  z += x[i] * _component_fps[i]->prop##_from_p_T(p, T); \
40  \
41  return z; \
42  }
43 
47 #define define_transport_prop_from_p_T(prop) \
48  Real IdealGasMixtureFluidProperties::prop##_from_p_T( \
49  Real p, Real T, const std::vector<Real> & x_secondary) const \
50  { \
51  const auto x = secondaryToAllMassFractions(x_secondary); \
52  const auto psi = molarFractionsFromMassFractions(x); \
53  mooseAssert(psi.size() == _n_components, "Size mismatch"); \
54  \
55  Real y = 0; \
56  for (const auto i : make_range(_n_components)) \
57  y += psi[i] * _component_fps[i]->prop##_from_p_T(p, T); \
58  \
59  return y; \
60  } \
61  ADReal IdealGasMixtureFluidProperties::prop##_from_p_T( \
62  const ADReal & p, const ADReal & T, const std::vector<ADReal> & x_secondary) const \
63  { \
64  const auto x = secondaryToAllMassFractions(x_secondary); \
65  const auto psi = molarFractionsFromMassFractions(x); \
66  mooseAssert(psi.size() == _n_components, "Size mismatch"); \
67  \
68  ADReal y = 0; \
69  for (const auto i : make_range(_n_components)) \
70  y += psi[i] * _component_fps[i]->prop##_from_p_T(p, T); \
71  \
72  return y; \
73  }
74 
75 // clang-format off
81 
82 define_transport_prop_from_p_T(mu)
83 define_transport_prop_from_p_T(k)
84 
85 #undef define_mass_specific_prop_from_p_T
86 #undef define_transport_prop_from_p_T
87 
89 // clang-format on
90 {
92  params += NaNInterface::validParams();
93 
94  params.addClassDescription("Class for fluid properties of an ideal gas mixture");
95 
96  params.addRequiredParam<std::vector<UserObjectName>>(
97  "component_fluid_properties",
98  "Name of component fluid properties user objects. The first entry should be the primary "
99  "component.");
100 
101  return params;
102 }
103 
105  : VaporMixtureFluidProperties(parameters),
106  NaNInterface(this),
107  _component_fp_names(getParam<std::vector<UserObjectName>>("component_fluid_properties")),
108  _n_components(_component_fp_names.size()),
109  _n_secondary_components(_n_components - 1)
110 {
111  if (_n_components == 0)
112  mooseError("There must be at least one entry in 'component_fluid_properties'.");
113 
115  for (const auto i : make_range(_n_components))
116  {
117  const auto & single_phase_fp =
118  getUserObjectByName<SinglePhaseFluidProperties>(_component_fp_names[i]);
119  _component_fps[i] = dynamic_cast<const IdealGasFluidProperties *>(&single_phase_fp);
120  if (!_component_fps[i])
121  mooseError(
122  "Each entry in 'component_fluid_properties' must have type 'IdealGasFluidProperties'.");
123  }
124 }
125 
128 {
129  return *_component_fps[0];
130 }
131 
134 {
135  mooseAssert(i < getNumberOfSecondaryVapors(), "Requested secondary index too high.");
136  return *_component_fps[i + 1];
137 }
138 
139 template <typename CppType>
140 std::vector<CppType>
142  const std::vector<CppType> & x_secondary) const
143 {
144  mooseAssert(x_secondary.size() == _n_secondary_components, "Size mismatch");
145 
146  CppType sum = 0;
147  for (const auto i : make_range(_n_secondary_components))
148  sum += x_secondary[i];
149 
150  const CppType x_primary = 1.0 - sum;
151 
152  std::vector<CppType> x;
153  x.push_back(x_primary);
154  x.insert(x.end(), x_secondary.begin(), x_secondary.end());
155 
156  return x;
157 }
158 
159 std::vector<ADReal>
161  const std::vector<ADReal> & x_secondary) const
162 {
163  return secondaryToAllMassFractions_templ(x_secondary);
164 }
165 
166 std::vector<Real>
168  const std::vector<Real> & x_secondary) const
169 {
170  return secondaryToAllMassFractions_templ(x_secondary);
171 }
172 
173 template <typename CppType>
174 CppType
176 {
177  mooseAssert(x.size() == _n_components, "Size mismatch");
178 
179  CppType sum = 0;
180  for (const auto i : make_range(_n_components))
181  sum += x[i] / _component_fps[i]->molarMass();
182 
183  return 1.0 / sum;
184 }
185 
186 ADReal
187 IdealGasMixtureFluidProperties::mixtureMolarMass(const std::vector<ADReal> & x) const
188 {
189  return mixtureMolarMass_templ(x);
190 }
191 
192 Real
193 IdealGasMixtureFluidProperties::mixtureMolarMass(const std::vector<Real> & x) const
194 {
195  return mixtureMolarMass_templ(x);
196 }
197 
198 template <typename CppType>
199 CppType
201 {
202  mooseAssert(x.size() == _n_components, "Size mismatch");
203 
204  CppType cp_mix = 0, cv_mix = 0;
205  for (const auto i : make_range(_n_components))
206  {
207  // cp and cv are constant due to ideal gas assumption; any (p, T) is fine:
208  cp_mix += x[i] * _component_fps[i]->cp_from_p_T(0, 0);
209  cv_mix += x[i] * _component_fps[i]->cv_from_p_T(0, 0);
210  }
211 
212  return cp_mix / cv_mix;
213 }
214 
215 ADReal
217 {
219 }
220 
221 Real
223 {
225 }
226 
227 template <typename CppType>
228 std::vector<CppType>
230  const std::vector<CppType> & x) const
231 {
232  mooseAssert(x.size() == _n_components, "Size mismatch");
233 
234  const auto M = mixtureMolarMass(x);
235  std::vector<CppType> psi(_n_components);
236  for (const auto i : make_range(_n_components))
237  psi[i] = x[i] * M / _component_fps[i]->molarMass();
238 
239  return psi;
240 }
241 
242 std::vector<ADReal>
244 {
246 }
247 
248 std::vector<Real>
250 {
252 }
253 
254 ADReal
255 IdealGasMixtureFluidProperties::rho_from_p_T(const ADReal & p,
256  const ADReal & T,
257  const std::vector<ADReal> & x_secondary) const
258 {
259  return 1.0 / v_from_p_T(p, T, x_secondary);
260 }
261 
262 Real
263 IdealGasMixtureFluidProperties::rho_from_p_T(Real p,
264  Real T,
265  const std::vector<Real> & x_secondary) const
266 {
267  return 1.0 / v_from_p_T(p, T, x_secondary);
268 }
269 
270 template <typename CppType>
271 CppType
272 IdealGasMixtureFluidProperties::e_from_p_rho_templ(const CppType & p,
273  const CppType & rho,
274  const std::vector<CppType> & x_secondary) const
275 {
276  const auto x = secondaryToAllMassFractions(x_secondary);
277  mooseAssert(x.size() == _n_components, "Size mismatch");
278 
279  const auto M = mixtureMolarMass(x);
280 
281  CppType e_ref_sum = 0;
282  CppType cv_sum = 0;
283  for (const auto i : make_range(_n_components))
284  {
285  e_ref_sum += x[i] * _component_fps[i]->referenceSpecificInternalEnergy();
286  // cv is constant due to ideal gas assumption; any (p, T) is fine:
287  cv_sum += x[i] * _component_fps[i]->cv_from_p_T(0, 0);
288  }
289 
290  return cv_sum * M * p / (_R * rho) + e_ref_sum;
291 }
292 
293 ADReal
294 IdealGasMixtureFluidProperties::e_from_p_rho(const ADReal & p,
295  const ADReal & rho,
296  const std::vector<ADReal> & x_secondary) const
297 {
298  return e_from_p_rho_templ(p, rho, x_secondary);
299 }
300 
301 Real
302 IdealGasMixtureFluidProperties::e_from_p_rho(Real p,
303  Real rho,
304  const std::vector<Real> & x_secondary) const
305 {
306  return e_from_p_rho_templ(p, rho, x_secondary);
307 }
308 
309 template <typename CppType>
310 CppType
311 IdealGasMixtureFluidProperties::p_from_v_e_templ(const CppType & v,
312  const CppType & e,
313  const std::vector<CppType> & x_secondary) const
314 {
315  const auto x = secondaryToAllMassFractions(x_secondary);
316  const auto M = mixtureMolarMass(x);
317 
318  return _R * T_from_v_e(v, e, x_secondary) / (M * v);
319 }
320 
321 ADReal
322 IdealGasMixtureFluidProperties::p_from_v_e(const ADReal & v,
323  const ADReal & e,
324  const std::vector<ADReal> & x_secondary) const
325 {
326  return p_from_v_e_templ(v, e, x_secondary);
327 }
328 
329 Real
330 IdealGasMixtureFluidProperties::p_from_v_e(Real v,
331  Real e,
332  const std::vector<Real> & x_secondary) const
333 {
334  return p_from_v_e_templ(v, e, x_secondary);
335 }
336 
337 template <typename CppType>
338 CppType
339 IdealGasMixtureFluidProperties::T_from_v_e_templ(const CppType & /*v*/,
340  const CppType & e,
341  const std::vector<CppType> & x_secondary) const
342 {
343  const auto x = secondaryToAllMassFractions(x_secondary);
344  mooseAssert(x.size() == _n_components, "Size mismatch");
345 
346  CppType e_ref_sum = 0;
347  CppType cv_sum = 0;
348  for (const auto i : make_range(_n_components))
349  {
350  e_ref_sum += x[i] * _component_fps[i]->referenceSpecificInternalEnergy();
351  // cv is constant due to ideal gas assumption; any (p, T) is fine:
352  cv_sum += x[i] * _component_fps[i]->cv_from_p_T(0, 0);
353  }
354 
355  return (e - e_ref_sum) / cv_sum;
356 }
357 
358 ADReal
359 IdealGasMixtureFluidProperties::T_from_v_e(const ADReal & v,
360  const ADReal & e,
361  const std::vector<ADReal> & x_secondary) const
362 {
363  return T_from_v_e_templ(v, e, x_secondary);
364 }
365 
366 Real
367 IdealGasMixtureFluidProperties::T_from_v_e(Real v,
368  Real e,
369  const std::vector<Real> & x_secondary) const
370 {
371  return T_from_v_e_templ(v, e, x_secondary);
372 }
373 
374 template <typename CppType>
375 CppType
376 IdealGasMixtureFluidProperties::c_from_p_T_templ(const CppType & /*p*/,
377  const CppType & T,
378  const std::vector<CppType> & x_secondary) const
379 {
380  const auto x = secondaryToAllMassFractions(x_secondary);
381  const auto M = mixtureMolarMass(x);
382  const auto gamma = mixtureSpecificHeatRatio(x);
383 
384  return std::sqrt(gamma * _R * T / M);
385 }
386 
387 ADReal
388 IdealGasMixtureFluidProperties::c_from_p_T(const ADReal & p,
389  const ADReal & T,
390  const std::vector<ADReal> & x_secondary) const
391 {
392  return c_from_p_T_templ(p, T, x_secondary);
393 }
394 
395 Real
396 IdealGasMixtureFluidProperties::c_from_p_T(Real p,
397  Real T,
398  const std::vector<Real> & x_secondary) const
399 {
400  return c_from_p_T_templ(p, T, x_secondary);
401 }
Base class for fluid properties of vapor mixtures.
std::vector< ADReal > secondaryToAllMassFractions(const std::vector< ADReal > &x_secondary) const
static const std::string cv
Definition: NS.h:122
const unsigned int _n_secondary_components
Number of secondary components.
static const Real _R
Universal gas constant (J/mol/K)
virtual const SinglePhaseFluidProperties & getSecondaryFluidProperties(unsigned int i=0) const override
Gets a secondary component single-phase fluid properties.
DualNumber< Real, DNDerivativeType, true > ADReal
IdealGasMixtureFluidProperties(const InputParameters &parameters)
void addRequiredParam(const std::string &name, const std::string &doc_string)
registerMooseObject("FluidPropertiesApp", IdealGasMixtureFluidProperties)
static const std::string cp
Definition: NS.h:121
const std::vector< double > x
std::vector< ADReal > molarFractionsFromMassFractions(const std::vector< ADReal > &x) const
virtual const SinglePhaseFluidProperties & getPrimaryFluidProperties() const override
Gets the primary component single-phase fluid properties.
static InputParameters validParams()
static const std::string mu
Definition: NS.h:123
std::vector< CppType > secondaryToAllMassFractions_templ(const std::vector< CppType > &x_secondary) const
Computes all mass fractions.
Common class for single phase fluid properties.
std::vector< const IdealGasFluidProperties * > _component_fps
Component fluid properties objects.
static InputParameters validParams()
const std::vector< UserObjectName > _component_fp_names
Names of component fluid properties.
ADReal mixtureSpecificHeatRatio(const std::vector< ADReal > &x) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
Definition: NS.h:84
CppType mixtureSpecificHeatRatio_templ(const std::vector< CppType > &x) const
Computes the mixture specific heat ratio.
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
Class for fluid properties of an ideal gas mixture.
static InputParameters validParams()
Definition: NaNInterface.C:15
ADReal mixtureMolarMass(const std::vector< ADReal > &x) const
define_mass_specific_prop_from_p_T(v)
Ideal gas fluid properties Default parameters are for air at atmospheric pressure and temperature...
const unsigned int _n_components
Number of components.
Interface class for producing errors, warnings, or just quiet NaNs.
Definition: NaNInterface.h:22
CppType mixtureMolarMass_templ(const std::vector< CppType > &x) const
Computes the mixture molar mass.
std::vector< CppType > molarFractionsFromMassFractions_templ(const std::vector< CppType > &x) const
Computes molar fractions.
static const std::string k
Definition: NS.h:130