Why

Four grand challenges

Teschner's survey of the six biggest unsolved problems in CFD, drawn from the NASA CFD Vision 2030 Study, names where the field is stuck. Four of those six have informed the design of this CFD library.

Challenge 3: Numerical algorithms

Error is attributed, and cost falls out of the representation

The survey records that uncertainty quantification is "unexplored in most cases," that error estimation for time-dependent flows lacks robustness, and that modelling error, boundary-condition error and numerical error resist being quantified at the same time.

Every theory, solver, stage and observable in the crate is generic over a single real scalar. A program fixes one alias and the whole computation runs at that precision, from the flux stencils through to the Kalman filter, downcasting to f64 only at the display boundary.

/// Working precision.
pub type FloatType = f64; // or f32, or deep_causality_num::Float106

/// Lift an exact `f64` specification into the working precision.
pub fn ft(x: f64) -> FloatType {
    FromPrimitive::from_f64(x).expect("specification lifts into FloatType")
}

That turns error attribution into an experiment you can run. The plasma-blackout corridor was flown at f64 and again at 106-bit precision. Every gate and every discrete event step came out identical; the continuous witnesses agreed to 15 or 16 significant digits. Round-off is therefore excluded, and the corridor's remaining error budget sits in the model closures and the grid. One line changes, and the question is answered by measurement rather than by argument.

Cost is attacked at the representation. The compressible marchers run on quantized tensor trains, where a 2^L grid costs orderχ² · L: logarithmic in point count, with sharp structure paid for in bond dimension. The rank studies located the driver as coordinate alignment, and the compressible carrier answers it with a shock-fitted inflow strip, so the exact Rankine–Hugoniot state bounds the marched layer and the shock is never captured.

  • Graded-torus MMS, 8² → 64²: observed order 1.98–2.01 against 2.00; divergence-freeness exact by construction.
  • Taylor–Green RHS kernel against exact autodiff derivatives: max abs error 1.11e-16.
  • Precision ladder on the same program: 3e-8 (f32) / 1e-16 (f64) / 8e-33 (Float106).
  • Sod shock tube at 512 cells, t = 0.2: density L1 0.0175, velocity 0.0274, pressure 0.0151; star pressure p* = 0.3031 exact.
  • Taylor–Green on a tensor train at 32²: bond 32 against 1024 dense, a 32× compression, observed order 2.18.
  • Blunt-body bow shock, 2⁵ → 2⁷: fitted bond 3 → 5, Cartesian capture bond 16 → 61.

verification/ studies/

Challenge 2: Physical modelling

A model's calibration range is a runtime predicate

The survey's charge against the standard closures is that they are calibrated over a range of flows and then fail outside it, with the failure invisible from inside the run.

Here the regime is a classified property of the evolved state, decided again on every step from a measured quantity. Three axes switch independently. The freestream Knudsen number selects the governing model: continuum Navier–Stokes, slip-corrected continuum, transitional, or free-molecular. The force ratio ε = a_aero/a_grav selects the integrator, so a trajectory advances on the exact KS-conformal core with aero as a between-step kick while gravity dominates, then switches to direct Cowell once aero does. The evolved electron density sets the plasma frequency, and the plasma frequency decides whether the GNSS link exists at all.

Because the classification is read off the field, a regime change is an event the run finds rather than a station it is told to switch at. Every transition lands in the provenance log. From a committed corridor run:

regime -> slip (GNSS-available), Kn=0.07829109848665225
regime -> slip (GNSS-denied), Kn=0.012690837165407727
regime -> continuum (GNSS-denied), Kn=0.00993838892165156
regime -> continuum (GNSS-available), Kn=0.0002551442196046344

One descent moves through orbit-like dynamics, slip flow, continuum flow, comms blackout and reacquisition inside one uninterrupted program, with the governing model changing underneath it four times. Turbulence closures are staged on the DEC solver behind the spectra observables; theroadmap carries the sequencing.

  • RAM-C II stagnation streamline, ~71 km, M = 25: the uncalibrated finite-rate network, run as prediction rather than fit, lands at 2.251e19 m⁻³ against the ~1e19 m⁻³ flight anchor, +0.35 decades inside a ±0.70 band.
  • The closed-form Park-2T controller lands at 5.31e17 m⁻³, 1.27 decades below the anchor after the N₂–N₂ reduced-mass correction; the offset is reported, not tuned away.
  • Plasma frequency ω_p 4.111e10 rad/s against the 9.40e9 comms band; blackout classified true.
  • Validated incompressible envelope Re 100 to 1600; the wake is reported and never gated.

Validation recordsCapability boundaries

Challenge 6: Multidisciplinary analysis and optimization

Nothing is exchanged, because nothing is separate

The survey observes that coupling several physics solvers needs a robust framework, that uncertainty propagation across a solver chain is unaddressed, and that no standardized multidisciplinary exchange format exists in the way CGNS serves CFD alone.

A coupling stack here is a static cons-tuple of physics stages stepping one shared field. No file, no adapter, and no exchange format exist, because the disciplines were never in separate processes.

