Line data Source code
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 :
10 : #pragma once
11 :
12 : #include "FluidProperties.h"
13 : /**
14 : * Adds AD versions of each fluid property. These functions use the Real versions of these
15 : methods
16 : * to compute the AD variables complete with derivatives. Typically, these do not need to be
17 : * overriden in derived classes.
18 : */
19 :
20 : #define propfuncAD(want, prop1, prop2) \
21 : virtual ADReal want##_from_##prop1##_##prop2( \
22 : const ADReal & p1, const ADReal & p2, const std::vector<ADReal> & x) const \
23 : { \
24 : Real p1_raw = p1.value(); \
25 : Real p2_raw = p2.value(); \
26 : std::vector<Real> x_raw(x.size(), 0); \
27 : for (unsigned int i = 0; i < x.size(); ++i) \
28 : x_raw[i] = x[i].value(); \
29 : \
30 : Real y_raw = 0; \
31 : Real dy_dp1 = 0; \
32 : Real dy_dp2 = 0; \
33 : std::vector<Real> dy_dx(x.size(), 0); \
34 : want##_from_##prop1##_##prop2(p1_raw, p2_raw, x_raw, y_raw, dy_dp1, dy_dp2, dy_dx); \
35 : \
36 : ADReal result = y_raw; \
37 : result.derivatives() = p1.derivatives() * dy_dp1 + p2.derivatives() * dy_dp2; \
38 : for (unsigned int i = 0; i < x.size(); ++i) \
39 : result.derivatives() += x[i].derivatives() * dy_dx[i]; \
40 : return result; \
41 : } \
42 : \
43 : virtual void want##_from_##prop1##_##prop2(const ADReal & prop1, \
44 : const ADReal & prop2, \
45 : std::vector<ADReal> & x, \
46 : ADReal & val, \
47 : ADReal & d##want##d1, \
48 : ADReal & d##want##d2, \
49 : std::vector<ADReal> & d##want##dx) const \
50 : { \
51 : imperfectJacobianMessage(__PRETTY_FUNCTION__, " derivative derivatives not implemented."); \
52 : Real dummy, tmp1, tmp2; \
53 : std::vector<Real> x_raw(x.size(), 0); \
54 : std::vector<Real> tmp3(x.size(), 0); \
55 : for (unsigned int i = 0; i < x.size(); ++i) \
56 : x_raw[i] = x[i].value(); \
57 : val = want##_from_##prop1##_##prop2(prop1, prop2, x); \
58 : want##_from_##prop1##_##prop2(prop1.value(), prop2.value(), x_raw, dummy, tmp1, tmp2, tmp3); \
59 : d##want##d1 = tmp1; \
60 : d##want##d2 = tmp2; \
61 : for (unsigned int i = 0; i < x.size(); ++i) \
62 : d##want##dx[i] = tmp3[i]; \
63 : }
64 :
65 : /**
66 : * Adds function definitions with not implemented error. These functions should be overriden in
67 : * derived classes where required. AD versions are constructed automatically using propfuncAD.
68 : */
69 : #define propfunc(want, prop1, prop2) \
70 : virtual Real want##_from_##prop1##_##prop2(Real, Real, const std::vector<Real> &) const \
71 : { \
72 : mooseError(name(), ": ", __PRETTY_FUNCTION__, " not implemented."); \
73 : } \
74 : \
75 : virtual void want##_from_##prop1##_##prop2(Real prop1, \
76 : Real prop2, \
77 : const std::vector<Real> & x, \
78 : Real & val, \
79 : Real & d##want##d1, \
80 : Real & d##want##d2, \
81 : std::vector<Real> & d##want##dx) const \
82 : { \
83 : imperfectJacobianMessage(__PRETTY_FUNCTION__, " derivatives not implemented."); \
84 : d##want##d1 = 0; \
85 : d##want##d2 = 0; \
86 : std::fill(d##want##dx.begin(), d##want##dx.end(), 0.); \
87 : val = want##_from_##prop1##_##prop2(prop1, prop2, x); \
88 : } \
89 : \
90 : propfuncAD(want, prop1, prop2)
91 :
92 : class SinglePhaseFluidProperties;
93 :
94 : /**
95 : * Base class for fluid properties of vapor mixtures
96 : *
97 : * Each interface, in addition to requiring 2 intensive thermodynamic properties,
98 : * requires the mass fractions of N-1 vapors in the mixture, where N is the
99 : * number of vapors in the mixture. The mass fraction of the remaining vapor
100 : * is inferred from the fact that the mass fractions sum to unity.
101 : */
102 : class VaporMixtureFluidProperties : public FluidProperties
103 : {
104 : public:
105 : static InputParameters validParams();
106 :
107 : VaporMixtureFluidProperties(const InputParameters & parameters);
108 : virtual ~VaporMixtureFluidProperties();
109 :
110 : /**
111 : * Gets the primary component single-phase fluid properties
112 : */
113 : virtual const SinglePhaseFluidProperties & getPrimaryFluidProperties() const = 0;
114 :
115 : /**
116 : * Gets a secondary component single-phase fluid properties
117 : *
118 : * @param[in] i Index of the secondary fluid properties (0 is first secondary)
119 : */
120 : virtual const SinglePhaseFluidProperties &
121 : getSecondaryFluidProperties(unsigned int i = 0) const = 0;
122 :
123 : #pragma GCC diagnostic push
124 : #pragma GCC diagnostic ignored "-Woverloaded-virtual"
125 : // clang-format off
126 :
127 : ///@{
128 0 : propfunc(p, v, e)
129 0 : propfunc(T, v, e)
130 0 : propfunc(c, v, e)
131 0 : propfunc(v, p, T)
132 0 : propfunc(rho, p, T)
133 0 : propfunc(e, p, T)
134 0 : propfunc(s, p, T)
135 0 : propfunc(c, p, T)
136 0 : propfunc(cp, p, T)
137 0 : propfunc(cv, p, T)
138 0 : propfunc(mu, p, T)
139 0 : propfunc(k, p, T)
140 0 : propfunc(e, p, rho)
141 : ///@}
142 :
143 : // clang-format on
144 :
145 : #undef propfunc
146 : #undef propfuncAD
147 :
148 : /**
149 : * Returns the number of secondary vapors
150 : */
151 0 : virtual unsigned int getNumberOfSecondaryVapors() const
152 : {
153 0 : return numberOfComponents() - 1;
154 : }
155 :
156 : /**
157 : * Returns the number of components in the mixture
158 : */
159 : virtual unsigned int numberOfComponents() const = 0;
160 :
161 : /**
162 : * Computes the mass fraction of the primary vapor given mass fractions of the
163 : * secondary vapors.
164 : *
165 : * This uses the relation
166 : * \f[
167 : * \sum\limits_i^N x_i = 1 ,
168 : * \f]
169 : * where the mass fractions \f$x_i, i=2\ldots N\f$ correspond to the secondary
170 : * vapors.
171 : */
172 : Real primaryMassFraction(const std::vector<Real> & x) const;
173 :
174 : /**
175 : * Computes the mixture molar mass for given molar fractions and molar masses
176 : *
177 : * @param[in] molar_fractions Molar fractions for all vapors
178 : * @param[in] molar_masses Molar masses for all vapors
179 : */
180 : Real mixtureMolarMass(const std::vector<Real> & molar_fractions,
181 : const std::vector<Real> & molar_masses) const;
182 :
183 : /**
184 : * Computes the mass fractions for given molar fractions and molar masses
185 : *
186 : * @param[in] molar_fractions Molar fractions for all vapors
187 : * @param[in] molar_masses Molar masses for all vapors
188 : */
189 : std::vector<Real> massFractionsFromMolarFractions(const std::vector<Real> & molar_fractions,
190 : const std::vector<Real> & molar_masses) const;
191 :
192 : protected:
193 : template <typename... Args>
194 8 : void imperfectJacobianMessage(Args... args) const
195 : {
196 8 : if (_allow_imperfect_jacobians)
197 8 : mooseDoOnce(mooseWarning(std::forward<Args>(args)...));
198 : else
199 0 : mooseError(std::forward<Args>(args)...);
200 8 : }
201 : };
202 :
203 : #pragma GCC diagnostic pop
204 :
205 : // Macro to avoid compilation issues associated with overloading virtual methods
206 : #define usingVaporMixtureFluidPropertiesMembers \
207 : using VaporMixtureFluidProperties::p_from_v_e; \
208 : using VaporMixtureFluidProperties::T_from_v_e; \
209 : using VaporMixtureFluidProperties::c_from_v_e; \
210 : using VaporMixtureFluidProperties::rho_from_p_T; \
211 : using VaporMixtureFluidProperties::v_from_p_T; \
212 : using VaporMixtureFluidProperties::s_from_p_T; \
213 : using VaporMixtureFluidProperties::e_from_p_T; \
214 : using VaporMixtureFluidProperties::c_from_p_T; \
215 : using VaporMixtureFluidProperties::cp_from_p_T; \
216 : using VaporMixtureFluidProperties::cv_from_p_T; \
217 : using VaporMixtureFluidProperties::mu_from_p_T; \
218 : using VaporMixtureFluidProperties::k_from_p_T; \
219 : using VaporMixtureFluidProperties::e_from_p_rho
|