Tabulated property fitting¶
Fit real-gas equation of state from tabulated properties.
This module turns a table of thermodynamic properties into the polynomial
coefficient arrays required by ember.fluid.RealFluid, following the
entropy-based formulation of Wheeler [1].
The user should perform the fitting once, offline, and then pass the resulting
coefficients to ember.fluid.RealFluid at simulation runtime. Only
sample_coolprop() needs a lazy import of CoolProp, so the rest of the
code can be used without it.
The method requires two polynomial fits: compressibility factor as a two-dimensional surface in density and internal energy, and entropy along a reference isochor as a one-dimensional function of internal energy. Optionally, viscosity and thermal conductivity are fitted as two further two-dimensional surfaces over density and internal energy.
Polynomials are fitted in coordinates scaled onto \([-1, 1]\) by the bounds of a fit box. The reference isochor passes through the centre of the box, and viscosity and conductivity are normalised by their values at the box centre.
Example usage¶
With CoolProp installed, the pipeline is a single call:
from ember.realgas_fit import fit, sample_coolprop
from ember.fluid import RealFluid
result = fit(
**sample_coolprop(
"CO2", rho_lim=(2.0, 150.0), u_lim=(3.5e5, 5.0e5)
)
) # fit the equation of state and transport surfaces
fluid = RealFluid(**result.kwargs) # hand to the solver
print(result.info_Z.rmse, result.info_s.rmse) # inspect the fit residuals
- class realgas_fit.FitInfo(rmse, R2)[source]¶
Bases:
objectQuality of a single least-squares polynomial fit.
- class realgas_fit.FitResult(kwargs, info_Z, info_s, info_mu, info_kappa)[source]¶
Bases:
objectFitted coefficients together with the residuals that bound their accuracy.
- kwargs¶
Keyword arguments defining the equation of state, ready to splat into
ember.fluid.RealFluid. Containsalpha,beta,rho_lim,u_lim,Rgas,delta,gamma,mu_candkappa_c.- Type:
- info_mu, info_kappa
Residuals of the two transport surfaces, relative to the value each is normalised by [–], so that they read as fractional errors.
- Type:
- realgas_fit.fit(rho, u, P, T, s, mu, kappa, Rgas, rho_lim, u_lim, order=8, basis='total-order')[source]¶
Fit an equation of state to tabulated thermodynamic properties.
Fits the compressibility factor as a surface in density and internal energy, then recovers the entropy variation along the reference isochor by subtracting the analytic density integral from the tabulated entropy. What remains is a function of internal energy alone, so a one-dimensional fit closes the model.
The sample points need not lie on a grid, but they must all be inside the box given by
rho_limandu_lim, and must avoid the two-phase region, where the properties are not smooth and the fit would be poisoned.sample_coolprop()masks it, and returns every argument below but the two that select the basis, sofit(**sample_coolprop(...))is the whole pipeline.- Parameters:
rho (array_like) – Sample densities [kg/m³].
u (array_like) – Sample specific internal energies [J/kg], on any datum.
P (array_like) – Pressure at the sample states [Pa].
T (array_like) – Temperature at the sample states [K].
s (array_like) – Specific entropy at the sample states [J/kg/K], on any datum.
mu (array_like) – Dynamic viscosity at the sample states [kg/m/s].
kappa (array_like) – Thermal conductivity at the sample states [W/m/K].
Rgas (float) – Specific gas constant [J/kg/K].
rho_lim (tuple) –
(min, max)density bounds of the fit box [kg/m³].u_lim (tuple) –
(min, max)internal energy bounds of the fit box [J/kg], on the same datum asu.order (int, optional) – Maximum polynomial order in each variable.
basis ({'total-order', 'tensor-grid'}, optional) – Which order combinations to retain.
'total-order'(the default) keeps only terms whose orders in the two variables sum to at mostorder;'tensor-grid'keeps every combination up toorderin each. The default drops the worst-conditioned high-order-in-both corners for roughly half the terms.
- Returns:
result – Coefficients ready for
ember.fluid.RealFluid, with the fit residuals that bound their accuracy.- Return type:
- realgas_fit.sample_coolprop(fluid_name, rho_lim, u_lim, ni=100)[source]¶
Sample thermodynamic properties over a fit box using CoolProp.
States that fail to converge or fall inside the two-phase dome are dropped: properties are not smooth across saturation, and including such points would poison the fit far more than any choice of basis or order. So are states whose transport properties CoolProp declines to report, which for a fluid with no transport model at all is every one of them — said so, rather than reported as an empty box.
- Parameters:
- Returns:
Arrays
rho,u,P,T,s,muandkappaat the surviving states,Rgas, the specific gas constant [J/kg/K], and therho_limandu_limthat were sampled. That is every argumentfit()needs, so the whole pipeline isfit(**sample_coolprop(...)).The box is passed on rather than left to the caller to repeat because nothing downstream could catch it being repeated wrongly: a fit taken over a box other than the sampled one puts the normalised coordinates outside
[-1, 1], where the Legendre basis loses its orthogonality and the fit its conditioning – and returns coefficients that are wrong without being nan.- Return type: