https://mooseframework.inl.gov
Loading...
Searching...
No Matches
TemperaturePressureFunctionFluidProperties.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
11#include "NewtonInversion.h"
12
14
17{
19 params.addRequiredParam<FunctionName>(
20 "k", "Thermal conductivity function of temperature and pressure [W/(m-K)]");
21 params.addRequiredParam<FunctionName>("rho",
22 "Density function of temperature and pressure [kg/m^3]");
23 params.addRequiredParam<FunctionName>(
24 "mu", "Dynamic viscosity function of temperature and pressure [Pa-s]");
25
26 params.addParam<FunctionName>(
27 "cp", "Isobaric specific heat function of temperature and pressure [J/(kg-K)]");
28 params.addRangeCheckedParam<Real>(
29 "cv", 0, "cv >= 0", "Constant isochoric specific heat [J/(kg-K)]");
30 params.addParam<Real>("e_ref", 0, "Specific internal energy at the reference temperature");
31 params.addParam<Real>("T_ref", 0, "Reference temperature for the specific internal energy");
32 params.addParam<Real>("dT_integration_intervals",
33 10,
34 "Size of intervals for integrating cv(T) to compute e(T) from e(T_ref)");
35
37 "Single-phase fluid properties that allows to provide thermal "
38 "conductivity, density, and viscosity as functions of temperature and pressure.");
39 return params;
40}
41
43 const InputParameters & parameters)
44 : SinglePhaseFluidProperties(parameters),
45 _initialized(false),
46 _cv(getParam<Real>("cv")),
47 _cv_is_constant(_cv != 0),
48 _e_ref(getParam<Real>("e_ref")),
49 _T_ref(getParam<Real>("T_ref")),
50 _integration_dT(getParam<Real>("dT_integration_intervals"))
51{
52 if (isParamValid("cp") && _cv_is_constant)
53 paramError("cp", "The parameter 'cp' may only be specified if 'cv' is unspecified or is zero.");
54}
55
56void
65
66std::string
68{
69 return "TemperaturePressureFunctionFluidProperties";
70}
71
72Real
74{
76 return _T_ref + (e - _e_ref) / _cv;
77 else
78 {
79 const Real p0 = _p_initial_guess;
80 const Real T0 = _T_initial_guess;
81 Real p, T;
82 bool conversion_succeeded = true;
83 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
84 if (conversion_succeeded)
85 return T;
86 else
87 mooseError("T_from_v_e calculation failed.");
88 }
89}
90
91Real
93{
94 auto lambda = [&](Real p, Real current_T, Real & new_h, Real & dh_dp, Real & dh_dT)
95 { h_from_p_T(p, current_T, new_h, dh_dp, dh_dT); };
97 p, h, _T_initial_guess, _tolerance, lambda, name() + "::T_from_p_h", _max_newton_its)
98 .first;
99 // check for nans
100 if (std::isnan(T))
101 mooseError("Conversion from pressure (p = ",
102 p,
103 ") and enthalpy (h = ",
104 h,
105 ") to temperature failed to converge.");
106 return T;
107}
108
109Real
111{
112 auto lambda = [&](Real p, Real current_T, Real & new_rho, Real & drho_dp, Real & drho_dT)
113 { rho_from_p_T(p, current_T, new_rho, drho_dp, drho_dT); };
115 p, rho, _T_initial_guess, _tolerance, lambda, name() + "::T_from_p_rho")
116 .first;
117 // check for nans
118 if (std::isnan(T))
119 mooseError("Conversion from pressure (p = ",
120 p,
121 ") and density (rho = ",
122 rho,
123 ") to temperature failed to converge.");
124 return T;
125}
126
127Real
129{
130 if (_cv_is_constant)
131 {
132 Real p = p_from_v_e(v, e);
133 Real T = T_from_v_e(v, e);
134 return cp_from_p_T(p, T);
135 }
136 else
137 {
138 const Real p0 = _p_initial_guess;
139 const Real T0 = _T_initial_guess;
140 Real p, T;
141 bool conversion_succeeded = true;
142 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
143 if (conversion_succeeded)
144 return cp_from_p_T(p, T);
145 else
146 mooseError("cp_from_v_e calculation failed. p= ", p, " T = ", T);
147 }
148}
149
150void
152 Real v, Real e, Real & cp, Real & dcp_dv, Real & dcp_de) const
153{
154 cp = cp_from_v_e(v, e);
155 // Using finite difference to get around difficulty of implementation
156 Real eps = 1e-10;
157 Real cp_pert = cp_from_v_e(v * (1 + eps), e);
158 dcp_dv = (cp_pert - cp) / eps / v;
159 cp_pert = cp_from_v_e(v, e * (1 + eps));
160 dcp_de = (cp_pert - cp) / eps / e;
161}
162
163Real
165{
166 if (_cv_is_constant)
167 return _cv;
168 else
169 {
170 const Real p0 = _p_initial_guess;
171 const Real T0 = _T_initial_guess;
172 Real p, T;
173 bool conversion_succeeded = true;
174 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
175 if (conversion_succeeded)
176 return cv_from_p_T(p, T);
177 else
178 mooseError("cp_from_v_e calculation failed.");
179 }
180}
181
182void
184 Real v, Real e, Real & cv, Real & dcv_dv, Real & dcv_de) const
185{
186 if (_cv_is_constant)
187 {
188 cv = cv_from_v_e(v, e);
189 dcv_dv = 0.0;
190 dcv_de = 0.0;
191 }
192 else
193 {
194 const Real p0 = _p_initial_guess;
195 const Real T0 = _T_initial_guess;
196 Real p, T;
197 bool conversion_succeeded = true;
198 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
199 Real dcv_dp, dcv_dT;
200 cv_from_p_T(p, T, cv, dcv_dp, dcv_dT);
201 if (!conversion_succeeded)
202 mooseError("cp_from_v_e and derivatives calculation failed.");
203
204 Real p1, T1;
205 p_T_from_v_e(v * (1 + 1e-6), e, p0, T0, p1, T1, conversion_succeeded);
206 Real dp_dv = (p1 - p) / (v * 1e-6);
207 Real dT_dv = (T1 - T) / (v * 1e-6);
208 if (!conversion_succeeded)
209 mooseError("cp_from_v_e and derivatives calculation failed.");
210
211 Real p2, T2;
212 p_T_from_v_e(v, e * (1 + 1e-6), p0, T0, p2, T2, conversion_succeeded);
213 Real dp_de = (p2 - p) / (e * 1e-6);
214 Real dT_de = (T2 - T) / (e * 1e-6);
215 if (!conversion_succeeded)
216 mooseError("cp_from_v_e and derivatives calculation failed.");
217
218 dcv_dv = dcv_dp * dp_dv + dcv_dT * dT_dv;
219 dcv_de = dcv_dp * dp_de + dcv_dT * dT_de;
220 }
221}
222
223Real
225{
226 const Real T = T_from_v_e(v, e);
227 // note that p and T inversion in the definition of lambda
228 auto lambda = [&](Real T, Real current_p, Real & new_rho, Real & drho_dT, Real & drho_dp)
229 { rho_from_p_T(current_p, T, new_rho, drho_dp, drho_dT); };
231 T, 1. / v, _p_initial_guess, _tolerance, lambda, name() + "::p_from_v_e")
232 .first;
233 // check for nans
234 if (std::isnan(p))
235 mooseError("Conversion from specific volume (v = ",
236 v,
237 ") and specific energy (e = ",
238 e,
239 ") to pressure failed to converge.");
240 return p;
241}
242
243Real
245{
246 if (_cv_is_constant)
247 {
248 Real temperature = T_from_v_e(v, e);
249 Real pressure = p_from_v_e(v, e);
250 return mu_from_p_T(pressure, temperature);
251 }
252 else
253 {
254 const Real p0 = _p_initial_guess;
255 const Real T0 = _T_initial_guess;
256 Real p, T;
257 bool conversion_succeeded = true;
258 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
259 if (conversion_succeeded)
260 return mu_from_p_T(p, T);
261 else
262 mooseError("mu_from_v_e calculation failed.");
263 }
264}
265
266Real
268{
269 if (_cv_is_constant)
270 {
271 Real temperature = T_from_v_e(v, e);
272 Real pressure = p_from_v_e(v, e);
273 return k_from_p_T(pressure, temperature);
274 }
275 else
276 {
277 const Real p0 = _p_initial_guess;
278 const Real T0 = _T_initial_guess;
279 Real p, T;
280 bool conversion_succeeded = true;
281 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
282 if (conversion_succeeded)
283 return k_from_p_T(p, T);
284 else
285 mooseError("k_from_v_e calculation failed.");
286 }
287}
288
289Real
291{
292 if (!_initialized)
294 return _rho_function->value(0, Point(temperature, pressure, 0));
295}
296
297void
299 Real pressure, Real temperature, Real & rho, Real & drho_dp, Real & drho_dT) const
300{
301 rho = rho_from_p_T(pressure, temperature);
302 const RealVectorValue grad_function = _rho_function->gradient(0, Point(temperature, pressure, 0));
303 drho_dT = grad_function(0);
304 drho_dp = grad_function(1);
305}
306
307void
309 const ADReal & temperature,
310 ADReal & rho,
311 ADReal & drho_dp,
312 ADReal & drho_dT) const
313{
314 rho = rho_from_p_T(pressure, temperature);
315 const ADRealVectorValue grad_function =
316 _rho_function->gradient(0, Point(temperature.value(), pressure.value(), 0));
317 drho_dT = grad_function(0);
318 drho_dp = grad_function(1);
319}
320
321Real
322TemperaturePressureFunctionFluidProperties::v_from_p_T(Real pressure, Real temperature) const
323{
324 return 1.0 / rho_from_p_T(pressure, temperature);
325}
326
327void
329 Real pressure, Real temperature, Real & v, Real & dv_dp, Real & dv_dT) const
330{
331 v = v_from_p_T(pressure, temperature);
332
333 Real rho, drho_dp, drho_dT;
334 rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
335
336 dv_dp = -v * v * drho_dp;
337 dv_dT = -v * v * drho_dT;
338}
339
340Real
341TemperaturePressureFunctionFluidProperties::h_from_p_T(Real pressure, Real temperature) const
342{
343 Real e = e_from_p_T(pressure, temperature);
344 Real rho = rho_from_p_T(pressure, temperature);
345 return e + pressure / rho;
346}
347
348void
350 Real pressure, Real temperature, Real & h, Real & dh_dp, Real & dh_dT) const
351{
352 Real e, de_dp, de_dT;
353 e_from_p_T(pressure, temperature, e, de_dp, de_dT);
354 Real rho, drho_dp, drho_dT;
355 rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
356 h = e + pressure / rho;
357 dh_dp = de_dp + 1. / rho - pressure / rho / rho * drho_dp;
358 dh_dT = de_dT - pressure * drho_dT / rho / rho;
359}
360
361Real
362TemperaturePressureFunctionFluidProperties::e_from_p_T(Real pressure, Real temperature) const
363{
364 if (_cv_is_constant)
365 return _e_ref + _cv * (temperature - _T_ref);
366 else
367 {
368 const int n_intervals = std::ceil(std::abs(temperature - _T_ref) / _integration_dT);
369 const auto h = (temperature - _T_ref) / n_intervals;
370 Real integral = 0;
371 // Centered step integration is second-order
372 for (const auto i : make_range(n_intervals))
373 integral += cv_from_p_T(pressure, _T_ref + (i + 0.5) * h);
374 integral *= h;
375 // we are still missing the dV or dP term to go from V/P_ref (e_ref = e(T_ref, V/P_ref))
376 // to current V. The dT term is the largest one though
377 return _e_ref + integral;
378 }
379}
380
381void
383 Real pressure, Real temperature, Real & e, Real & de_dp, Real & de_dT) const
384{
385 if (_cv_is_constant)
386 {
387 e = e_from_p_T(pressure, temperature);
388 de_dp = 0.0;
389 de_dT = _cv;
390 }
391 else
392 {
393 e = e_from_p_T(pressure, temperature);
394 Real ep = e_from_p_T(pressure * (1 + 1e-8), temperature);
395 de_dp = (ep - e) / (pressure * 1e-8);
396 de_dT = cv_from_p_T(pressure, temperature);
397 }
398}
399
400Real
402{
403 if (_cv_is_constant)
404 {
405 Real temperature = T_from_p_rho(p, rho);
406 return _e_ref + _cv * (temperature - _T_ref);
407 }
408 else
409 {
410 Real temperature = T_from_p_rho(p, rho);
411 return e_from_p_T(p, temperature);
412 }
413}
414
415Real
417{
418 Real rho, drho_dp, drho_dT;
419 rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
420 return -drho_dT / rho;
421}
422
423Real
425{
426 if (_cv_is_constant)
427 {
428 Real rho, drho_dp, drho_dT;
429 rho_from_p_T(p, T, rho, drho_dp, drho_dT);
430 // Wikipedia notation for thermal expansion / compressibility coefficients
431 Real alpha = -drho_dT / rho;
432 Real beta = -drho_dp / rho;
433 if (!MooseUtils::absoluteFuzzyEqual(beta, 0))
434 return _cv + MathUtils::pow(alpha, 2) * T / rho / beta;
435 else
436 return _cv;
437 }
438 else
439 {
440 if (!_initialized)
442 return _cp_function->value(0, Point(T, p, 0));
443 }
444}
445
446void
448 Real pressure, Real temperature, Real & cp, Real & dcp_dp, Real & dcp_dT) const
449{
450 if (_cv_is_constant)
451 {
452 cp = cp_from_p_T(pressure, temperature);
453 Real eps = 1e-8;
454 Real cp_1p = cp_from_p_T(pressure * (1 + eps), temperature);
455 Real cp_1T = cp_from_p_T(pressure, temperature * (1 + eps));
456 dcp_dp = (cp_1p - cp) / (pressure * eps);
457 dcp_dT = (cp_1T - cp) / (temperature * eps);
458 }
459 else
460 {
461 cp = cp_from_p_T(pressure, temperature);
462 const RealVectorValue grad_function =
463 _cp_function->gradient(0, Point(temperature, pressure, 0));
464 dcp_dT = grad_function(0);
465 dcp_dp = grad_function(1);
466 }
467}
468
469Real
471{
472 if (_cv_is_constant)
473 return _cv;
474 else
475 {
476 Real rho, drho_dp, drho_dT;
477 rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
478 // Wikipedia notation for thermal expansion / compressibility coefficients
479 Real alpha = -drho_dT / rho;
480 Real beta = -drho_dp / rho;
481 if (!MooseUtils::absoluteFuzzyEqual(beta, 0))
482 return cp_from_p_T(pressure, temperature) -
483 MathUtils::pow(alpha, 2) * temperature / rho / beta;
484 else
485 return cp_from_p_T(pressure, temperature);
486 }
487}
488
489void
491 Real pressure, Real temperature, Real & cv, Real & dcv_dp, Real & dcv_dT) const
492{
493 if (_cv_is_constant)
494 {
495 cv = cv_from_p_T(pressure, temperature);
496 dcv_dp = 0.0;
497 dcv_dT = 0.0;
498 }
499 else
500 {
501 cv = cv_from_p_T(pressure, temperature);
502 Real eps = 1e-10;
503 Real cv_1p = cv_from_p_T(pressure * (1 + eps), temperature);
504 Real cv_1T = cv_from_p_T(pressure, temperature * (1 + eps));
505 dcv_dp = (cv_1p - cv) / (pressure * eps);
506 dcv_dT = (cv_1T - cv) / (temperature * eps);
507 }
508}
509
510Real
512{
513 if (!_initialized)
515 return _mu_function->value(0, Point(temperature, pressure, 0));
516}
517
518void
520 Real pressure, Real temperature, Real & mu, Real & dmu_dp, Real & dmu_dT) const
521{
522 mu = mu_from_p_T(pressure, temperature);
523 const RealVectorValue grad_function = _mu_function->gradient(0, Point(temperature, pressure, 0));
524 dmu_dT = grad_function(0);
525 dmu_dp = grad_function(1);
526}
527
528Real
529TemperaturePressureFunctionFluidProperties::k_from_p_T(Real pressure, Real temperature) const
530{
531 if (!_initialized)
533 return _k_function->value(0, Point(temperature, pressure, 0));
534}
535
536void
538 Real pressure, Real temperature, Real & k, Real & dk_dp, Real & dk_dT) const
539{
540 k = k_from_p_T(pressure, temperature);
541 const RealVectorValue grad_function = _k_function->gradient(0, Point(temperature, pressure, 0));
542 dk_dT = grad_function(0);
543 dk_dp = grad_function(1);
544}
DualNumber< Real, DNDerivativeType, true > ADReal
const double mu
const Real p
const double rho
const double T
const double v
registerMooseObject("FluidPropertiesApp", TemperaturePressureFunctionFluidProperties)
const Function & getFunction(const std::string &name) const
virtual RealGradient gradient(Real t, const Point &p) const
virtual Real value(Real t, const Point &p) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
const std::string & name() const
void paramError(const std::string &param, Args... args) const
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
Common class for single phase fluid properties.
const Real _T_initial_guess
Initial guess for temperature (or temperature used to compute the initial guess)
void p_T_from_v_e(const CppType &v, const CppType &e, Real p0, Real T0, CppType &p, CppType &T, bool &conversion_succeeded) const
Determines (p,T) from (v,e) using Newton Solve in 2D Useful for conversion between different sets of ...
const Real _p_initial_guess
Initial guess for pressure (or pressure used to compute the initial guess)
static InputParameters validParams()
const Real _tolerance
Newton's method may be used to convert between variable sets.
const unsigned int _max_newton_its
Maximum number of iterations for the variable conversion newton solves.
e e e e s T T T T T rho v v T e h
Fluid properties provided as multiple-variable functions of temperature and pressure.
virtual Real e_from_p_rho(Real p, Real rho) const override
Specific internal energy from pressure and density.
void initialSetup() override
Functions are constructed after fluid properties, so we delay the getting of the Function.
virtual Real cv_from_v_e(Real v, Real e) const override
Isochoric specific heat from specific volume and specific internal energy.
bool _initialized
whether the object is initialized, eg, the functions have been retrieved from the problem
virtual Real T_from_v_e(Real v, Real e) const override
Temperature from specific volume and specific internal energy.
virtual Real k_from_p_T(Real p, Real T) const override
Thermal conductivity from pressure and temperature.
const Real _integration_dT
Size of temperature intervals when integrating the specific heat to compute the specific energy.
const Function * _rho_function
function defining density as a function of temperature and pressure
const bool _cv_is_constant
whether a constant isochoric specific heat is used
virtual Real p_from_v_e(Real v, Real e) const override
Pressure from specific volume and specific internal energy.
virtual Real cv_from_p_T(Real p, Real T) const override
Isochoric specific heat capacity from pressure and temperature.
virtual Real k_from_v_e(Real v, Real e) const override
Thermal conductivity from specific volume and specific internal energy.
virtual Real e_from_p_T(Real p, Real T) const override
Specific internal energy from pressure and temperature.
virtual Real rho_from_p_T(Real p, Real T) const override
Density from pressure and temperature.
const Function * _mu_function
function defining dynamic viscosity as a function of temperature and pressure
virtual Real h_from_p_T(Real p, Real T) const override
Specific enthalpy from pressure and temperature.
virtual Real T_from_p_rho(Real p, Real rho) const
Temperature from pressure and density.
virtual std::string fluidName() const override
Fluid name.
virtual Real beta_from_p_T(Real p, Real T) const override
Thermal expansion coefficient from pressure and temperature.
virtual Real mu_from_v_e(Real v, Real e) const override
Dynamic viscosity from specific volume and specific internal energy.
const Function * _cp_function
function defining specific heat as a function of temperature and pressure
const Function * _k_function
function defining thermal conductivity as a function of temperature and pressure
virtual Real v_from_p_T(Real p, Real T) const override
Specific volume from pressure and temperature.
virtual Real cp_from_p_T(Real p, Real T) const override
Isobaric specific heat capacity from pressure and temperature.
const Real _T_ref
Reference temperature for the reference specific energy.
virtual Real T_from_p_h(Real p, Real h) const override
Temperature from pressure and specific enthalpy.
virtual Real cp_from_v_e(Real v, Real e) const override
Isobaric specific heat from specific volume and specific internal energy.
virtual Real mu_from_p_T(Real p, Real T) const override
Dynamic viscosity from pressure and temperature.
std::pair< T, T > NewtonSolve(const T &x, const T &y, const Real z_initial_guess, const Real tolerance, const Functor &y_from_x_z, const std::string &caller_name, const unsigned int max_its=100, const bool verbose=false)
NewtonSolve does a 1D Newton Solve to solve the equation y = f(x, z) for variable z.
T pow(T x, int e)