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
66Real
68{
69 // Relative step, falling back to the relative step itself as an absolute step when the
70 // argument is zero and a relative step would vanish
71 return x == 0 ? rel_step : rel_step * std::abs(x);
72}
73
74std::string
76{
77 return "TemperaturePressureFunctionFluidProperties";
78}
79
80Real
82{
84 return _T_ref + (e - _e_ref) / _cv;
85 else
86 {
87 const Real p0 = _p_initial_guess;
88 const Real T0 = _T_initial_guess;
89 Real p, T;
90 bool conversion_succeeded = true;
91 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
92 if (conversion_succeeded)
93 return T;
94 else
95 mooseError("T_from_v_e calculation failed.");
96 }
97}
98
99Real
101{
102 auto lambda = [&](Real p, Real current_T, Real & new_h, Real & dh_dp, Real & dh_dT)
103 { h_from_p_T(p, current_T, new_h, dh_dp, dh_dT); };
105 p, h, _T_initial_guess, _tolerance, lambda, name() + "::T_from_p_h", _max_newton_its)
106 .first;
107 // check for nans
108 if (std::isnan(T))
109 mooseError("Conversion from pressure (p = ",
110 p,
111 ") and enthalpy (h = ",
112 h,
113 ") to temperature failed to converge.");
114 return T;
115}
116
117Real
119{
120 auto lambda = [&](Real p, Real current_T, Real & new_rho, Real & drho_dp, Real & drho_dT)
121 { rho_from_p_T(p, current_T, new_rho, drho_dp, drho_dT); };
123 p, rho, _T_initial_guess, _tolerance, lambda, name() + "::T_from_p_rho")
124 .first;
125 // check for nans
126 if (std::isnan(T))
127 mooseError("Conversion from pressure (p = ",
128 p,
129 ") and density (rho = ",
130 rho,
131 ") to temperature failed to converge.");
132 return T;
133}
134
135Real
137{
138 if (_cv_is_constant)
139 {
140 Real p = p_from_v_e(v, e);
141 Real T = T_from_v_e(v, e);
142 return cp_from_p_T(p, T);
143 }
144 else
145 {
146 const Real p0 = _p_initial_guess;
147 const Real T0 = _T_initial_guess;
148 Real p, T;
149 bool conversion_succeeded = true;
150 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
151 if (conversion_succeeded)
152 return cp_from_p_T(p, T);
153 else
154 mooseError("cp_from_v_e calculation failed. p= ", p, " T = ", T);
155 }
156}
157
158void
160 Real v, Real e, Real & cp, Real & dcp_dv, Real & dcp_de) const
161{
162 cp = cp_from_v_e(v, e);
163 // Using finite difference to get around difficulty of implementation
164 const Real dv = fdStep(v, 1e-10);
165 dcp_dv = (cp_from_v_e(v + dv, e) - cp) / dv;
166 const Real de = fdStep(e, 1e-10);
167 dcp_de = (cp_from_v_e(v, e + de) - cp) / de;
168}
169
170Real
172{
173 if (_cv_is_constant)
174 return _cv;
175 else
176 {
177 const Real p0 = _p_initial_guess;
178 const Real T0 = _T_initial_guess;
179 Real p, T;
180 bool conversion_succeeded = true;
181 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
182 if (conversion_succeeded)
183 return cv_from_p_T(p, T);
184 else
185 mooseError("cv_from_v_e calculation failed.");
186 }
187}
188
189void
191 Real v, Real e, Real & cv, Real & dcv_dv, Real & dcv_de) const
192{
193 if (_cv_is_constant)
194 {
195 cv = cv_from_v_e(v, e);
196 dcv_dv = 0.0;
197 dcv_de = 0.0;
198 }
199 else
200 {
201 const Real p0 = _p_initial_guess;
202 const Real T0 = _T_initial_guess;
203 Real p, T;
204 bool conversion_succeeded = true;
205 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
206 Real dcv_dp, dcv_dT;
207 cv_from_p_T(p, T, cv, dcv_dp, dcv_dT);
208 if (!conversion_succeeded)
209 mooseError("cv_from_v_e and derivatives calculation failed.");
210
211 Real p1, T1;
212 const Real dv = fdStep(v, 1e-6);
213 p_T_from_v_e(v + dv, e, p0, T0, p1, T1, conversion_succeeded);
214 Real dp_dv = (p1 - p) / dv;
215 Real dT_dv = (T1 - T) / dv;
216 if (!conversion_succeeded)
217 mooseError("cv_from_v_e and derivatives calculation failed.");
218
219 Real p2, T2;
220 const Real de = fdStep(e, 1e-6);
221 p_T_from_v_e(v, e + de, p0, T0, p2, T2, conversion_succeeded);
222 Real dp_de = (p2 - p) / de;
223 Real dT_de = (T2 - T) / de;
224 if (!conversion_succeeded)
225 mooseError("cv_from_v_e and derivatives calculation failed.");
226
227 dcv_dv = dcv_dp * dp_dv + dcv_dT * dT_dv;
228 dcv_de = dcv_dp * dp_de + dcv_dT * dT_de;
229 }
230}
231
232Real
234{
235 const Real T = T_from_v_e(v, e);
236 // note that p and T inversion in the definition of lambda
237 auto lambda = [&](Real T, Real current_p, Real & new_rho, Real & drho_dT, Real & drho_dp)
238 { rho_from_p_T(current_p, T, new_rho, drho_dp, drho_dT); };
240 T, 1. / v, _p_initial_guess, _tolerance, lambda, name() + "::p_from_v_e")
241 .first;
242 // check for nans
243 if (std::isnan(p))
244 mooseError("Conversion from specific volume (v = ",
245 v,
246 ") and specific energy (e = ",
247 e,
248 ") to pressure failed to converge.");
249 return p;
250}
251
252Real
254{
255 if (_cv_is_constant)
256 {
257 Real temperature = T_from_v_e(v, e);
258 Real pressure = p_from_v_e(v, e);
259 return mu_from_p_T(pressure, temperature);
260 }
261 else
262 {
263 const Real p0 = _p_initial_guess;
264 const Real T0 = _T_initial_guess;
265 Real p, T;
266 bool conversion_succeeded = true;
267 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
268 if (conversion_succeeded)
269 return mu_from_p_T(p, T);
270 else
271 mooseError("mu_from_v_e calculation failed.");
272 }
273}
274
275Real
277{
278 if (_cv_is_constant)
279 {
280 Real temperature = T_from_v_e(v, e);
281 Real pressure = p_from_v_e(v, e);
282 return k_from_p_T(pressure, temperature);
283 }
284 else
285 {
286 const Real p0 = _p_initial_guess;
287 const Real T0 = _T_initial_guess;
288 Real p, T;
289 bool conversion_succeeded = true;
290 p_T_from_v_e(v, e, p0, T0, p, T, conversion_succeeded);
291 if (conversion_succeeded)
292 return k_from_p_T(p, T);
293 else
294 mooseError("k_from_v_e calculation failed.");
295 }
296}
297
298Real
300{
301 if (!_initialized)
303 return _rho_function->value(0, Point(temperature, pressure, 0));
304}
305
306void
308 Real pressure, Real temperature, Real & rho, Real & drho_dp, Real & drho_dT) const
309{
310 rho = rho_from_p_T(pressure, temperature);
311 const RealVectorValue grad_function = _rho_function->gradient(0, Point(temperature, pressure, 0));
312 drho_dT = grad_function(0);
313 drho_dp = grad_function(1);
314}
315
316void
318 const ADReal & temperature,
319 ADReal & rho,
320 ADReal & drho_dp,
321 ADReal & drho_dT) const
322{
323 rho = rho_from_p_T(pressure, temperature);
324 const ADRealVectorValue grad_function =
325 _rho_function->gradient(0, Point(temperature.value(), pressure.value(), 0));
326 drho_dT = grad_function(0);
327 drho_dp = grad_function(1);
328}
329
330Real
331TemperaturePressureFunctionFluidProperties::v_from_p_T(Real pressure, Real temperature) const
332{
333 return 1.0 / rho_from_p_T(pressure, temperature);
334}
335
336void
338 Real pressure, Real temperature, Real & v, Real & dv_dp, Real & dv_dT) const
339{
340 v = v_from_p_T(pressure, temperature);
341
342 Real rho, drho_dp, drho_dT;
343 rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
344
345 dv_dp = -v * v * drho_dp;
346 dv_dT = -v * v * drho_dT;
347}
348
349Real
350TemperaturePressureFunctionFluidProperties::h_from_p_T(Real pressure, Real temperature) const
351{
352 Real e = e_from_p_T(pressure, temperature);
353 Real rho = rho_from_p_T(pressure, temperature);
354 return e + pressure / rho;
355}
356
357void
359 Real pressure, Real temperature, Real & h, Real & dh_dp, Real & dh_dT) const
360{
361 Real e, de_dp, de_dT;
362 e_from_p_T(pressure, temperature, e, de_dp, de_dT);
363 Real rho, drho_dp, drho_dT;
364 rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
365 h = e + pressure / rho;
366 dh_dp = de_dp + 1. / rho - pressure / rho / rho * drho_dp;
367 dh_dT = de_dT - pressure * drho_dT / rho / rho;
368}
369
370Real
371TemperaturePressureFunctionFluidProperties::e_from_p_T(Real pressure, Real temperature) const
372{
373 if (_cv_is_constant)
374 return _e_ref + _cv * (temperature - _T_ref);
375 else
376 {
377 const int n_intervals = std::ceil(std::abs(temperature - _T_ref) / _integration_dT);
378 const auto h = (temperature - _T_ref) / n_intervals;
379 Real integral = 0;
380 // Centered step integration is second-order
381 for (const auto i : make_range(n_intervals))
382 integral += cv_from_p_T(pressure, _T_ref + (i + 0.5) * h);
383 integral *= h;
384 // we are still missing the dV or dP term to go from V/P_ref (e_ref = e(T_ref, V/P_ref))
385 // to current V. The dT term is the largest one though
386 return _e_ref + integral;
387 }
388}
389
390void
392 Real pressure, Real temperature, Real & e, Real & de_dp, Real & de_dT) const
393{
394 if (_cv_is_constant)
395 {
396 e = e_from_p_T(pressure, temperature);
397 de_dp = 0.0;
398 de_dT = _cv;
399 }
400 else
401 {
402 e = e_from_p_T(pressure, temperature);
403 const Real dp = fdStep(pressure, 1e-8);
404 de_dp = (e_from_p_T(pressure + dp, temperature) - e) / dp;
405 de_dT = cv_from_p_T(pressure, temperature);
406 }
407}
408
409Real
411{
412 if (_cv_is_constant)
413 {
414 Real temperature = T_from_p_rho(p, rho);
415 return _e_ref + _cv * (temperature - _T_ref);
416 }
417 else
418 {
419 Real temperature = T_from_p_rho(p, rho);
420 return e_from_p_T(p, temperature);
421 }
422}
423
424Real
426{
427 Real rho, drho_dp, drho_dT;
428 rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
429 return -drho_dT / rho;
430}
431
432Real
434{
435 if (_cv_is_constant)
436 {
437 Real rho, drho_dp, drho_dT;
438 rho_from_p_T(p, T, rho, drho_dp, drho_dT);
439 // Wikipedia notation for thermal expansion / compressibility coefficients
440 Real alpha = -drho_dT / rho;
441 Real beta = drho_dp / rho;
442 if (!MooseUtils::absoluteFuzzyEqual(beta, 0))
443 return _cv + MathUtils::pow(alpha, 2) * T / rho / beta;
444 else
445 return _cv;
446 }
447 else
448 {
449 if (!_initialized)
451 return _cp_function->value(0, Point(T, p, 0));
452 }
453}
454
455void
457 Real pressure, Real temperature, Real & cp, Real & dcp_dp, Real & dcp_dT) const
458{
459 if (_cv_is_constant)
460 {
461 cp = cp_from_p_T(pressure, temperature);
462 const Real dp = fdStep(pressure, 1e-8);
463 const Real dT = fdStep(temperature, 1e-8);
464 dcp_dp = (cp_from_p_T(pressure + dp, temperature) - cp) / dp;
465 dcp_dT = (cp_from_p_T(pressure, temperature + dT) - cp) / dT;
466 }
467 else
468 {
469 cp = cp_from_p_T(pressure, temperature);
470 const RealVectorValue grad_function =
471 _cp_function->gradient(0, Point(temperature, pressure, 0));
472 dcp_dT = grad_function(0);
473 dcp_dp = grad_function(1);
474 }
475}
476
477Real
479{
480 if (_cv_is_constant)
481 return _cv;
482 else
483 {
484 Real rho, drho_dp, drho_dT;
485 rho_from_p_T(pressure, temperature, rho, drho_dp, drho_dT);
486 // Wikipedia notation for thermal expansion / compressibility coefficients
487 Real alpha = -drho_dT / rho;
488 Real beta = drho_dp / rho;
489 if (!MooseUtils::absoluteFuzzyEqual(beta, 0))
490 return cp_from_p_T(pressure, temperature) -
491 MathUtils::pow(alpha, 2) * temperature / rho / beta;
492 else
493 return cp_from_p_T(pressure, temperature);
494 }
495}
496
497void
499 Real pressure, Real temperature, Real & cv, Real & dcv_dp, Real & dcv_dT) const
500{
501 if (_cv_is_constant)
502 {
503 cv = cv_from_p_T(pressure, temperature);
504 dcv_dp = 0.0;
505 dcv_dT = 0.0;
506 }
507 else
508 {
509 cv = cv_from_p_T(pressure, temperature);
510 const Real dp = fdStep(pressure, 1e-10);
511 const Real dT = fdStep(temperature, 1e-10);
512 dcv_dp = (cv_from_p_T(pressure + dp, temperature) - cv) / dp;
513 dcv_dT = (cv_from_p_T(pressure, temperature + dT) - cv) / dT;
514 }
515}
516
517Real
519{
520 if (!_initialized)
522 return _mu_function->value(0, Point(temperature, pressure, 0));
523}
524
525void
527 Real pressure, Real temperature, Real & mu, Real & dmu_dp, Real & dmu_dT) const
528{
529 mu = mu_from_p_T(pressure, temperature);
530 const RealVectorValue grad_function = _mu_function->gradient(0, Point(temperature, pressure, 0));
531 dmu_dT = grad_function(0);
532 dmu_dp = grad_function(1);
533}
534
535Real
536TemperaturePressureFunctionFluidProperties::k_from_p_T(Real pressure, Real temperature) const
537{
538 if (!_initialized)
540 return _k_function->value(0, Point(temperature, pressure, 0));
541}
542
543void
545 Real pressure, Real temperature, Real & k, Real & dk_dp, Real & dk_dT) const
546{
547 k = k_from_p_T(pressure, temperature);
548 const RealVectorValue grad_function = _k_function->gradient(0, Point(temperature, pressure, 0));
549 dk_dT = grad_function(0);
550 dk_dp = grad_function(1);
551}
DualNumber< Real, DNDerivativeType, true > ADReal
const std::vector< double > x
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.
static Real fdStep(Real x, Real rel_step)
Finite-difference step for argument x that does not vanish when x is zero.
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)