chc.transport¶
Stability tier: experimental.
Continuum mean-field control: the density transport PDE rho_t + (rho v)_x = s.
The continuous-space sibling of chc.meanfield.MeanFieldControl (which lives on a finite
zone graph). Agents are a density rho(x, t) on a periodic 1-D domain; a velocity field v
advects them and a source s injects/removes mass. Two pieces, both honest and validated:
- a conservative finite-volume solver (upwind flux) that conserves total mass to machine
precision -- the physical invariant of a continuity equation -- advanced by Strang-Marchuk
operator splitting (advection & reaction), reusing
chc.splitting.strang_marchuk_step. This is where the Marchuk framing earns its keep on a genuine PDE; the split is 2nd-order in time; MeanFieldTransport, which picks the velocity field steeringrhofrom an initial to a target profile at least transport effortsum rho v^2-- a discretised dynamic optimal transport / mean-field game, differentiable straight through the conservative solver.
The discrete zone graph stays the primary model, with most of the value at a fraction of the cost; this continuum model is built as its elegant limit, with the mass-conservation and splitting-order gates that make it trustworthy rather than merely elegant.
MeanFieldTransport
dataclass
¶
Steer a density rho(x,t) to a target by choosing the velocity field (continuum MFC).
Minimises terminal mismatch ||rho_T - target||^2 plus transport effort sum rho v^2 over
a time-varying velocity field, advecting mass with the conservative solver. The velocity is
CFL-capped so the explicit scheme stays stable no matter what the optimiser proposes.
rollout_cost(v_seq)
¶
Terminal mismatch + transport effort for a velocity plan v_seq (horizon, n).
plan(steps=300, lr=0.05)
¶
Adam on the velocity field through the conservative solver; keep the best-seen plan.
mismatches(steps=300)
¶
Terminal mismatch with no control vs the planned velocity field (lower is better).
transport_step(rho, v, k, s, dx, dt)
¶
One Strang-Marchuk step of rho_t + (rho v)_x = -k rho + s (reaction & advection).
solve_transport(rho0, v, k, s, dx, dt, steps)
¶
Roll the Strang-Marchuk step steps times; return (final_density, trajectory).
periodic_wavenumbers(n, length)
¶
Real-FFT wavenumbers k_m = 2*pi*m/length for m = 0 .. n//2.
advection_diffusion_symbol(n, length, *, speed, viscosity)
¶
Symbol of the translation-invariant vector field -c u_x + nu u_xx: -i c k - nu k^2.
Derived in validation/spectral_circulant.mac STEP 5: substituting exp(i(kx - wt)) gives
w(k) = c k - i nu k^2, so the phase speed is c at every wavenumber -- the advection is
NON-dispersive and all the k-dependence sits in the exp(-nu k^2 t) decay.
On an even grid the Nyquist bin is set to zero for the advection part, and that is the correct
discrete answer rather than a patch: the Nyquist mode is cos(pi j) = (-1)^j, whose exact
derivative -pi sin(pi j) vanishes at every grid point, so the sampled first derivative of
that mode is identically zero (STEP 7). It is also what keeps the operator a REAL circulant --
a real first column forces a real eigenvalue at Nyquist, which -i c k is not.
advection_diffusion_kernel(n, length, *, speed, viscosity)
¶
First column of the circulant realising that vector field -- the truth to be recovered.
A chc.residual.SpectralResidual parameterises exactly this vector, so on this plant the
truth lies IN the hypothesis class. That is deliberate: it makes a failure to recover it a
failure of the fit rather than of the model, which is what the comparison against an MLP is
supposed to isolate.
advection_diffusion_field(u, length, *, speed, viscosity)
¶
Apply -c d_x + nu d_xx to a periodic field, spectrally and therefore exactly.
advection_diffusion_propagator(u, length, *, speed, viscosity, dt)
¶
The EXACT solution operator over dt: exp(-i c k dt - nu k^2 dt) applied spectrally.
Exact in time as well as in space, so it introduces no discretisation error of its own -- unlike
transport_step, whose upwind flux and Strang split are second-order at best. The price
is that it only exists because the operator is linear and translation-invariant, which is
precisely the structure chc.residual.SpectralResidual is built to exploit.
periodic_smoothing_kernel(n, length, width)
¶
A periodic Gaussian convolution kernel, unit gain at k = 0 -- a NONLOCAL actuator.
Control applied in one cell spreads to its neighbours. A diagonal control matrix cannot express that and a circulant can, which is why the certificate gives the control channel its own kernel rather than a scalar.