Astrophysics

General-relativistic magnetohydrodynamics as a five-stage CausalFlow pipeline

Couple a GR solver, a coupling layer, and an MHD solver through a CausalFlow chain. Curvature picks the metric; the metric drives the plasma physics; stability falls out at the end.

The full crate lives at grmhd. It is the “multi-physics monad”: gravity (tensor calculus) couples to plasma (multivector geometric algebra) through a binding stage that picks the right metric based on the local curvature. Five stages, one chain, one final state.

The chain

Spacetime Metric (g_uv) → Einstein Tensor (G_uv) → Metric Selection

                                           Lorentz Force (F = J·B)

                                               EM Stress-Energy

                                                Stability Analysis

Five and_then stages. Each model stage is a pure function that maps a GrmhdState to the next; it returns a PropagatingEffect<GrmhdState>, adapted into the flow with .into().

use deep_causality_core::CausalFlow;
use model::{GrmhdState, SimulationConfig};

CausalFlow::value(GrmhdState::new(&config))
    .and_then(|s| model::calculate_curvature(s).into())
    .and_then(|s| model::select_metric(s).into())
    .and_then(|s| model::calculate_lorentz_force(s).into())
    .and_then(|s| model::calculate_energy_momentum(s).into())
    .and_then(|s| model::analyze_stability(s).into())
    .run(print_conclusion, |err| eprintln!("Simulation failed: {err:?}"));

main.rs:56.

The five stages

The model module owns the stage functions. Each one is a pure function that takes a GrmhdState and returns a new PropagatingEffect<GrmhdState> with one more field populated.

Stage 1: GR solver. Computes spacetime curvature from the input metric. Uses CausalTensor from the tensor crate; the Einstein tensor is a contraction of the Ricci tensor under a simplified weak-field assumption.

Stage 2: Coupling layer. Reads state.curvature_intensity and selects the appropriate metric for the downstream solver. Below the curvature threshold the chain uses Euclidean; above it, Minkowski. The selection is a small expression that updates a label on the state.

Stage 3: MHD solver. Computes the Lorentz force F = J × B using CausalMultiVector from the multivector crate. The selected metric drives the inner product; the same code handles both flat and curved space without branching.

Stage 4: Stress-energy coupling. Derives the electromagnetic stress-energy density from the Lorentz force; this is what feeds back into general relativity in a real simulation. The example writes the scalar into state.em_energy_density and stops there.

Stage 5: Stability analysis. Reads the accumulated state and emits a stability verdict (stable / marginal / unstable) plus a status string.

The configuration

let config = SimulationConfig {
    current_density: 10.0,    // Plasma current J
    magnetic_field: 2.0,      // Magnetic field B
    curvature_threshold: 0.05,
};

Three knobs. Increasing the current density raises the Lorentz force. Increasing the curvature threshold delays the Euclidean→Minkowski switch. Both can be exercised without recompiling the chain.

What the architecture earns you

Multi-physics simulation usually runs into a structural problem: two solvers, each with its own state model, need to exchange information at every tick. The naïve coupling is a tangle of mutable references; the careful coupling is a custom interface that takes weeks to design.

The monadic version: the state is a value. Each stage is a pure function. The flow threads the state through. Adding a third solver is one more .and_then(...) stage. Removing one is the inverse. The chain is testable end-to-end without a harness because the input is a value and the output is a value.

If any stage fails, the chain short-circuits: the error field becomes Some(...), every downstream bind becomes a no-op, and the EffectLog preserves the trace of every stage that ran before the failure.

Run it

git clone https://github.com/deepcausality-rs/deep_causality
cd deep_causality
cargo run --release -p physics_examples --example grmhd_example

Expected output: a stage-labelled trace, then a summary block with curvature intensity, selected metric, Lorentz force magnitude, EM energy density, and the final stability status.

Why this is a good fit

Extreme-environment simulation (accretion disks, neutron-star magnetospheres, gamma-ray bursts) is exactly the case where you need both general relativity and magnetohydrodynamics, and you need them coupled. The Causal Monad turns the coupling problem into a list of stages and a bind chain. Mathematical correctness sits at the stage boundaries, where the input and output are typed values you can write tests for.