acropora
acropora evolves probability measures by pushing forward individual states. It approximates statistical solutions of nonlinear PDEs by propagating Monte Carlo ensembles through deterministic solvers, on CPU (NumPy) or GPU (CuPy) from a single code path. Its first scheme is a vectorial lattice Boltzmann method for the compressible Euler equations used in the reference application to compute statistical solutions of a Mach 2000 astrophysical jet.
acropora is the companion code to: S. Simonis and G. Wissocq, Computing statistical solutions of a Mach 2000 astrophysical jet, arXiv:2605.25282 (2026). url: https://arxiv.org/abs/2605.25282 doi: 10.48550/arXiv.2605.25282
The data of the paper are archived on Zenodo: doi: 10.5281/zenodo.23415318
Install
Requires Python 3.9 or newer.
git clone https://github.com/stephan-911/acropora.git
cd acropora
pip install -e . # CPU only
pip install -e ".[gpu]" # + CuPy (CUDA 12)
pip install -e ".[post,dev]" # post-processing / tests
python -m pytest tests -q # 33 passed
On a cluster, load a recent Python first (module load ...; for the GPU extra
also the CUDA 12 module) and place the virtual environment on a work
filesystem:
python3 -m venv $WORK/acropora-venv
$WORK/acropora-venv/bin/pip install --upgrade pip
$WORK/acropora-venv/bin/pip install -e "/path/to/acropora[post,dev]"
An editable install records the repository path, so the environment keeps
tracking the checkout wherever it sits. The batch jobs take the environment
from VENV in the site file (see Batch jobs).
Quick start (CPU)
import numpy as np
from acropora import (Euler2D, VectorialD2Q5, Mach2000JetBC, run_sample,
grid_from_nx)
Nx, Ny, dx = grid_from_nx(250) # 250 x 200 cells, dx = 0.01
bc = Mach2000JetBC.make("ghost", Ny, seed=42) # portable RNG
solver = VectorialD2Q5(Euler2D(gamma=5/3), Nx, Ny, dx,
xp=np, boundary=bc)
bc.initial_condition(solver)
run_sample(solver, np.linspace(0, 0.0035, 8),
lambda ck, rho: print(ck, rho.max()))
Switch to GPU by xp = acropora.get_xp("gpu")
(or --backend gpu in the example CLI);
nothing else changes.
Layout
src/acropora/
backend.py array-namespace dispatch (numpy/cupy), device mgmt
grid.py grid geometry from the x-resolution Nx
random_fields.py stochastic inlet perturbation + RNG modes
models/ PDE systems: fluxes + wave-speed bound (Euler2D; add
your system here)
schemes/ time-stepping schemes (vectorial D2Q5 with
positivity limiter; add schemes here)
limiters.py reusable limiter components
boundaries.py boundary/IC objects (Mach2000JetBC; add setups here)
runner.py single-sample time loop + checkpointing
ensemble.py Monte Carlo orchestration (node partitioning,
per-sample restart, persistent worker pool)
io/ memmapped ensemble store
post/ post-processing: grid restriction, one-/
two-point Wasserstein distances, strong L1 error,
mean/std errors, rate fits, part merging,
centerline bands and one-point densities,
PDF-heatmap rasterization with pgfplots output,
quantile-band diagnostics
examples/mach2000_jet/ CLI + SLURM script for reproducibility
baseline/ reference implementation behind a numpy shim
(regression baseline)
tests/ bit-exact regression vs baseline + physics tests
benchmarks/ CPU benchmark + cluster GPU benchmark/repro script
The split: a model provides fluxes and a wave-speed bound, a scheme integrates any model, and a boundary object owns setup-specific state, so a new PDE or flow case is one new file, not a fork of the stepper.
Reproducibility
- Bit-exact within a backend: the CPU path reproduces the production
solver to the last bit (tested,
tests/test_regression_bitexact.py); the GPU path with--rng legacy-cupyreproduces the published dataset seed-for-seed (verify withbenchmarks/bench_gpu_cluster.py --paper-npy ...). - Identical initial data across backends (
portableRNG, default). - Pathwise CPU/GPU bit-equality at t = 0.0035 is not claimed: reductions and transcendentals differ by ULPs between backends and the flow is chaotic; the benchmark reports the divergence growth instead.
Reproducing the paper dataset
cd examples/mach2000_jet
./jobs.sh gen-full # 20-node GPU array, --rng legacy-cupy, writes $DATA_FULL
./jobs.sh merge --after <jobid> # merge the part files into samples_{Nx}.npy
The analysis stages read the dataset from DATA_NATIVE. To analyse the
regenerated data, set DATA_NATIVE to the same directory as DATA_FULL in
acropora-env.sh; to analyse the published dataset instead, point it there.
The two are kept separate so a regeneration never overwrites existing data.
The Zenodo record (10.5281/zenodo.23415318)
holds the ensembles restricted to the coarsest grid, the convergence and
centerline results, and the generation records. To rerun the convergence study
without the GPU generation, rebuild the ensemble files there with
bash merge_parts.sh, set DATA_ON500 to that folder in acropora-env.sh,
and run ./jobs.sh main, ./jobs.sh w2-reference and ./jobs.sh w2-cauchy.
Post-processing (acropora.post, pip install acropora[post]) reproduces the
paper's quantities: both comparison protocols (Cauchy: consecutive pairs;
reference: each vs the finest grid) with selectable restriction (coarsest,
the default and published methodology: every field is block-averaged to the
coarsest grid, so all comparisons are evaluated there; pairwise: only the
finer field is averaged, onto the coarser member's native grid), the
one-point per-cell Wasserstein distance, the two-point Wasserstein distance
(POT exact EMD, spatial subsampling), the per-sample strong L1
error, ensemble mean/std L1 errors, log-log rate fits, the centerline
percentile bands and one-point density grids, the log-scale PDF heatmaps
(rasterized to PNG with the matching \addplot graphics code emitted), and
the quantile-band diagnostics behind the statements about those figures.
Golden tests assert value-identical output against the reference analysis
script in baseline/.
Resolutions are the x-resolutions Nx -- arguments, file
names, and CSV columns -- matching the data files: the jet ladder is
--resolutions 500 1000 2000 4000, producing samples_500.npy ...
samples_4000.npy, centerline_nx500_... ... centerline_nx4000_..., and
coarse_nx / fine_nx / compare_nx columns. The transverse count and mesh
width follow from the domain via grid_from_nx (Nx=500 -> 500x400,
dx=5e-3).
Batch jobs
Batch jobs are submitted through one driver that reads a site file:
cp acropora-env.example.sh acropora-env.sh # at the repository root, git-ignored
$EDITOR acropora-env.sh # venv, partitions, account, data paths
cd examples/mach2000_jet
./jobs.sh restrict # once: restrict onto the coarsest grid
./jobs.sh main --after <jobid> # convergence study (chained)
./jobs.sh w2-reference; ./jobs.sh w2-cauchy
./jobs.sh centerline # reads the native data
./jobs.sh verify-gpu # GPU bit-exactness vs the dataset
./jobs.sh gen-test # small regeneration on one GPU node
./jobs.sh <stage> --dry-run prints the resolved paths and the exact sbatch
command without submitting. Nothing has to be exported in the shell: the jobs
load the site file themselves, so a fresh login cannot break them.
Funding
Funded by the Federal Ministry of Research, Technology and Space (BMFTR) through the PRIME programme of the German Academic Exchange Service (DAAD). Responsibility for the content of this publication lies with the author.
Citing
If you use acropora, please cite the companion paper (see CITATION.cff,
which GitHub and Zenodo parse automatically):
S. Simonis and G. Wissocq,
Computing statistical solutions of a Mach 2000 astrophysical jet,
arXiv:2605.25282 (2026).
https://doi.org/10.48550/arXiv.2605.25282
License
BSD-2-Clause-Patent (BSD 2-clause license with an explicit patent grant).
Copyright 2026 Stephan Simonis. Full text in LICENSE.
The acropora logo is © 2026 Stephan Simonis and is not covered by the BSD-2-Clause-Patent license.
Metadata
Release files for acropora 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| acropora-1.0.0.tar.gz | 41.6 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| acropora-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 79.7 kB
Release files / acropora-1.0.0.tar.gz
| Download URL | acropora-1.0.0.tar.gz |
|---|---|
| Size | 41.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2e4846e62ac58e84282b9a23f8c303f52318e7286c4ae68e1b522177b6e8a7a1
|
|
BLAKE2b-256 checksum How to use checksums |
9838b0c8916a8ea8d6bdf91f66991c1bac2e727d04477c997e66eee830870d22
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency logRelease files / acropora-1.0.0-py3-none-any.whl
| Download URL | acropora-1.0.0-py3-none-any.whl |
|---|---|
| Size | 38.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5d9f4713d42b696f6acee2cacf63b3821f024e0a6fd75abec820a386591ae34d
|
|
BLAKE2b-256 checksum How to use checksums |
04fa75038bbcf5ff33b318a296f316abed0e2037582bd3d9e550a00f02d64f76
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency logSecurity for acropora 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for acropora-1.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.