Coupling::between_steps()
    .then(VibrationalLagStage::new(/* Millikan-White bath */))
    .then(FiniteRateIonizationStage::new(n_tot).with_density_field("n_tot"))
    .then(RegimeClassify::new(l_char, trigger))
    .then(BankSteeredLift::new(rho_ref, cda_over_m, l_over_d))
    .then(TrajectoryNav::new(q_diag, gnss_var, optical_var).with_imu(imu))
    .then(CyberneticCorrect::new(SafetyEnvelope::new(q_max, g_max, bank_max)))
    .build()

Vibrational relaxation, reacting plasma chemistry, regime classification, steered aerodynamic force, a 17-state error-state Kalman navigation engine, and a bounded-correction safety gate, in one loop body. Stages communicate through named fields on the evolved state, and anErr from any stage short-circuits the whole step.

Uncertainty crosses the chain the same way. The ensemble index threads into the stack, so a Monte-Carlo draw is a parameter of the coupled physics rather than a wrapper around it. The evolved electron density gates which measurements the Kalman filter is permitted to fold; the Knudsen number selects the governing model; the safety gate's clamped bank command is flown by the aero stage and steers the trajectory that sets the next step's freestream. Fluid dynamics, estimation and control close one loop.

  • Plasma retropulsion descent, blackout exit to touchdown: sixteen gates in 355.6 s.
  • Weather-dispersion table: six atmospheres alternated from one baseline, each an ensemble of receiver-noise draws, flown concurrently to one gated table.
  • Branch fan-outs run on scoped threads and produce bits identical to the sequential run.

Worked examplesdeep_causality_cfd/

Challenge 5: Knowledge extraction

The run returns a verdict, not a field

The survey notes that pulling whole simulations onto a workstation stops being possible at scale, and that extracting actionable information from single runs and parameter sweeps needs better frameworks than the post-processor.

The study grammar reduces inside the process. A campaign names its cases, marches or forks them, reduces each outcome to a scored row, and gates the table. What crosses the boundary is the table and the verdict; the field stays where it was computed.

let table = CfdFlow::study("weather-dispersion table")
    .cases(model::weather_cases())
    .baseline(model::standard_day)
    .alternate(model::weather_world)
    .ensemble(constants::MC_DRAWS)
    .couple(|case, draw| world::corridor_coupling(model::bias_departure(case.d_temp), draw))
    .march_for(constants::STEPS, world::initial_field)
    .reduce_ensemble(model::world_row)
    .gates(model::weather_gates())
    .verdict()?;

verdict() returns data. The DSL never prints and never exits, so the caller decides what an exit code means. The gating sequence is a named value the study inserts whole, which makes an acceptance criterion a reviewable object rather than a comment in a post-processing script. Every branch stamps a !!ContextAlternation!! marker into its provenance log naming its baseline, and an optionalsave_log(path) flushes provenance to disk, one file per branch under a fan-out.

The same discipline covers the crate's own evidence.verification/ holds thirteen runnable programs gated against analytic solutions, published references, or invariants the discretization must preserve. studies/ holds the empirical probes that settled design questions, with each finding encoded as a gate so the conclusion stays reproducible instead of surviving as folklore. Four hypotheses were refuted this way and are recorded as refuted.

  • Thirteen gated verification programs, each with a committed run artifact and a stated caveat.
  • Findings encoded as gates: a study that stops reproducing fails, rather than quietly ageing.
  • Four refuted hypotheses kept on the record with the measurement that killed them.

Validation recordsCapability boundaries

Not on the list

Forking a running simulation

The survey's six entries are the problems the field has agreed to name. Counterfactual dynamics is absent from them, and the reason is that a simulation has been something you configure and then run to completion. Changing a decision meant changing an input file and paying for the whole trajectory again.

CfdFlow separates the description of a problem from its execution. A march runs a description until a predicate fires and yields a resumable pause. A campaign forks that pause once per candidate and continues each branch in its own alternated world. The fork shares the paused state in O(1) through copy-on-write, tensor fields, navigation engine and provenance log included, so the branch point is a flow-resolved state rather than a rerun from initial conditions.

The distinction carries a practical consequence. Forking parameters gives a sweep; forking state mid-flight gives the decision the vehicle faces, with its plume, its sheath, and its filter as they stand at that instant.

  • Fork setup measured at 42 ns; continuation cost 0.67–1.04× the trunk.
  • Bank-angle corridor: seventeen worlds, six coarse and eleven fine, with the best committed mid-descent.
  • Plasma retropulsion: the mid-burn fork of a marched plume-coupled state departs a frozen-drag prediction by 139.4 m/s.

Fork a running simulationWorked examples

References

  1. Teschner, T.-R. The 6 Biggest and Unsolved Challenges in CFD.CFD University, Cranfield University. Accessed 21 July 2026.cfd.university
  2. Slotnick, J., Khodadoust, A., Alonso, J., Darmofal, D., Gropp, W., Lurie, E., and Mavriplis, D. CFD Vision 2030 Study: A Path to Revolutionary Computational Aerosciences. NASA/CR-2014-218178, NASA Langley Research Center, March 2014.ntrs.nasa.gov/citations/20140003093

The challenge numbering above follows Teschner's article. Every measured figure is copied from a committed artifact underverification/ or studies/ , at f64 on an Apple M3 Max, release build.