Date: 2026-01-30 Purpose: Comprehensive guide for using the gasmodels module Module: src/physics/gasmodels
Table of Contents
- Introduction
- Basic Usage
- Equation of State Selection
- Gas Mixtures
- Property Evaluation
- Chemical Equilibrium
- Compressible Flow Applications
- Advanced Topics
- Performance Optimization
Introduction
The gasmodels module provides a unified interface to various equations of state (EoS) for gas property calculations. It builds on the gastables module to create complete thermodynamic models with:
- Ideal gas behavior for low-pressure applications
- Cubic equations of state (SRK, Peng-Robinson) for moderate-to-high pressure
- Helmholtz free energy models for cryogenic fluids (H2 — para/normal/ortho — plus O2, CH4 and N2)
- Gas mixtures with composition-dependent properties
- Chemical equilibrium via Gibbs minimization
- Compressible flow utilities for aerospace/propulsion applications
Design philosophy:
Following BELFEM's HPC-first approach (see doc/coding_philosophy.md):
- Manual memory management for Gas objects (stack or explicit delete)
- Function pointer dispatch for zero-overhead EoS polymorphism
- Preallocated work arrays for mixture property calculations
- Spline-based evaluation for repeated property lookups
Basic Usage
Creating an Ideal Gas
The simplest use case - ideal gas model for a pure component:
{
return 0;
}
The gas class that provides the fluid model.
Definition cl_Gas.hpp:81
real lambda(const real T, const real p) const
thermal conductivity in W/(m*K)
Definition cl_Gas.cpp:1772
virtual real h(const real T, const real p) const
Definition cl_Gas.cpp:1692
real rho(const real T, const real p) const
Definition cl_Gas.cpp:1562
real mu(const real T, const real p) const
dynamic viscosity in Pa*s
Definition cl_Gas.cpp:1756
virtual real cp(const real T, const real p) const
Definition cl_Gas.cpp:1586
virtual real s(const real T, const real p) const
Definition cl_Gas.cpp:1708
USER GUIDES:
Definition cl_Capacitor.cpp:16
double real
Definition typedefs.hpp:36
Key points:
- Gas constructor creates internal RefGas objects from gastables
- Gas destructor cleans up all internal resources
- All property methods are const — but const here is logical constness, not thread safety. The const evaluators write a shared cache, so two threads must not call them on the same Gas object even through a const reference (cl_Gas.hpp:74-78). That matches the framework-wide posture: BELFEM parallelizes with MPI and is not internally thread safe
- Temperature in Kelvin, pressure in Pascal (SI units throughout)
Creating a Custom Mixture
Vector<real> molar_fractions = {0.78084, 0.20946, 0.00934, 0.00040};
real T = 300.0, p = 101325.0;
real cp_mix = custom_air.cp(T, p);
real mu_mix = custom_air.mu(T, p);
real lambda_mix = custom_air.lambda(T, p);
Cell is a wrapper around the standard vector.
Definition cl_Cell.hpp:42
Column vector.
Definition cl_BZ_Vector.hpp:41
@ IDGAS
Definition en_GM_GasModel.hpp:19
Using a Real Gas (Cubic EoS)
real Z = p * v / (N2.R(T,p) * T);
virtual class for equation of state
Definition cl_GM_EoS.hpp:34
virtual real hdep(const real T, const real p) const
Definition cl_GM_EoS.cpp:189
@ PR
Definition en_GM_GasModel.hpp:21
Using a Helmholtz EoS (Cryogenic)
real v = hydrogen.v(T, p);
real h = hydrogen.h(T, p);
real cp = hydrogen.cp(T, p);
real w = hydrogen.c(T, p);
if (hydrogen.is_liquid()) {
}
@ NormalHydrogen
Definition en_Helmholtz.hpp:20
Equation of State Selection
Decision Tree
Need gas properties?
│
├─ Cryogenic fluid (H2, O2, CH4, N2)?
│ └─ Use HELMHOLTZ
│ - Accurate across phase boundaries
│ - Wide pressure/temperature range
│ - Handles liquid, vapor, supercritical
│
├─ Pressure > 10 bar?
│ ├─ Non-polar or weakly polar?
│ │ └─ Use SRK
│ │ - Good for hydrocarbons
│ │ - Moderate accuracy, fast
│ │
│ └─ Polar or near critical point?
│ └─ Use PR (Peng-Robinson)
│ - Better for polar molecules
│ - More accurate liquid density
│
└─ Low pressure (< 10 bar)?
└─ Use IDGAS
- Simple, fast
- Accurate for most gases at ambient conditions
Comparison Table
| EoS | Accuracy | Speed | Pressure Range | Typical Applications |
| IDGAS | Good (low p) | Fast | < 10 bar | Combustion, HVAC, ambient conditions |
| SRK | Good (moderate p) | Fast | 1-100 bar | Natural gas, petrochemical processing |
| PR | Excellent (high p) | Moderate | 1-1000 bar | Supercritical extraction, refrigeration |
| HELMHOLTZ | Excellent (all p) | Slow | All | Cryogenic storage, liquefaction, reference data |
When to Use Each Model
IDGAS:
SRK (Soave-Redlich-Kwong):
@ SRK
Definition en_GM_GasModel.hpp:20
PR (Peng-Robinson):
HELMHOLTZ:
@ Methane
Definition en_Helmholtz.hpp:23
@ Oxygen
Definition en_Helmholtz.hpp:22
Gas Mixtures
Creating Mixtures
Molar fraction basis (most common):
real T = 300.0, p = 101325.0;
real M_mix = mixture.M(T, p);
real R_mix = mixture.R(T, p);
real cp_mix = mixture.cp(T, p);
Mass fraction basis:
virtual void remix_mass(const Vector< real > &aMassFractions, bool aRemixHeat=true, bool aRemixTransport=true)
Definition cl_Gas.cpp:658
Mixture Rules
Thermodynamic properties (additive by molar fraction):
real T = 500.0, p = 101325.0;
real cp_mix = mixture.cp(T, p);
Viscosity (NASA RP-1311, Gordon & McBride, Eqs. 5.3, 5.5, 5.7):
real mu_mix = mixture.mu(T, p);
Thermal conductivity (NASA RP-1311, Eqs. 5.4, 5.6):
real lambda_mix = mixture.lambda(T, p);
Remixing
Change molar composition:
mixture.remix(new_fractions);
real cp_new = mixture.cp(T, p);
Change mass composition:
mixture.remix_mass(mass_fractions);
Reset to initial composition:
Performance note:
mixture.remix(new_fractions,
false,
false);
Accessing Mixture Composition
real chi_N2 = mixture.molar_fraction(0);
uint n = mixture.number_of_components();
A single chemical species with its caloric and transport properties.
Definition cl_GT_RefGas.hpp:76
unsigned int uint
Definition typedefs.hpp:30
Property Evaluation
State Variables
Finding state from different input pairs:
real T = 300.0, p = 101325.0;
real p_calc = air.
p(T, v);
real T_calc = air.
T(p, v);
real T(const real p, const real v) const
Definition cl_Gas.cpp:1570
real p(const real T, const real v) const
Definition cl_Gas.cpp:1528
real v(const real T, const real p) const
Definition cl_Gas.cpp:1546
Note for real gas:
- v(T, p) is closed-form (Cardano) for SRK/PR and a Newton iteration for the Helmholtz EoS
- p(T, v) is direct from EoS
- T(p, v) iterates for the Helmholtz EoS and is not implemented for SRK/PR (BELFEM_ERROR)
Thermodynamic Properties
Caloric properties:
real T = 400.0, p = 200000.0;
virtual real c(const real T, const real p) const
Definition cl_Gas.cpp:1659
virtual real cv(const real T, const real p) const
Definition cl_Gas.cpp:1627
virtual real gamma(const real T, const real p) const
Definition cl_Gas.cpp:1643
virtual real u(const real T, const real p) const
Definition cl_Gas.cpp:1675
Ideal gas relations:
real cp = idgas.cp(300.0, 101325.0);
real cv = idgas.cv(300.0, 101325.0);
real R = idgas.R(300.0, 101325.0);
#define BELFEM_ASSERT(aCheck,...)
Definition assert.hpp:244
Real gas departure functions:
real T = 120.0, p = 10e6;
real h = realgas.h(T, p);
real h_total = h_ideal + h_dep - eos->
hdep0(T);
virtual real sdep(const real T, const real p) const
Definition cl_GM_EoS.cpp:207
virtual real hdep0(const real T) const
Definition cl_GM_EoS.cpp:245
virtual real cpdep(const real T, const real p) const
Definition cl_GM_EoS.cpp:198
Transport Properties
real T = 300.0, p = 101325.0;
real Pr(const real T, const real p) const
Prandtl Number.
Definition cl_Gas.cpp:1788
Note:
- Transport properties are weakly pressure-dependent for most gases
- IDGAS: No pressure effect (from RefGas polynomials only)
- Real gas: Small pressure correction via density-dependent correlations
Thermodynamic Coefficients
real T = 300.0, p = 101325.0;
real kappa(const real T, const real p) const
isothermal compressibility coefficient
Definition cl_Gas.hpp:1332
real beta(const real T, const real p) const
isochoric stress coefficient
Definition cl_Gas.hpp:1324
real alpha(const real T, const real p) const
thermal expansion coefficient
Definition cl_Gas.hpp:1316
Ideal gas values:
real T = 300.0, p = 101325.0;
BELFEM_ASSERT(std::abs(alpha - 1.0/T) < 1e-9,
"α = 1/T for ideal gas");
Derivatives
real T = 400.0, p = 101325.0;
virtual real dsdp(const real T, const real p) const
Definition cl_Gas.cpp:1740
virtual real dhdp(const real T, const real p) const
Definition cl_Gas.cpp:3955
virtual real dsdT(const real T, const real p) const
Definition cl_Gas.cpp:1724
virtual real dcpdT(const real T, const real p) const
Definition cl_Gas.cpp:1611
Chemical Equilibrium
Gibbs Minimization
The Gas class can compute equilibrium composition by minimizing Gibbs free energy subject to elemental mass balance.
Theory:
At equilibrium, the total Gibbs energy is minimized:
G_total = Σ nᵢ·μᵢ → minimum
subject to:
Σ aᵢⱼ·nᵢ = bⱼ (elemental mass balance)
where:
- nᵢ = moles of species i
- μᵢ = chemical potential of species i
- aᵢⱼ = number of atoms of element j in species i
- bⱼ = total moles of element j
Computing Equilibrium
Example: Hydrogen combustion
Cell<string> species = {
"H2",
"O2",
"H2O",
"H",
"O",
"OH",
"H2O2"};
Vector<real> initial_guess = {0.2, 0.1, 0.5, 0.05, 0.05, 0.05, 0.05};
combustion.compute_equilibrium(T, p, equilibrium_fractions);
combustion.remix(equilibrium_fractions);
"%s: χ = %.6f",
species(i).c_str(),
equilibrium_fractions(i));
}
void message(const belfem::InfoLevel aInfoLevel, const std::string &aFormat, const Args ... aArgs)
Definition cl_Logger.hpp:144
size_t size() const
return the size of the Cell
Definition cl_Cell.hpp:181
uint32_t index_t
Definition typedefs.hpp:52
@ Default
Definition cl_Logger.hpp:35
Remix to Equilibrium (In-Place)
combustion.remix_to_equilibrium(T, p);
combustion.remix_to_equilibrium(T, p,
false,
false);
Gibbs Energy and Formation Enthalpies
combustion.Gibbs(T, gibbs);
combustion.dGibbsdT(T, dgibbs_dT);
combustion.Hf(T, Hf);
Elemental Balance Check
const Matrix<real> & formation = combustion.formation_table();
Dense column-major matrix.
Definition cl_BZ_Matrix.hpp:28
Common Equilibrium Scenarios
1. Combustion products:
Cell<string> products = {
"CO2",
"H2O",
"N2",
"O2",
"CO",
"H2",
"NO",
"OH"};
Vector<real> guess = {0.1, 0.2, 0.6, 0.05, 0.01, 0.01, 0.01, 0.01};
exhaust.remix_to_equilibrium(1800.0, 101325.0);
2. Dissociation at high temperature:
for (
real T = 1000.0; T <= 5000.0; T += 500.0) {
hot_gas.remix_to_equilibrium(T, 101325.0);
real chi_H = hot_gas.molar_fraction(1);
}
3. Cryogenic equilibrium (ortho/para hydrogen):
Compressible Flow Applications
Isentropic Relations
Finding state after isentropic compression/expansion:
real T1 = 300.0, p1 = 101325.0;
real T2_check = T1 * std::pow(p2/p1, (gamma-1)/gamma);
real isen_p(const real T0, const real p0, const real T1) const
get an isentropic pressure
Definition cl_Gas.cpp:2352
real isen_T(const real T0, const real p0, const real p1) const
get an isentropic temperature
Definition cl_Gas.cpp:2312
Isentropic efficiency:
real T1 = 300.0, p1 = 101325.0, p2 = 500000.0;
real T2_actual = T1 + (T2_isentropic - T1) / eta_c;
real T3 = 1500.0, p3 = 500000.0, p4 = 101325.0;
real T4_actual = T3 - eta_t * (T3 - T4_isentropic);
Total (Stagnation) Conditions
Computing stagnation temperature and pressure:
real p_static = 101325.0;
air.
total(T_static, p_static, U, T_total, p_total);
void total(const real T, const real p, const real &u, real &aTt, real &aPt) const
calculate the total state
Definition cl_Gas.cpp:2382
Mach number from static and total conditions:
real M2 = (T_total/T_static - 1.0) * 2.0 / (gamma - 1.0);
Normal Shock Relations
Analyzing a normal shock:
real T1 = 300.0, p1 = 101325.0, U1 = 600.0;
air.
shock(T1, p1, U1, T2, p2, U2);
"Normal shock: M1 = %.3f → M2 = %.3f, p2/p1 = %.3f",
M1, M2, p2/p1);
void shock(const real T1, const real p1, const real &u1, real &T2, real &p2, real &u2) const
perpendicular shock
Definition cl_Gas.cpp:3469
Oblique Shock
Computing oblique shock with flow deflection:
real T1 = 300.0, p1 = 101325.0, U1 = 700.0;
air.
shock(T1, p1, U1, alpha, T2, p2, U2, beta);
"Oblique shock: α = %.1f°, β = %.1f°",
const real deg
degree
Definition constants.hpp:55
Prandtl-Meyer Expansion
Supersonic expansion around a corner:
real T1 = 300.0, p1 = 101325.0, U1 = 500.0;
real prandtl_meyer(const real T1, const real p1, const real &u1, const real &alpha, real &T2, real &p2, real &u2) const
Prandtl-Meyer turn of a supersonic stream around a corner, for a thermally perfect ideal gas.
Definition cl_Gas.cpp:3373
The closed-form perfect-gas angle is a private helper that only seeds the iteration; prandtl_meyer() returns the downstream Mach number.
Area-Mach Number Relation (Isentropic Flow)
real term = (2.0/(gamma+1.0)) * (1.0 + (gamma-1.0)/2.0 * M1*M1);
real A_over_Astar = (1.0/M1) * std::pow(term, (gamma+1.0)/(2.0*(gamma-1.0)));
Advanced Topics
Component-Specific Properties
For mixtures, access properties of individual components:
real T = 400.0, p = 101325.0;
real v_N2 = air.
v(i, T, p);
real h_N2 = air.
h(i, T, p);
Direct EoS Access
p = 10e6;
real T_crit, p_crit, v_crit;
virtual real p(const real T, const real v) const =0
pressure in Pa
virtual void eval_critical_point(real &T, real &p, real &v) const =0
virtual real dvdT(const real T, const real v) const
Definition cl_GM_EoS.cpp:69
virtual real dpdv(const real T, const real v) const =0
virtual real dpdT(const real T, const real v) const =0
Helmholtz Derivatives
For Helmholtz EoS, access fundamental equation derivatives:
if (helm != nullptr) {
}
a model for the helmholtz energy, specifically user for cryogenic fluids
Definition cl_GM_Helmholtz.hpp:60
real s(const real T, const real p) const
Definition cl_GM_Helmholtz.cpp:371
real cp(const real T, const real p) const
Definition cl_GM_Helmholtz.cpp:392
real h(const real T, const real p) const
Definition cl_GM_Helmholtz.cpp:360
real w(const real T, const real p) const
speed of sound in m/s ( helmholtz only )
Definition cl_GM_Helmholtz.cpp:404
Vapor Pressure Curves
For Helmholtz models, vapor pressure correlation:
virtual real p_vap(const real T) const
Definition cl_GM_EoS.cpp:307
virtual real T_vap(const real p) const
Definition cl_GM_EoS.cpp:315
Performance Optimization
Minimize Object Creation
Following BELFEM's manual memory philosophy:
for (int i = 0; i < 10000; ++i) {
real cp = air.
cp(300.0, 101325.0);
}
for (int i = 0; i < 10000; ++i) {
real cp = air.
cp(300.0 + i*0.1, 101325.0);
}
Spline Evaluation
Gas always evaluates its own mixture splines (mHeatSpline, mViscositySpline, mConductivitySpline), rebuilt on remix(); there is no mode to switch, and the RefGas mode of the components does not affect it.
Preallocate Work Arrays
For mixture calculations, Gas preallocates work arrays:
Avoid Unnecessary Remixing
for (int i = 0; i < 1000; ++i) {
mixture.remix(same_fractions);
real cp = mixture.cp(T, p);
}
mixture.remix(new_fractions);
for (int i = 0; i < 1000; ++i) {
real cp = mixture.cp(T + i*0.1, p);
}
Use Appropriate EoS for Speed
Performance ranking (fastest to slowest):
- IDGAS - Direct polynomial evaluation
- SRK - Cubic solution (closed-form Cardano root)
- PR - Cubic solution (closed-form Cardano root, same cost as SRK)
- HELMHOLTZ - Complex derivatives (10-100× slower)
Benchmark Example
for (int i = 0; i < 100000; ++i) {
real cp = idgas.
cp(300.0 + i*0.001, 101325.0);
}
uint64_t time_idgas = timer.
next();
for (int i = 0; i < 100000; ++i) {
real cp = pr.cp(300.0 + i*0.001, 101325.0);
}
uint64_t time_pr = timer.
stop();
"IDGAS: %lu ms, PR: %lu ms, Ratio: %.2f",
time_idgas, time_pr, (
real)time_pr / time_idgas);
High-resolution wall-clock timing.
Definition cl_Timer.hpp:28
uint64_t stop()
Definition cl_Timer.hpp:43
uint64_t next()
Definition cl_Timer.hpp:53
void reset()
Definition cl_Timer.hpp:63
Troubleshooting
Issue: Convergence Failure in v(T,p) (Helmholtz EoS only)
BELFEM_ERROR: Too many iterations for T=... K, p=... bar, rho=... kg/m^3, relax=...
Cause: Near critical point or phase boundary, EoS may have multiple solutions or poor conditioning.
Solution:
for (int iter = 0; iter < 100; ++iter) {
real p_calc = eos->
p(T, v_guess);
v_guess -= (p_calc - p) / dpdv;
if (std::abs(p_calc - p) < 1e-6) break;
}
Issue: Negative Heat Capacity
No check exists; a negative cp from a cubic EoS inside the two-phase dome is returned as is.
Cause: Unphysical state (inside two-phase region or extrapolation beyond valid range).
Solution:
real T_crit, p_crit, v_crit;
if (T < T_crit && p > p_crit) {
}
Note: Mixture Composition Need Not Sum to 1.0
Molar and mass fractions are normalized to unity inside remix() / remix_mass(); a non-normalised input is accepted.
Issue: Equilibrium Calculation Fails
BELFEM_ERROR: To many iterations while trying to find chemical equilibrium.
Cause: Poor initial guess or elemental imbalance.
Solution:
Further Reading
Module Documentation
- README.md - Quick reference for gasmodels module
Related Modules
Literature References
Equations of State:
- Soave (1972), "Equilibrium Constants from a Modified Redlich-Kwong Equation of State", Chemical Engineering Science, 27(6):1197-1203
- Peng & Robinson (1976), "A New Two-Constant Equation of State", Industrial & Engineering Chemistry Fundamentals, 15(1):59-64
- Reid, Prausnitz & Poling (1987), "The Properties of Gases and Liquids" (4th ed.), McGraw-Hill
Helmholtz Models:
- Leachman et al. (2009), "Fundamental Equations of State for Parahydrogen, Normal Hydrogen, and Orthohydrogen", J. Phys. Chem. Ref. Data, 38(3):721-748
- Setzmann & Wagner (1991), "A New Equation of State and Tables of Thermodynamic Properties for Methane", J. Phys. Chem. Ref. Data, 20(6):1061-1155
- Schmidt & Wagner (1985), "A New Form of the Equation of State for Pure Substances", Fluid Phase Equilibria, 19(3):175-200
- Span et al. (2000), "A Reference Equation of State for the Thermodynamic Properties of Nitrogen", J. Phys. Chem. Ref. Data, 29(6):1361-1433
Mixture Rules:
- Gordon & McBride (1994), NASA RP-1311, Eqs. (5.3)-(5.7)
- Wilke (1950), "A Viscosity Equation for Gas Mixtures", J. Chem. Phys., 18:517-519
- Bird, Stewart & Lightfoot (2007), "Transport Phenomena" (2nd ed.), Wiley
Chemical Equilibrium:
- Smith & Missen (1982), "Chemical Reaction Equilibrium Analysis", Wiley-Interscience
- Gordon & McBride (1994), "Computer Program for Calculation of Complex Chemical Equilibrium Compositions", NASA RP-1311
Compressible Flow:
- Anderson (2003), "Modern Compressible Flow" (3rd ed.), McGraw-Hill
- Shapiro (1953), "The Dynamics and Thermodynamics of Compressible Fluid Flow", Ronald Press
Last Updated: 2026-01-30 Maintainer: BELFEM development team