Directory macros/luatex/generic/luacoolprop
luacoolprop 1.1.0
luacoolprop is a format-generic LuaTeX interface to the CoolProp shared library. It computes thermodynamic states in Lua and emits PGFPlots code for PH (pressure-enthalpy), log-log PV (pressure-specific-volume), linear TS (temperature-entropy), linear HS (enthalpy-entropy), and PT (pressure-temperature, logarithmic in pressure) diagrams of pure fluids. It requires PGFPlots 1.18 or later but never changes the document's selected PGFPlots compatibility level.
The package supports saturation curves, quality lines, diagram-specific background families, thermodynamic process paths, stable curve names, per-curve overrides, and automatic label placement delegated to pgfplots-autonode.
The autonomous pgfplots-autonode library is included with the package. It can also label ordinary PGFPlots curves independently of LuaCoolProp.
The final stage of the methane Linde-process tutorial: a computed PH diagram, coupled flows, state readings, and energy balances.
An intermediate butane PV tutorial stage, comparing a real-fluid isotherm with its dilute-gas approximation.
Both images are rasterized from PDFs built by the package's TeX sources. Run scripts/build-examples.sh followed by scripts/build-readme-images.sh to regenerate them; no external exercise artwork is bundled.
!WARNING
This package has been vibe-coded with ChatGPT. Substantial parts of its
design, code, documentation, and tests were generated or revised with AI
assistance. AI output can be plausible and still be wrong. CTAN publication
is not a safety certification: inspect the source and independently validate
all thermodynamic results before industrial, regulated, safety-critical, or
other high-consequence use.
Author and Current Maintainer: Christophe Jorssen <christophe.jorssen@gmail.com>. Version 1.1.0 is dated 2026-09-18; version 1.0.0 was distributed to a small group on 2026-09-05. The work is maintained and distributed under the LaTeX Project Public License 1.3c or later. The public project repository is github.com/cjorssen/luacoolprop.
Citing CoolProp
If you publish work based on thermodynamic results produced with LuaCoolProp, please cite the underlying CoolProp project as its authors request: Ian H. Bell, Jorrit Wronski, Sylvain Quoilin, and Vincent Lemort, “Pure and Pseudo-pure Fluid Thermophysical Property Evaluation and the Open-Source Thermophysical Property Library CoolProp,” Industrial & Engineering Chemistry Research 53(6), 2498–2508 (2014), doi:10.1021/ie4033999, and coolprop.org. The official citation page also provides BibTeX. Record the CoolProp version used for reproducibility.
Files
luacoolprop.tex: generic TeX interface based onpgfkeys.luacoolprop.lua: FFI declarations, CoolProp wrappers, thermodynamic calculations, curve generation, process validation, and PGFPlots serialization.luacoolprop.sty: LaTeX wrapper.t-luacoolprop.tex: ConTeXt wrapper.p-luacoolprop.tex: plain TeX wrapper.luacoolprop-manual.tex: English user manual, exhaustive TeX reference, command/key indexes, and developer reference.docs/luacoolprop-tex-reference.tex: command-by-command and key-by-key TeX reference with executable source/result examples.docs/pgfplots-autonode-reference.tex: complete reference for the bundled autonomous PGFPlots library.docs/r717-teaching-tutorial.tex: instructor-oriented tutorial producing a blank R717 worksheet diagram and its annotated model-solution diagram.docs/r134a-air-conditioner-tutorial.tex: advanced six-stage R134a tutorial progressing from phase regions to a fully quantified air-conditioning cycle.docs/butane-pv-tutorial.tex: five-stage butane PV tutorial covering phase regions, the ideal-gas limit, intersection-defined states, a rigid-tank isochore, and numerical process exports.docs/r1234yf-heat-pump-tutorial.tex: worksheet/model-solution tutorial for an R1234yf swimming-pool heat pump, including saturation-derived pressures, a four-device PH cycle, and automated condenser-power calculation.docs/methane-linde-tutorial.tex: expert worksheet/progressive-solution tutorial for methane liquefaction by the Linde process, including coupled separator, regenerator, mixer, three-stage compression, and live power balances.docs/luacoolprop-lua-api.md: detailed Lua API, ownership, units, error, extension, and contribution reference.examples/: compilable LaTeX, plain TeX, ConTeXt, and Lua API examples with reproducible compilation logs.pgflibrarypgfplots.autonode.code.tex: autonomous PGFPlots library for automatic label placement.pgfplots-autonode.lua: numerical backend of theautonodelibrary.pgfplots-autonode.styandpgfplots-autonode.code.tex: alternate loaders.
Quick start: automatic PH diagram
The LaTeX wrapper uses siunitx for generated numbers and units. If siunitx was loaded first, LuaCoolProp preserves its package options and \sisetup configuration. Otherwise the wrapper loads it with the standard defaults. Plain TeX and ConTeXt do not acquire this LaTeX dependency.
Numeric input is locale independent: always use . as the decimal separator, even if siunitx displays decimal commas. Decimal scientific notation and an attached recognized process unit are accepted, for example 1.2E5Pa. Malformed numbers, units, booleans, lists, modes, presets, and bounds stop the build instead of silently selecting a fallback.
\documentclass[border=3mm]{standalone} \usepackage{luacoolprop} \pgfplotsset{compat=1.18} \begin{document} \LCPPHDiagram[ fluid=R134a, quality step=0.2, isotherm=true, temperature values={-20,0,20,40,60}, labels=true ] \end{document}
Compile with lualatex --shell-escape after selecting the external CoolProp shared library as described below. The source is also available as examples/ph-readme-automatic.tex.
Quick start: choose the curves in a PGFPlots axis
Use a normal PGFPlots axis when you want to choose each family and control the axes yourself. auto node placement enables the bundled autonomous label solver; it does not take control of unrelated axes.
\documentclass[border=3mm]{standalone} \usepackage{luacoolprop} \pgfplotsset{compat=1.18} \begin{document} \begin{tikzpicture} \begin{axis}[ lcp fluid=R134a, width=12cm,height=8cm, ymode=log,grid=both, xlabel={$h/(\mathrm{kJ\,kg^{-1}})$}, ylabel={$p/\mathrm{bar}$}, auto node placement ] \LCPAddPHQuality[quality values={0,0.5,1},labels=true] \LCPAddPHIsotherms[temperature values={-20,0,20,40,60},labels=true] \end{axis} \end{tikzpicture} \end{document}
This exact source is examples/ph-readme-selected.tex.
Pressure-specific-volume diagrams
PV is a registered diagram type with a log-log default axis. Quality curves, isotherms, and isentropes use the shared option vocabulary; the abscissa is mass-specific volume in m³/kg by default.
\LCPPVDiagram[ fluid=R134a, isotherm=true, isentrope=true, quality values={0,0.25,0.5,0.75,1}, temperature values={-20,0,20,40,60}, entropy values={1.6,1.8,2.0}, labels=true ]
The low-level commands \LCPAddPVQuality, \LCPAddPVIsotherms, \LCPAddPVIsentropes, \LCPAddPVPlots, and \LCPAddPVProcess work inside an existing loglogaxis. PV process coordinate exports use scaled specific volume for X while retaining raw SI volume in the ...SpecificVolumeSI macros.
Temperature-entropy diagrams
TS is a registered diagram type with linear axes. Mass-specific entropy is shown in kJ/(kg K) and absolute temperature in K by default. Quality curves and constant mass-specific enthalpy curves use the shared selection, styling, label, and autonode vocabulary.
\LCPTSDiagram[ fluid=R134a, isenthalp=true, quality values={0,0.25,0.5,0.75,1}, enthalpy values={200,250,300,350,400,450}, labels=true ]
The low-level commands \LCPAddTSQuality, \LCPAddTSIsenthalps, \LCPAddTSPlots, and \LCPAddTSProcess work inside an existing linear axis. TS process coordinate exports use scaled entropy for X and the selected scaled/offset temperature coordinate for Y while retaining absolute temperature and every other resolved property in SI.
Enthalpy-entropy diagrams
HS is a registered linear diagram type with mass-specific entropy on the horizontal axis and mass-specific enthalpy on the vertical axis. It supports qualities, isochores, isotherms, and isobars, including a common critical-limit endpoint and continuous two-phase isotherm/isobar segments.
\LCPHSDiagram[ fluid=Water, quality step=0.2, isochore=true, specific volume values={0.01,0.1,1}, isotherm=true, temperature values={100,200,300,400}, isobar=true, isobar values={0.1,1,10,100}, labels=true ]
The low-level commands \LCPAddHSQuality, \LCPAddHSIsochores, \LCPAddHSIsotherms, \LCPAddHSIsobars, \LCPAddHSPlots, and \LCPAddHSProcess work inside an existing linear axis. HS process exports use scaled entropy for X and scaled enthalpy for Y, with all resolved thermodynamic properties retained in SI.
Pressure-temperature diagrams
PT uses temperature on the horizontal axis and a logarithmic pressure axis. Its default background is the single liquid-vapour coexistence curve from the triple point to the critical point. Saturated liquid and saturated vapour have the same (T,p) coordinates, so this locus is intentionally not represented as separate Q=0 and Q=1 curves. Isentropes, isenthalps, and isochores are optional.
\LCPPTDiagram[ fluid=R134a, temperature axis unit=celsius, pressure axis unit=bar, isentrope=true, entropy values={1.4,1.7,2.0}, isenthalp=true, enthalpy values={200,300,400}, isochore=true, specific volume values={0.001,0.01,0.1} ]
The low-level commands are \LCPAddPTPhaseEnvelope (also \LCPAddPTSaturation), \LCPAddPTIsentropes, \LCPAddPTIsenthalps, \LCPAddPTIsochores, \LCPAddPTPlots, and \LCPAddPTProcess.
Scientific and coordinate contracts
PH, PV, TS, HS, and PT are peers in one registry. Their background capabilities are validated: PH provides quality/isotherm/isentrope/isochore, PV provides quality/isotherm/isentrope, TS provides quality/isenthalp, and HS provides quality/isochore/isotherm/isobar, while PT provides one phase envelope plus isentrope/isenthalp/isochore. An unsupported family switch is an error; all six conserved-property process types remain projectable in every diagram.
Diagram construction accepts only CoolProp fluids reported as pure. Mixtures and predefined blends are rejected because this release does not implement mixture phase envelopes. The low-level Lua wrappers remain mixture-capable.
At the critical state, vapor quality is undefined. When a quality curve reaches the critical pressure, its final graphical record is a quality-independent limiting endpoint, not a state carrying the curve's subcritical quality value.
Use semantic coordinate keys such as pressure axis unit=mpa, enthalpy axis unit=jkg, specific volume axis unit=lkg, entropy axis unit=jkgk, and temperature axis unit=celsius. Each changes the numeric coordinate and generated label together. Raw scale keys are retained for advanced use and produce an explicit scaled-SI label.
Enthalpy and entropy reference origins are selected at initialization with \LCPSetReferenceState{DEF|IIR|ASHRAE|NBP} or reference state=.... The first diagram calculation locks the convention for that fluid. Use the same convention for every compared state and use enthalpy differences in energy balances.
Adaptive curves retain disconnected valid components instead of drawing across rejected CoolProp states. domain policy=ignore|warning|error controls the diagnostic; PGFPlots serialization always uses explicit jumps.
Process path example
\LCPAddPHProcess[ fluid=R134a, type=isentrope, from={pressure=1bar,quality=1}, to={pressure=10bar}, style={very thick,-Latex}, label={$1\to2$}, mark endpoints=true ]
Diagram API
Diagram identifiers are uppercase coordinate pairs. \LCPPHDiagram[<options>], \LCPPVDiagram[<options>], \LCPTSDiagram[<options>], and \LCPHSDiagram[<options>], and \LCPPTDiagram[<options>] are the convenience spellings; \LCPDiagram{PH}[<options>], \LCPDiagram{PV}[<options>], and \LCPDiagram{TS}[<options>], \LCPDiagram{HS}[<options>], and \LCPDiagram{PT}[<options>] are their generic equivalents. The same dispatch API is available for plots, families, and processes:
\LCPAddDiagramPlots{PH}[<options>] \LCPAddDiagramFamily{PH}{isotherm}[<options>] \LCPAddDiagramProcess{PH}[<options>]
Additional implementations can register further identifiers behind the same interface. Mixed-case commands and abbreviated keys are accepted aliases; the canonical interface uses uppercase diagram codes and full property names such as quality, temperature, and pressure.
The developer-facing Lua API is documented in docs/luacoolprop-lua-api.md. It covers the CoolProp FFI wrappers, deterministic AbstractState cleanup, SI-unit contracts, PH, PV, TS, HS, and PT point/process records, renderer options, error handling, and the stable registration shape for custom diagram implementations.
Autonomous PGFPlots library
pgfplots-autonode is part of this work as a regular PGFPlots library. LuaCoolProp loads it automatically. It can also be used independently after loading the PGFPlots frontend for the current format:
\usepgfplotslibrary{autonode}
The frontend is \usepackage{pgfplots} in LaTeX, \input pgfplots.tex in plain TeX, and \usemodule[t][pgfplots] in ConTeXt. A labelled plot uses \pgfplotsautonode as a trailing path command:
\begin{axis}[auto node placement,auto node algorithm=repair] \addplot[domain=0:4] {x} \pgfplotsautonode[preferred pos=0.65,sloped=true]{$y=x$}; \end{axis}
auto node placement is the lifecycle switch which runs the joint solver at the end of the axis. It is mandatory for standalone use and for LuaCoolProp family commands inside a manually written axis; omitting it produces a clear warning. High-level commands such as \LCPPHDiagram install it on the axis they create without changing unrelated PGFPlots axes.
The standalone examples autonode-latex-basic.tex, plain-autonode-basic.tex, and context-autonode-basic.tex exercise the same library implementation in all three formats. The pgfplots-autonode LaTeX package and direct code loader are alternate entry points.
CoolProp installation and runtime
CoolProp is an external native dependency. It is never included in the LuaCoolProp package or its CTAN archive. Obtain a binary from the official shared-library page or build a reviewed revision from the official CoolProp repository. The library is normally named libCoolProp.dylib on macOS, libCoolProp.so on Linux, and CoolProp.dll on Windows.
The CoolProp library and the TeX engine process must have matching architectures. Use an absolute LUACOOLPROP_LIB path, and record the CoolProp tag or commit used to produce reproducible documents. Loading a shared library executes native code, so use only an official binary or one built from source you trust.
Security warning: --shell-escape
!CAUTION
LuaCoolProp requires full--shell-escapebecause TeX Live exposes the
LuaTeX FFI module only in a shell-escape-enabled typesetting process. This
option lets the document and every loaded class, package, module, and input
file run external programs with your user permissions. Compile only trusted
sources, preferably in a sandbox or isolated account without secrets or
elevated privileges. Never run the TeX engine asrootor Administrator.
Restricted shell escape is not sufficient for this FFI mechanism.
LuaCoolProp uses FFI to load the CoolProp C API. It does not download or compile CoolProp and does not issue shell commands while typesetting, but that does not reduce the authority granted to the rest of the document by --shell-escape.
Install the TeX package
Once the package is available through a TeX distribution, install it with that distribution's package manager (tlmgr install luacoolprop for TeX Live, or the MiKTeX Console on MiKTeX). CoolProp must still be installed separately.
For a manual TDS installation, unpack luacoolprop.tds.zip at the root of a personal TEXMF tree. On TeX Live this is normally:
texmf_home=$(kpsewhich -var-value=TEXMFHOME) mkdir -p "$texmf_home" unzip luacoolprop.tds.zip -d "$texmf_home" mktexlsr "$texmf_home"
Do not unpack the browsing archive luacoolprop.zip directly into a TEXMF tree: it contains documentation and source files in CTAN's browsing layout.
Reproducible source checkout
Building from source requires Git, CMake, Ninja, Python, a C++ compiler, and CoolProp's submodule prerequisites. Keep the checkout beside, never inside, this repository. This example pins the v8.0.0 tag; replace it deliberately when adopting another reviewed release.
git clone https://github.com/CoolProp/CoolProp.git ../coolprop-src git -C ../coolprop-src fetch --tags git -C ../coolprop-src checkout --detach v8.0.0 git -C ../coolprop-src submodule update --init --recursive
macOS
Install Apple's command-line developer tools plus Git, CMake, and Ninja. For a reproducible build, perform the pinned common checkout above first. The bundled helper then reuses ../coolprop-src, updates submodules, and puts the build in a sibling directory. If no checkout exists, it can clone the current default branch for exploratory use:
./scripts/build-coolprop-macos.sh
It defaults to arm64 on Apple Silicon and prints the final absolute library path. Match an Intel TeX engine or request a universal binary with:
COOLPROP_MACOS_ARCH=x86_64 ./scripts/build-coolprop-macos.sh
COOLPROP_MACOS_ARCH='arm64;x86_64' ./scripts/build-coolprop-macos.sh
The separate ./scripts/update-coolprop.sh v8.0.0 command is a maintainer workflow for intentionally adopting another CoolProp API. It also regenerates the marked FFI declaration block in luacoolprop.lua, so end users should not run it as a routine installation step. It accepts 8.0.0 and resolves the leading v. The equivalent build-only CMake commands are:
cmake -S ../coolprop-src -B ../coolprop-build-macos-arm64 -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_OSX_ARCHITECTURES=arm64 \ -DCOOLPROP_SHARED_LIBRARY=ON \ -DCOOLPROP_STATIC_LIBRARY=OFF \ -DCOOLPROP_OBJECT_LIBRARY=OFF cmake --build ../coolprop-build-macos-arm64 --target CoolProp export LUACOOLPROP_LIB="$PWD/../coolprop-build-macos-arm64/libCoolProp.dylib"
Linux
Install Git, CMake, Ninja, Python, a C++ toolchain, and 7-Zip with the system package manager. For Debian or Ubuntu, the usual package names are git, cmake, ninja-build, build-essential, python3, and p7zip-full. After the pinned checkout above:
cmake -S ../coolprop-src -B ../coolprop-build-linux -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCOOLPROP_SHARED_LIBRARY=ON \ -DCOOLPROP_STATIC_LIBRARY=OFF \ -DCOOLPROP_OBJECT_LIBRARY=OFF cmake --build ../coolprop-build-linux --target CoolProp export LUACOOLPROP_LIB="$PWD/../coolprop-build-linux/libCoolProp.so"
A system-wide install and sudo are not required. Keeping the versioned build outside the package and selecting it with an absolute path is easier to audit.
Windows
The simplest setup is to extract an official precompiled x64 DLL to a stable directory outside the LuaCoolProp tree. For a source build, install Git, CMake, Python, and either Ninja with a compatible C++ compiler or Visual Studio. In PowerShell, a Ninja build is:
git clone https://github.com/CoolProp/CoolProp.git ..\coolprop-src git -C ..\coolprop-src fetch --tags git -C ..\coolprop-src checkout --detach v8.0.0 git -C ..\coolprop-src submodule update --init --recursive cmake -S ..\coolprop-src -B ..\coolprop-build-windows -G Ninja ` -DCMAKE_BUILD_TYPE=Release ` -DCOOLPROP_SHARED_LIBRARY=ON ` -DCOOLPROP_STATIC_LIBRARY=OFF ` -DCOOLPROP_OBJECT_LIBRARY=OFF cmake --build ..\coolprop-build-windows --target CoolProp $env:LUACOOLPROP_LIB = (Resolve-Path ..\coolprop-build-windows\CoolProp.dll).Path
With Visual Studio 2022, use the matching x64 multi-configuration build:
cmake -S ..\coolprop-src -B ..\coolprop-build-vs ` -G "Visual Studio 17 2022" -A x64 ` -DCOOLPROP_SHARED_LIBRARY=ON ` -DCOOLPROP_STATIC_LIBRARY=OFF ` -DCOOLPROP_OBJECT_LIBRARY=OFF cmake --build ..\coolprop-build-vs --config Release --target CoolProp $env:LUACOOLPROP_LIB = (Resolve-Path ..\coolprop-build-vs\Release\CoolProp.dll).Path
Some CMake versions place the DLL in a different configuration subdirectory; locate the newly built CoolProp.dll under the selected build directory if needed. In cmd.exe, use set "LUACOOLPROP_LIB=C:\absolute\path\CoolProp.dll".
Compile a document
Set LUACOOLPROP_LIB in the terminal that launches TeX, then use the engine belonging to the document format.
LaTeX:
export LUACOOLPROP_LIB=/absolute/path/to/libCoolProp.dylib
lualatex --shell-escape myfile.tex
Plain TeX documents load p-luacoolprop.tex and use LuaTeX:
\input p-luacoolprop.tex \pgfplotsset{compat=1.18} \LCPPHDiagram[fluid=R134a] \bye
luatex --shell-escape myfile.tex
ConTeXt documents select the t- module explicitly, because this repository also contains the plain-TeX p- wrapper:
\usemodule[t][luacoolprop] \pgfplotsset{compat=1.18} \starttext \LCPPHDiagram[fluid=R134a] \stoptext
context --luatex --shell-escape myfile.tex
The --luatex switch selects ConTeXt MkIV. It is required because LuaCoolProp uses the LuaTeX FFI module, which is not available in LuaMetaTeX/LMTX. Full installation, loader diagnostics, and security guidance are in luacoolprop-manual.pdf.
Reproducible document build
The repository build exercises all three wrappers. Files named plain-*.tex are built with luatex, files named context-*.tex with ConTeXt MkIV, and all other examples plus the manual with lualatex. The manual build also regenerates its separate command and key/value indexes with makeindex:
LUACOOLPROP_LIB=/path/to/libCoolProp.dylib ./scripts/build-examples.sh
Console logs are stored in examples/logs/ and build-logs/; PDFs are placed next to their sources. Sandboxed builds may set LUACOOLPROP_TEX_CACHE to a writable directory for the LaTeX and plain-TeX font cache.
The same build also compiles every teaching driver in tutorial/ before the manual. Their logs are stored in tutorial/logs/; shared implementations in tutorial/source/ keep the generated diagrams synchronized with the manual. This includes the R717 and R1234yf worksheet/solution pairs, the six-page advanced R134a air-conditioner construction, the five-page butane PV construction, and the six-page expert methane Linde-process correction.
Complete validation
The main test entry point checks POSIX shell syntax, verifies that every public TeX command and key remains represented in the exhaustive reference, exercises the numerical LuaCoolProp and autonomous label-placement APIs, and finally rebuilds every LaTeX, plain TeX, and ConTeXt example plus the indexed manual:
LUACOOLPROP_LIB=/path/to/libCoolProp.dylib ./scripts/test.sh
The numerical tests compare independent CoolProp entry points and physical invariants instead of freezing values from one CoolProp release. Test logs are written to build-logs/; document logs retain their established locations in build-logs/ and examples/logs/.
After a successful local test, create and installation-test both CTAN archives listed by MANIFEST.txt with:
./scripts/package-release.sh
The command writes luacoolprop.zip and luacoolprop.tds.zip. The browsing archive contains the exact top-level directory luacoolprop/ and embeds the TDS archive as requested by CTAN. Both archives use SOURCE_DATE_EPOCH when set, otherwise the canonical release epoch recorded in VERSION; file modes, timestamps, and member order are normalized. The installed-tree test resolves no runtime file from the repository and covers LuaLaTeX, plain LuaTeX, ConTeXt MkIV, and standalone pgfplots-autonode.
Copyright (C) 2026 Christophe Jorssen. LuaCoolProp, including pgfplots-autonode, is distributed under LPPL 1.3c or later with maintenance status maintained. CoolProp is a separate MIT-licensed dependency and is not included.
Download the contents of this package in one zip archive (6.5M).
Luacoolprop – Thermodynamic calculations and diagrams in LuaTeX via the CoolProp shared library
LuaCoolProp is a format-generic LuaTeX package for thermodynamic calculations and pure-fluid PH, PV, TS, HS, and PT diagrams with PGFPlots. It uses an externally installed CoolProp shared library through LuaTeX FFI. The package provides LaTeX, plain TeX, and ConTeXt frontends and includes the autonomous pgfplots-autonode library for automatic curve labels.
| Package | Luacoolprop |
| Bug tracker | |
| Repository | |
| Version | 1.1.0 |
| Licenses | The LaTeX Project Public License 1.3c |
| Copyright | 2026 Christophe Jorssen |
| Maintainer | Christophe Jorssen |
| Topics | LuaTeX External code Physics PGF TikZ Graphics plot function |