caustic
A 6D Vlasov–Poisson solver framework for collisionless gravitational dynamics.
caustic is a modular, general-purpose library for solving the Vlasov–Poisson equations in full 6D phase space (3 spatial + 3 velocity dimensions). It targets astrophysical problems — dark matter halo formation, galaxy dynamics, tidal streams, stellar system stability — that are traditionally handled by N-body methods but suffer from artificial collisionality and loss of fine-grained phase-space structure.
The library provides a pluggable architecture where the phase-space representation, Poisson solver, time integrator, and initial condition generator can be swapped independently.
Why not N-body?
N-body simulations sample the distribution function with discrete particles. This introduces noise and artificial two-body relaxation that destroys exactly the structures a collisionless solver should preserve: caustic surfaces, thin phase-space streams, and the true velocity distribution at any point. caustic solves the governing equation directly — no particles, no sampling noise, no artificial collisionality.
Quick start
Add to your Cargo.toml:
[]
= "0.0.9"
Minimal example: Plummer sphere equilibrium
use *;
use ;
Conservation-aware simulation with LoMaC
let mut sim = builder
.domain
.poisson_solver
.advector
.integrator
.initial_conditions
.time_final
.lomac // enable local macroscopic conservation
.build?;
Architecture
Each solver component is a Rust trait; implementations are swapped independently:
| Trait | Role | Implementations |
|---|---|---|
PhaseSpaceRepr |
Store and query f(x,v) | UniformGrid6D, HtTensor, TensorTrain, SheetTracker, SpectralV, AmrGrid, HybridRepr |
PoissonSolver |
Solve ∇²Φ = 4πGρ | FftPoisson, FftIsolated, TensorPoisson, Multigrid, SphericalHarmonicsPoisson, TreePoisson |
Advector |
Advance f by Δt | SemiLagrangian (Catmull-Rom + sparse polynomial) |
TimeIntegrator |
Orchestrate timestep | StrangSplitting (2nd), YoshidaSplitting (4th), LieSplitting (1st), UnsplitIntegrator (RK2/3/4) |
Phase-space representations
| Representation | Memory | Description |
|---|---|---|
UniformGrid6D |
O(N⁶) | Brute-force 6D grid, rayon-parallelized. Reference implementation. |
HtTensor |
O(dNk² + dk³) | Hierarchical Tucker tensor decomposition. Black-box construction via HTACA. SLAR advection. |
TensorTrain |
O(dNr²) | TT-SVD decomposition with cross approximation advection. |
SheetTracker |
O(N³) | Lagrangian cold dark matter sheet. CIC density deposit. Caustic detection. |
SpectralV |
O(N³M³) | Hermite spectral basis in velocity; finite-difference in space. |
AmrGrid |
adaptive | Adaptive mesh refinement in 6D with gradient-based refinement. |
HybridRepr |
adaptive | Sheet/grid hybrid with caustic-aware interface switching. |
Poisson solvers
| Solver | BC | Complexity | Description |
|---|---|---|---|
FftPoisson |
Periodic | O(N³ log N) | Real-to-complex FFT via realfft, rayon-parallelized. |
FftIsolated |
Isolated | O(N³ log N) | Hockney-Eastwood zero-padding on (2N)³ grid. |
TensorPoisson |
Isolated | O(N³ log N) | Braess-Hackbusch exponential sum Green's function + dense 3D FFT. 2nd-order near-field correction. |
HtPoisson |
Isolated | O(R_G·r·N log N) | HT-format Poisson: exp-sum Green's function in HT tensor format with rank re-compression. |
Multigrid |
Periodic/Isolated | O(N³) | V-cycle with red-black Gauss-Seidel smoothing, rayon-parallelized. |
SphericalHarmonicsPoisson |
Isolated | O(l²_max N) | Legendre decomposition + radial ODE integration. |
TreePoisson |
Isolated | O(N³ log N³) | Barnes-Hut octree with multipole expansion, rayon-parallelized. |
Time integrators
| Integrator | Order | Description |
|---|---|---|
StrangSplitting |
2 | Drift(Δt/2) → kick(Δt) → drift(Δt/2). Symplectic. |
YoshidaSplitting |
4 | 3-substep Yoshida coefficients, 7 sub-steps total. Symplectic. |
LieSplitting |
1 | Drift(Δt) → kick(Δt). For testing/comparison only. |
UnsplitIntegrator |
2/3/4 | Method-of-lines RK on full Vlasov PDE. No splitting error. Re-solves Poisson at each stage. |
RkeiIntegrator |
3 | RKEI (Runge-Kutta Exponential Integrator). SSP-RK3 with unsplit characteristics. 3 Poisson solves per step. |
InstrumentedStrangSplitting |
2 | Strang splitting with per-sub-step rank diagnostics (drift/kick/Poisson amplification tracking). |
The PhaseSpaceRepr trait
The central abstraction. All phase-space storage strategies implement this interface:
Hierarchical Tucker (HT) tensor compression
A uniform 6D grid at N=64 per dimension requires 64⁶ ≈ 7×10¹⁰ cells. The HtTensor representation exploits the balanced binary tree structure of the x-v split to store f(x,v) in O(dNk² + dk³) memory, where k is the representation rank and N is the grid size per dimension.
Construction methods:
HtTensor::from_full()— compress a full 6D array via hierarchical SVD (HSVD). O(N⁶).HtTensor::from_function_aca()— black-box construction via the HTACA algorithm (Ballani & Grasedyck 2013). Builds the HT decomposition by sampling O(dNk) fibers instead of evaluating all N⁶ grid points.
Operations (all in compressed format, never expanding to full):
compute_density()— O(Nk²) velocity integration via tree contractiontruncate(eps)— rank-adaptive recompression (orthogonalize + top-down SVD)add()— rank-concatenation addition, followed bytruncate()to compressinner_product()/frobenius_norm()— O(dk⁴) via recursive Gram matricesevaluate()— single-point query in O(dk³)advect_x()/advect_v()— SLAR (Semi-Lagrangian Adaptive Rank) via HTACA reconstruction
Conservation framework (LoMaC)
The LoMaC (Local Macroscopic Conservation) framework restores exact conservation of mass, momentum, and energy after each time step. Enable via .lomac(true) on the simulation builder.
Components:
- KFVS — Kinetic Flux Vector Splitting macroscopic solver with half-Maxwellian fluxes
- Conservative SVD — Moment-preserving projection via Gram matrix inversion
- Rank-adaptive controller — Conservation-aware truncation tolerance with budget management
Initial conditions
Isolated equilibria (via sample_on_grid()):
PlummerIC— Plummer sphere via analytic distribution function f(E)KingIC— King model via Poisson-Boltzmann ODE (RK4 integration)HernquistIC— Hernquist profile via closed-form f(E)NfwIC— NFW profile via numerical Eddington inversion
Cosmological:
ZeldovichSingleMode— single-mode Zel'dovich pancakeZeldovichIC— multi-mode Zel'dovich ICs from Gaussian random field (Harrison-Zel'dovich spectrum, FFT-based, reproducible seeding)
Disk dynamics:
DiskStabilityIC— exponential disk with Shu (1969) distribution function f(E, L_z), Toomre Q stability parameter, azimuthal perturbation modes (bars, spirals)
Multi-body and custom:
MergerIC— two-body superposition f = f₁ + f₂ with offsetsTidalIC— progenitor equilibrium model in an external host potentialCustomIC/CustomICArray— user-provided callable or pre-computed array
Diagnostics
Conserved quantities monitored each timestep via GlobalDiagnostics:
- Total energy (kinetic + potential), momentum, angular momentum
- Casimir C₂, Boltzmann entropy
- Virial ratio, total mass in box
- Density profile (radial binning)
Analysis tools:
- L1/L2/L∞ field norms and error metrics
ConservationSummary— energy, mass, momentum, C₂ drift trackingconvergence_table— Richardson extrapolation and convergence order estimationCausticDetector— caustic surface detection, first caustic time
I/O and checkpointing
- Binary snapshot save/load (shape + time + data)
- CSV diagnostics (time series of all conserved quantities)
- JSON checkpoint (snapshot + diagnostics history)
- HT tensor checkpoint (tree structure without dense expansion)
- HDF5 (feature-gated):
save_snapshot_hdf5,load_snapshot_hdf5,save_ht_checkpoint_hdf5,load_ht_checkpoint_hdf5
Exit conditions
Termination is configurable via the builder API:
| Condition | Description |
|---|---|
TimeLimitCondition |
Stop at t ≥ t_final |
EnergyDriftCondition |
Stop when |ΔE/E| > tolerance |
MassLossCondition |
Stop when mass loss exceeds threshold |
CasimirDriftCondition |
Stop when C₂ drift exceeds threshold |
WallClockCondition |
Stop after wall-clock time limit |
SteadyStateCondition |
Stop when ∥∂f/∂t∥ < ε |
CflViolationCondition |
Stop on CFL violation |
VirialRelaxedCondition |
Stop when virial ratio stabilizes |
CausticFormationCondition |
Stop at first caustic (stream count > 1) |
Validation suite
163+ tests — run with cargo test --release -- --test-threads=1:
Physics validation
| Test | Validates |
|---|---|
free_streaming |
Spatial advection accuracy (G=0, f shifts as f(x−vt, v, 0)) |
uniform_acceleration |
Velocity advection accuracy |
jeans_instability |
Growth rate matches analytic dispersion relation (periodic BC) |
jeans_instability_isolated |
Jeans instability with FftIsolated BCs, growth rate comparison |
jeans_stability |
Sub-Jeans perturbation does not grow |
plummer_equilibrium |
Long-term equilibrium preservation |
king_equilibrium |
King model (W₀=5) equilibrium preservation |
nfw_equilibrium |
NFW profile cusp preservation over 5 t_dyn |
zeldovich_pancake |
Caustic position matches analytic Zel'dovich solution |
spherical_collapse |
Spherical overdensity collapse dynamics |
cold_collapse_1d |
Cold slab gravitational collapse, phase-space spiral formation |
conservation_laws |
Energy, momentum, C₂ conservation to tolerance |
landau_damping |
Damping rate matches analytic Landau rate |
nonlinear_landau_damping |
Large perturbation (ε=0.5), phase-space vortex, conservation over 50 bounce times |
two_stream_instability |
Two-stream IC, perturbation growth and saturation |
sheet_1d_density_comparison |
1D sheet model vs exact Eldridge-Feix dynamics |
Convergence tests
| Test | Validates |
|---|---|
density_integration_convergence |
Spatial convergence of density integration |
free_streaming_convergence |
Error decreases with resolution |
convergence_table_structure |
Richardson extrapolation framework |
Solver cross-validation
| Test | Validates |
|---|---|
multigrid_vs_fft |
Multigrid matches FftPoisson on periodic problem |
multigrid_convergence_order |
2nd-order convergence (double N, error /4) |
spherical_vs_fft_isolated |
Spherical harmonics matches FftIsolated |
tree_vs_fft_isolated |
Barnes-Hut tree matches FftIsolated |
tensor_poisson_vs_fft_isolated |
TensorPoisson matches FftIsolated |
Plus integration tests, HT tensor/ACA tests (17), conservation framework tests (15), diagnostics tests (10), and solver-specific unit tests.
Equation-to-module mapping
| Equation / Method | Module | Reference |
|---|---|---|
| ∂f/∂t + v·∇ₓf − ∇Φ·∇ᵥf = 0 (Vlasov) | time/strang.rs, time/yoshida.rs, time/rkei.rs |
Operator splitting: Cheng & Knorr (1976) |
| ∇²Φ = 4πGρ (Poisson) | poisson/fft.rs, poisson/multigrid.rs |
Hockney & Eastwood (1988) |
| 1/r ≈ Σ c_k exp(-α_k r²) (exponential sum) | poisson/exponential_sum.rs, poisson/tensor_poisson.rs |
Braess & Hackbusch, IMA J. Numer. Anal. 25(4) (2005) |
| HT-format Poisson with rank re-compression | poisson/ht_poisson.rs |
Khoromskij (2011), Braess-Hackbusch (2005) |
| Near-field correction (0th + 2nd order) | poisson/exponential_sum.rs, poisson/tensor_poisson.rs |
Exl, Mauser & Zhang, JCP (2016) |
| Hierarchical Tucker decomposition | algos/ht.rs |
Hackbusch & Kühn, JCAM 261 (2009) |
| HTACA (black-box HT construction) | algos/ht.rs, algos/aca.rs |
Ballani & Grasedyck, Numer. Math. 124 (2013) |
| SLAR (semi-Lagrangian adaptive rank) | algos/ht.rs |
Kormann & Reuter (2024) |
| RKEI (Runge-Kutta exponential integrator) | time/rkei.rs |
Kormann & Reuter (2024) |
| LoMaC (local macroscopic conservation) | conservation/lomac.rs, conservation/kfvs.rs |
Guo & Qiu, arXiv:2207.00518 (2022) |
| Conservative SVD projection | conservation/conservative_svd.rs |
Guo & Qiu (2022) |
| KFVS (kinetic flux vector splitting) | conservation/kfvs.rs |
Mandal & Deshpande, Comput. Fluids 23(4) (1994) |
| Plummer DF: f(E) ∝ (−E)^{7/2} | init/isolated.rs |
Dejonghe (1987), Binney & Tremaine (2008) |
| King model: Poisson-Boltzmann ODE | init/isolated.rs |
King, AJ 71 (1966) |
| NFW: numerical Eddington inversion | init/isolated.rs |
Navarro, Frenk & White, ApJ 462 (1996) |
| Zel'dovich approximation | init/cosmological.rs |
Zel'dovich, A&A 5 (1970) |
| Shu disk DF: f(E, L_z) | init/stability.rs |
Shu, ApJ 160 (1970) |
Feature flags
[]
= { = "0.0.6", = ["hdf5"] }
| Flag | Description |
|---|---|
hdf5 |
HDF5 I/O via hdf5-metno (snapshot and HT checkpoint read/write) |
mpi |
MPI domain decomposition via the mpi crate (requires MPI installation) |
jemalloc |
jemalloc global allocator via tikv-jemallocator |
mimalloc-alloc |
mimalloc global allocator |
dhat-heap |
Heap profiling via dhat |
tracy |
Tracy profiler integration via tracing-tracy |
Performance
- Parallelism: rayon data parallelism across
UniformGrid6D(density, advection),FftPoisson(FFT axes),TreePoisson(grid walk),SheetTracker(particle advection),Multigrid(residual, prolongation) - Release profile: fat LTO,
codegen-units = 1,target-cpu=native(via.cargo/config.toml) - Benchmarks: criterion benchmarks (
cargo bench), benchmark binary:solver_kernels - Instrumentation:
tracing::info_span!on all hot methods (zero overhead without a subscriber) - Profiling profile:
[profile.profiling]inherits release with debug symbols forperf/samply
Companion: phasma
phasma is a ratatui-based terminal UI that consumes caustic as a library dependency. It provides interactive parameter editing, live diagnostics rendering, density/phase-space heatmaps, energy conservation plots, radial profile charts, rank monitoring, and Poisson solver analysis — all from the terminal. phasma contains no solver logic; it delegates entirely to caustic.
Minimum supported Rust version
Rust edition 2024, targeting stable Rust 1.85+.
License
This project is licensed under the GNU General Public License v3.0. See LICENSE for details.
Citation
If you use caustic in academic work, please cite: