AcaysiaRT
A high-throughput GPU simulation runtime built for ensemble prediction — the control, optimization, and learning workflows that single-trajectory solvers cannot support. One templated CUDA core serves 127 registered process models, from a pH-CSTR to a 168-state chromatography column, each one bit-exact parity-tested against a PyTorch reference. Proven first on chemical reactors.
It is the runtime underneath the Acaysia MPPI control system, the engine AcaysiaDRT composes for spatial detail, and — through its Rete layer — the engine that runs whole plants with recycle.
Schematic — MPPI samples N rollouts over horizon H, then softmax-weights them by cost.
Measured, With Conditions Attached
Every number below is a reproducible benchmark from the repository, not a projection. A throughput figure without its batch size, horizon, and GPU is not a claim.
| Backend | 10,000 rollouts × H=100 | Throughput |
|---|---|---|
| PyTorch (CPU) — reference / debug only | 29.85 ms | ~33 M reactor-steps/sec |
| CUDA (RTX 5080, Blackwell sm_120) | 0.164 ms | ~6.1 B reactor-steps/sec |
Data-parallel batch sharding
Reactors are independent, so a batch splits across GPUs and results stay bit-exact against the single-GPU path. Measured on 2× RTX 5080 at N=200,000 × H=100 — a 646 MB trajectory.
| Mode | Time | Throughput |
|---|---|---|
| 1 GPU (all N) | 5.6 ms | 3.6 B steps/sec |
| 2 GPU, shards resident | 2.0 ms | 10 B steps/sec (~2.8×) |
| 2 GPU, gathered to one device | 23 ms | 0.9 B steps/sec |
The trajectory tensor is large, so gathering it back to one device dominates the kernel. Multi-GPU pays off when the batch exceeds one card's VRAM, or when each GPU keeps its shard resident across many ticks — per-GPU MPPI or training — rather than gathering every call.
One Core, 127 Process Models
The engine and MPPI kernels are template<class Model> and instantiated per model, so the same high-performance core serves every reactor archetype. A new model is a registry drop-in architecturally — it inherits the engine and model-generic MPPI without touching dispatch.
The classical core
pH-CSTR, reactive CSTR, PFR, batch and semi-batch. Binary and multi-feed distillation, dividing-wall columns, absorbers, strippers, extractors, decanters, flash drums, evaporators, crystallizers.
Heavy industry
Leach tanks, autoclave pressure-oxidation, thickeners, grinding mills, flotation cells, hydrocyclones, screens, filter presses, EAF and BOF steelmaking on JANAF thermodynamics.
Electrochemical & capture
SOEC electrolyzers, vanadium redox-flow batteries, solid-sorbent direct-air capture on a temperature/vacuum swing, fired heaters, boilers, compressors, expanders, FCC regenerators.
Living and regulated processes
Immobilized-enzyme packed beds, penicillin fed-batch fermentation, photobioreactors, ASM2d biological nutrient removal, UV advanced-oxidation, UHT pasteurization.
| Representative model | What it is | Controlled output |
|---|---|---|
| pH-CSTR | Neutralization with carbonate and weak acid/base equilibria — the reference model | pH |
| Distillation column | Binary constant-molar-overflow, tray-by-tray (Skogestad “Column A”) | Distillate purity |
| Reaction-network CSTR | Data-defined mass-action reactor, fixed-dim, any network — hosts 45 curated processes | Product concentration |
| Crystallizer | Cooling MSMPR via the method of moments | Temperature → crystal size |
| Autoclave POx leach | Pressure-oxidation hydrometallurgical leach | Metal extraction |
| Dividing-wall column | 82-state thermally-coupled distillation | Side-draw purity |
| Penicillin fermenter | Bajpai–Reuss fed-batch antibiotic fermentation | Product titer |
| SOEC electrolyzer | Solid-oxide electrolysis cell | Hydrogen rate |
A representative selection. Alongside the 127 registered models sit 45 curated reaction-network processes running on the shared reaction-network engine. 126 of 127 are MPPI-controllable — the exception is pipe, a transfer-line connector. The largest state dimension in the registry is 168; 43 models carry the stream contract that makes them wireable into a Rete plant.
Technical Specifications
CUDA is production
The CUDA engine is the only production backend. PyTorch exists for distribution/ABI, the Python API surface, and reference correctness checking — it is not a second execution engine, and selecting it emits an explicit warning.
One core, instantiated per model
Adding a process model does not mean writing a new engine. Each model plugs into the same templated CUDA core and the same controller, so performance work done once benefits every model in the registry — and a new one arrives without a bespoke code path to maintain.
Tensors in, tensors out
step / rollout / observe dispatch through the registry; step_soa and rollout_soa are the structure-of-arrays fast path for MPPI hot loops. TORCH_LIBRARY bindings keep tensors zero-copy on device.
Conserved totals, projected equilibrium
Speciation is never carried in state. The step marches conserved totals and clamps to physical bounds; observe() solves equilibrium on demand — a log-domain Newton iteration for pH — and applies sensor bias at the output.
Model-Generic MPPI
One sampling-based CUDA controller works with every registered model. Its cost is data-driven over a model's observable vector — per-output target, weight, and bounds — so a model picks what it tracks by setting weights. There is no per-model controller code to write.
Thousands of futures per tick
MPPI needs thousands of parallel rollouts over a 100–200 step horizon with consistent, deterministic stepping. That requirement is the reason this runtime exists, and it is what makes path-integral control practical for process plants.
Convergence-tested per model
Every MPPI-controllable model ships a closed-loop convergence test, not just a smoke test — the controller has to actually drive that model's tracked output to target in CI.
Surrogate corrections, cleanly bounded
The biasing layer is the entry-side transform that shapes a learned surrogate's predicted corrections into a model's declared correction slots — 117 of the 127 models have them. It is deliberately standalone: torch and the ontology only, enforced by test.
Whole-flowsheet control
Single units compose into plants through the Rete layer below, where one MPPI sample becomes one whole-plant rollout — recycle loops included.
Whole Plants, Not Just Units
A plant is not a pile of unit operations — it is a loop. Product streams get fed back into the units that made them, and every recycle changes the duty of everything upstream. Rete is the layer that wires AcaysiaRT models into a full flowsheet and marches the whole thing forward at once, recycle included.
Recycle changes the answer
Run that loop at 70% recycle and the two conversion numbers move in opposite directions. Per-pass conversion falls from 0.4623 to 0.3068 — each trip through the reactor does less work. Overall conversion on fresh feed rises from 0.4623 to 0.5961.
That divergence is the textbook recycle result, and it is exactly what a unit-by-unit model cannot tell you. It is also why plant decisions made from single-unit simulations go wrong: the number that matters is the one a loop produces. The balances are cross-checked against DWSIM.
Tune the plant, not the loop
Plant-wide MPPI treats one control sample as one whole-plant rollout, so the controller optimizes across units instead of fighting itself — the classic failure when each loop is tuned in isolation and the recycle carries the disagreement around.
Dozens of units, thousands of futures
Plants of 50-plus mixed unit types march on the GPU, batched over thousands of samples at once. Fusing a plant into a single kernel is worth roughly 22× over the same work run unit-by-unit on the same card.
A plant is a document
Topology, feeds, connections, and targets live in a declarative definition you can save, diff, and hand to someone else. Configuration is an artifact, not a state buried in a session.
Answers about dynamics
It marches in time rather than solving for a steady state, so it reports when a recycle loop settles and how it got there — startup, disturbance rejection, and the transients a steady-state flowsheet package never shows you.
Validation Provenance
Validation runs on a T0–T5 ladder where tier, numerical outcome, and health are orthogonal. A strong oracle does not lose its tier when it exposes a model gap — which is exactly what keeps the incentives honest.
| Tier | What it means |
|---|---|
| T0 | Running-deployment validation, tied to a real deployment and its committed operating envelope |
| T1 | Full-model oracle — an independent reference covering primary behavior, regimes, and outputs |
| T2 | Partial independent oracle — measurements, standards, or an authoritative external tool on a named subset |
| T3 | Local scientific reference — a good validator-authored analytical model, not externally grounded |
| T4 | Cross-implementation parity — catches numerical and indexing defects; cannot establish that the physics is right |
| T5 | Supporting assurance — calibration replay, invariants, regression |
92 of 127 models at T0–T2
72% of the roster carries independent evidence at the top three tiers, across 264 logical validators over 200 cached runs. Current health: 261 fresh, 0 stale, 0 failed.
Best-in-class, per domain
A deliberate collage rather than one tool: Cantera for gas and combustion, PHREEQC for aqueous and hydrometallurgy, JANAF for pyrometallurgy, CoolProp for thermophysical properties, and published benchmarks — ASM2d/BSM, Bajpai–Reuss, HCH-1 — for biological units.
Blind, fit, or held-out
Every validator declares how it was calibrated. That is the structural defense against the classic failure mode of fitting a model to its own oracle and then citing the agreement as evidence.
2,650 tests
Per-model CUDA↔PyTorch parity, physics invariants, and MPPI closed-loop convergence for all 127 models; plus MPPI cost-layout contracts, biasing slot writes, and multi-GPU sharding. CUDA tests are hardware-gated.
Distances are reported as multiples of the declared tolerance: 0.58× means 42% headroom remains, 1.83× means 83% over. A gap never demotes a tier — it is the result the validator was built to find, and several validators have surfaced and documented real fidelity gaps.
Simple, Powerful API
Tensors in, tensors out. Pick a model by name; the registry handles dispatch.
# AcaysiaRT ships from source with the CUDA extension
pip install -e .
python setup.py build_ext --inplace
# Requires torch, numpy, and the shared
# acaysia-ontology-schemas contracts package
import torch
import acaysia_rt as art
# pH-CSTR state [N, 8]: T, V, DIC, ALK,
# WAC_TOT, WBASE_TOT, BIAS_PH, UA_SCALE
states = torch.tensor([[
298.0, 100.0, 0.002, 0.002,
0.0, 0.0, 0.0, 1.0
]], device="cuda")
# Roll out a horizon of 100 steps
traj = art.rollout(states, controls_seq, dt=0.1)
# Derived quantities: pH, speciation, ...
pH = art.observe(states)[:, art.OutputIndex.PH]
Ready to Accelerate Your Control Systems
Contact us to discuss how AcaysiaRT can power your MPPI control and simulation workloads.
Request Early Access