The Thermodynamics.jl package implements the thermodynamic formulation of the CliMA Earth System Model (Yatunin et al., 2026). It provides a consistent framework for moist thermodynamics based on the Rankine-Kirchhoff approximations (Romps, 2021), and thermodynamic functions for moist air including all phases of water (vapor, liquid, and ice).
| Documentation | |
| Docs Build | |
| GHA CI | |
| Code Coverage | |
| Downloads |
using Pkg
Pkg.add("Thermodynamics")
Pkg.add("ClimaParams")Thermodynamics.jl provides a functional, stateless API. You import the package (TD) and pass a parameter set plus thermodynamic variables (e.g., density, internal energy, specific humidities) directly to functions.
import Thermodynamics as TD
# Use RootSolvers for the saturation adjustment method
import RootSolvers as RS
using ClimaParams
# 1. Create thermodynamic parameters
# (requires a definition of the parameter set, e.g. from ClimaParams)
params = TD.Parameters.ThermodynamicsParameters(Float64)
# 2. Define your thermodynamic variables
ρ = 1.1 # Density [kg/m³]
e_int = 200000.0 # Internal energy [J/kg]
q_tot = 0.015 # Total specific humidity [kg/kg]
q_liq = 0.005 # Liquid specific humidity [kg/kg]
q_ice = 0.001 # Ice specific humidity [kg/kg]
# 3. Compute properties directly
T = TD.air_temperature(params, e_int, q_tot, q_liq, q_ice)
p = TD.air_pressure(params, T, ρ, q_tot, q_liq, q_ice)To find the phase equilibrium temperature and phase partition from thermodynamic variables (e.g., given ρ, e_int, q_tot), use saturation_adjustment:
# Solve for phase equilibrium (T, q_liq, q_ice) given (ρ, e_int, q_tot)
# using SecantMethod
sol = TD.saturation_adjustment(
RS.SecantMethod, # Root-solving method
params, # Parameter set
TD.ρe(), # Formulation: Density & Internal Energy
ρ, e_int, q_tot, # Input variables
10, # Max iterations
1e-3 # Relative tolerance
)
println("Equilibrium T: ", sol.T)
println("Liquid q: ", sol.q_liq)
println("Ice q: ", sol.q_ice)
println("Converged: ", sol.converged)- Moist air thermodynamics including all water phases (vapor, liquid, ice).
- Stateless, functional API for flexibility and integration.
- Consistent formulation assuming a calorically perfect gas mixture.
- Type-stable and GPU-compatible (CUDA.jl, AMDGPU.jl, etc.).
- AD-compatible (ForwardDiff.jl, etc.) for differentiable physics.
- Zero-allocation design for core functions.
- Multiple formulations: Solve for phase equilibrium from
(ρ, e_int),(p, h),(p, θ_li), etc. - Extensible parameters: Easily adapt to different planetary atmospheres via
ClimaParams.
Functions in Thermodynamics.jl are stateless. They take a ThermodynamicsParameters struct and the necessary thermodynamic variables (e.g., T, ρ, q...) as arguments. This design fits naturally into large-scale simulations (e.g., with ClimaAtmos.jl).
The working fluid is moist air (dry air + water vapor + liquid water + ice, which may include precipitation). We treat it as a mixture of ideal gases and condensed phases, ensuring rigorous mass and energy conservation.
All quantities are derived from the calorically perfect gas assumption with constant specific heat capacities. This provides a consistent, closed set of equations for saturation vapor pressures (the so-called Rankine-Kirchhoff approximation), latent heats, and other derived quantities.
- Mathematical Formulation - Theoretical background.
- How-To Guide - Recipes and examples.
- API Reference - Detailed function documentation.
Thermodynamics.jl is the thermodynamic core for the CliMA ecosystem, including:
For questions, check the documentation or open an issue on GitHub.