Spatial UDE feasibility — environment-dependent neural closure over a field¶
Follow-up to the 0-D hybrid probe (scripts/hybrid_feasibility_probe.py): can a
neural closure that depends on the local environment be learned end-to-end
through the differentiable BGC, batched over a spatial field? This is the
Track-2 thesis the 0-D box cannot demonstrate (it homogenizes spatial structure),
and it is exactly the structure tonight's Southern-Ocean calcite finding
(scripts/per_pft_picpoc_validate.py) says the real process has.
Script: scripts/hybrid_spatial_h200.py (+ scripts/slurm/run_hybrid_spatial_h200.sbatch).
Setup¶
Each cell of an H×W field has its own iron DFe (spanning the limitation knee)
and a local environment scalar env ∈ [0,1] (stand-in for temperature /
saturation / light). A 2-input net learns the closure f(iron, env) end-to-end;
truth is iron-limitation(DFe) × env-window(env).
Result (RTX 5090, 9,216-cell field, 2000 epochs, ~4.7 min)¶
| metric | value |
|---|---|
| loss | 0.61 → 3.8e-5 (↓ ~15,900×) |
| 2-D closure recovery (MAE) | 0.0044 (0.44%) |
The hybrid recovers a spatial, environment-modulated closure to sub-percent accuracy. This is the concrete Track-2 leapfrog: differentiably learning the kind of environment-gated, spatially-varying process the per-PFT/SO finding points to.
Launch-bound / torch.compile (corrected)¶
The per-step rollout is launch-bound. A clean benchmark (RTX 5090, 9,216 cells, 100 steps, warmed up at the timing shape):
| mode | ms/iter |
|---|---|
| eager python loop | 236 |
torch.compile(step) |
80 (≈3×) |
torch.compile does fix the launch-bound (~3×). An earlier run reported
0.8× ("slower") — that was a benchmarking bug: the compiled step was warmed
up at n=5 but timed at n=200, so recompilation contaminated the timing. Fixed
in hybrid_spatial_h200.py (epoch_time now warms up at the timing shape).
Cluster note¶
The H200 job (gpu-short, node d4054) ran on a real H200 but, on the pre-fix
script, its eager/launch-bound per-epoch (~1 s) overran a tight 30-min wall before
writing JSON. The science is device-independent (the 5090 result stands); a
right-sized H200 rerun with the fixed script is a clean-up, not a blocker. Next
real GPU lever for scale: TF32 (set_float32_matmul_precision('high')),
compiling the whole rollout / CUDA graphs, and larger fields.