Astrophysics
General-relativistic magnetohydrodynamics as a five-stage monadic pipeline
Couple a GR solver, a coupling layer, and an MHD solver through monadic bind. Curvature picks the metric; the metric drives the plasma physics; stability falls out at the end.
The full crate lives at examples/physics_examples/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 bind calls. Each one is a pure function from a GrmhdState to a PropagatingEffect<GrmhdState>.
use deep_causality::PropagatingEffect;
use model::{GrmhdState, SimulationConfig};
let result: PropagatingEffect<GrmhdState> = PropagatingEffect::pure(GrmhdState::new(&config))
.bind(|state, _, _| model::calculate_curvature(state.into_value().unwrap_or_default()))
.bind(|state, _, _| model::select_metric(state.into_value().unwrap_or_default()))
.bind(|state, _, _| model::calculate_lorentz_force(state.into_value().unwrap_or_default()))
.bind(|state, _, _| model::calculate_energy_momentum(state.into_value().unwrap_or_default()))
.bind(|state, _, _| model::analyze_stability(state.into_value().unwrap_or_default()));
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 bind operator threads the state through. Adding a third solver is one more .bind(...) call. 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.