Installation¶
Requires Python ≥ 3.10 (per pyproject.toml's requires-python).
Python 3.9 was removed in v0.4.0
Deprecated in v0.3.3 (2026-08-24), removed on 2026-08-30. v0.3.3
remains installable on 3.9 and is the last release that is — pip will
resolve to it automatically on a 3.9 interpreter, because
requires-python is metadata the index enforces.
The floor moved for cost, not for a blocker. What a 3.9 row cost, all
of which is now gone: a second dependency lock
(requirements-ci-py39.lock), a second CI image, two CI jobs
(unit-py39 at 9.5 min on every pipeline, plus lock-verify-py39),
and a repo-wide Optional[X] constraint that existed only because
3.9's eval cannot parse X | None inside typing.get_type_hints().
The announcement asked 3.9-bound users to say so first, because the floor had been adopted deliberately for HPC environments that ship an old interpreter. Nobody did in the six days between the two releases, which is a weak signal and is recorded as one: an unraised objection is not the same as a surveyed constituency. If 3.10 is genuinely out of reach for you, open an issue — a floor can be lowered again, and the reason is worth having on record either way.
pip install aeolus1d # solver + CLI
That is the whole install for using aeolus1d. Everything below is either an optional extra or the contributor workflow.
From a clone instead — needed to contribute, to run the test suite,
or to use the example cases that live in examples/ subdirectories
(only the top-level examples/*.toml are bundled into the wheel):
git clone https://gitlab.com/niklas.nordin.swe/aeolus.git aeolus1d
cd aeolus1d
pip install -e .
Optional extras¶
The base install pulls in the solver + CLI only. Heavier optional
dependencies sit behind extras — note that the GUI is not
included in [dev]:
pip install "aeolus1d[gui]" # Qt + PyVista + pyvistaqt for the visual editor
pip install "aeolus1d[real-gas]" # CoolProp for the tabulated EOS builder
pip install "aeolus1d[chemistry-yaml]" # pyyaml — Cantera mechanism import
pip install "aeolus1d[chem-fast]" # numbalsoda — GIL-free per-cell stiff chemistry
pip install "aeolus1d[interop]" # pycgns / lxml / pythonfmu / fmpy / defusedxml
Contributor-only extras, which need the clone:
pip install -e ".[dev]" # pytest + ruff + mypy + pre-commit
pip install -e ".[build]" # PyInstaller for the GUI binary bundle
pip install -e ".[docs]" # mkdocs + mkdocs-material + mkdocstrings for this site
The [chem-fast] extra is opt-in: it is only exercised when a case
sets [case] chem_solver = "numbalsoda", which runs the general
mechanism-surface stiff-chemistry per cell under numbalsoda's nogil
LSODA in a prange. The core install ships a scipy-LSODA fallback, so
you never need it unless you specifically select that backend. A
separate [ml] extra (scikit-learn / torch) is only needed to
train the optional chemistry surrogate weights — runtime inference is
pure-numpy and needs neither.
You can combine extras: pip install -e ".[dev,gui,real-gas]".
Alternatively, the repository ships two loosely-pinned requirements
files: pip install -r requirements.txt installs the core + GUI
runtime set, and requirements-dev.txt adds the test / lint / docs
toolchain (then pip install -e . for aeolus1d itself).
First run — prime the Numba kernel cache¶
The first time the solver runs in a fresh environment, Numba
compiles the @njit kernels — a one-time ~19 s pause (measured
2026-08-08; hardware-dependent) for the
full quasi-steady + chemistry kernel set — and caches the results on
disk; every subsequent run loads them in seconds. Do that compile
out loud instead of inside your first real run:
aeolus1d warmup # pre-compiles the hot kernel families
aeolus1d doctor reports whether the kernel cache is warm or cold.
Sanity check¶
make test # ~3 min, parallel, skips @slow
aeolus1d bench nozzle # quick CLI benchmark
aeolus1d run examples/03_two_pipes_junction.toml --out run.h5
The default make test runs pytest -n auto -m "not slow" —
parallel across all cores and skipping the strict-Helmholtz xfail
plus any benches marked @pytest.mark.slow. make test-all
runs everything; make test-fast adds --durations=10 so the
slowest survivors are visible.
Plain pytest (no Makefile) also runs in parallel — the
-n auto flag is wired into pyproject.toml's
[tool.pytest.ini_options]. To force sequential execution
for cleaner tracebacks, pass pytest -n 0 … or use
make test-serial.
If any of the GUI / real-gas / build extras report missing modules when running their respective entry-points, double-check you installed with the matching extras flag — the imports are deliberately lazy so a base solver install stays light.
Standalone binary (PyInstaller)¶
For end users without a Python environment, the GUI ships as a
self-contained one-folder bundle built with PyInstaller — no pip,
no virtualenv, the whole examples/ tree included so the example
browser and aeolus1d examples work offline.
pip install -e ".[gui,build]" # adds PyInstaller
./aeolus1d_gui/build/build.sh # ~3–8 min, Linux/macOS
./dist/aeolus1d-gui/aeolus1d-gui # launch
PyInstaller cannot cross-compile — a Windows .exe must be built
on Windows. A turnkey wrapper drives the same spec:
# from Windows PowerShell (NOT WSL), at the repo root:
powershell -ExecutionPolicy Bypass -File aeolus1d_gui\build\build_windows.ps1
.\dist\aeolus1d-gui\aeolus1d-gui.exe
build_windows.ps1 creates an isolated .venv, installs .[gui,build],
and runs PyInstaller; it needs a real python.org Python 3.10–3.12 (not
the Microsoft Store alias stub) and ~4–5 GB free on the build drive.
The [ml] extras (torch / sklearn) are intentionally excluded from
the bundle. Full per-platform notes, spec internals, and known
limitations live in aeolus1d_gui/build/README.md.
WSL / Windows¶
The Qt-PyVista canvas can be flaky under WSLg's X server. If components don't render or the canvas crashes:
- Force the X11 platform:
export QT_QPA_PLATFORM=xcbbefore launching the GUI. - Install the X11 client libs:
sudo apt-get install libxcb-cursor0 libegl1 libgl1-mesa-glx. - For a smoke test, software-render:
LIBGL_ALWAYS_SOFTWARE=1 ./aeolus1d_gui/run_gui.sh.
The solver itself is platform-agnostic; only the GUI is sensitive to the WSLg layer.