Skip to content

feat(solver): add 3D XLB recovery surrogate#118

Draft
andrinr wants to merge 2 commits into
feat/ns-grid-surrogate-solverfrom
feat/ns-3d-grid-recovery-surrogate
Draft

feat(solver): add 3D XLB recovery surrogate#118
andrinr wants to merge 2 commits into
feat/ns-grid-surrogate-solverfrom
feat/ns-3d-grid-recovery-surrogate

Conversation

@andrinr

@andrinr andrinr commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

This stacked draft adds a task-specific differentiable solver for the existing
3D initial-condition recovery benchmark:

  • direct full-field v0 -> u(T) prediction, not a one-step/autoregressive rollout
  • fixed N=16, nu=0.01, dt=0.02, 100-step, triply-periodic contract
  • width-32 3D periodic FNO with six modes/axis and six residual spectral blocks
  • exact viscous-diffusion skip plus Helmholtz-projected inputs, outputs, and VJPs
  • packaged inference code and weights only; training and dataset-generation
    code remain outside the repository

This PR is stacked on #117 because both solvers share the
navier-stokes-grid Tesseract family. Cross-suite exclusions prevent either
task-specific solver from entering the other dimensionality or general sweeps.
The canonical drag output is zero: this periodic 3D task has no obstacle and
there is no learned drag head.

Offline teacher selection

All experiments used the same shared Mosaic Slurm runner and Pyxis/Enroot image
path as the solver-in-the-loop work, on RTX 5090 GPUs. No hosted benchmark was
run. Exact-cell warm in-process medians:

solver forward VJP
XLB 4.812 ms 14.368 ms
Exponax 10.447 ms 19.475 ms
Warp-NS 95.453 ms 215.824 ms
PhiFlow 145.900 ms 283.464 ms
PICT 822.847 ms 2,300.287 ms

XLB is therefore the training teacher.

Training provenance

  • 8,192 direct XLB KBC D3Q27 trajectories
  • split 6,144 / 1,024 / 1,024
  • benchmark IC seeds 0, 1, and 2 excluded from every split
  • amplitudes from zero to 1.25, centered on the benchmark |k|=2 shell with
    broader divergence-free spectra mixed in
  • derivative distillation from 4,096 float64 XLB directional JVPs
  • trajectory dataset SHA-256:
    0257c89ec3a8f4886f81960cc6867a24278de8b35b745cc98c6a1471ca3f6b8a
  • JVP dataset SHA-256:
    46432889c24aa8b4e6e1f1a4bf0d1c40b866930f56cfed86157d92d42ef107ee
  • packaged checkpoint SHA-256:
    8669ebaf92d920668c945b04722021fef12d5fc6fa4aa182abc63c81780ed0c9

Held-out fields and derivatives

On the three excluded benchmark ICs:

metric value
final-field relative L2 7.151%
final-field cosine 0.997441
random projected JVP cosine 0.849667
random projected JVP relative error 0.591554

The random-white tangent probe is deliberately harsher than the low-frequency
recovery manifold; held-out training-distribution directional-JVP relative
error is approximately 15%.

Three orthogonal slices of the held-out full-field prediction

Exact projected-L-BFGS recovery

This is the existing
optimization/recovery_constant_ic_bfgs_proj cell, unmodified: zero
initialization, 100 iterations, seeds 0/1/2, and each solver generating and
inverting its own final field.

solver seed 0 seed 1 seed 2 mean
XLB 4.70% 5.02% 5.94% 5.22%
XLB 3D surrogate 6.20% 6.92% 8.15% 7.09%

Mean final-field MSE is 2.58e-8 for XLB and 5.33e-8 for the surrogate.
Both complete all 100 iterations and pass the registered recovery threshold.

Recovered initial and final full fields

Full 3D IC recovery evolution

Timing: kernel versus harness

measurement XLB surrogate speedup
packaged forward kernel 4.812 ms 0.920 ms 5.23x
packaged VJP kernel 14.368 ms 1.082 ms 13.28x
exact recovery harness 30.96 s 24.48 s 1.26x
recovery peak VRAM 1,110 MiB 823 MiB 1.35x lower

The harness speedup is intentionally reported separately. HTTP/RPC, host
callbacks, L-BFGS bookkeeping, Helmholtz projection, line search, serialization,
and synchronization dominate this small N=16 cell; kernel acceleration
therefore cannot translate one-for-one to end-to-end acceleration.

Recovery accuracy and timing decomposition

Jacobian conditioning

The full-output Jacobian d u(T) / d v0 was evaluated at seeds 0/1/2 on the
complete 512-dimensional real divergence-free Fourier subspace through
|k| <= 4 (both transverse polarizations and sine/cosine phases; mean and
longitudinal modes excluded). This is the recovery-relevant subspace, not a
claim about every Nyquist-scale direction.

seed XLB kappa(J) surrogate kappa(J)
0 7.182 6.758
1 6.632 6.497
2 6.778 6.434
mean 6.864 6.563
  • mean kappa(J^T J): 47.17 XLB, 43.09 surrogate
  • mean Jacobian Frobenius cosine: 0.9901
  • mean Jacobian Frobenius relative error: 14.02%
  • mean effective rank: 418.8 XLB, 420.9 surrogate

XLB and surrogate recovery-subspace Jacobian spectra

Negative result: surrogate inversion of XLB observations

Self-recovery does not establish that the surrogate can invert an
XLB-generated observation. I ran that cross-model test separately: the targets
come from XLB, while projected L-BFGS differentiates through the surrogate.

metric seed 0 seed 1 seed 2 mean
final IC error at 100 iters 40.33% 41.53% 42.54% 41.47%
best saved IC error 17.78% 18.42% 20.87% 19.02%
surrogate residual to XLB target 1.33% 1.43% 1.58% 1.45%
XLB re-evaluation residual 6.51% 7.01% 9.16% 7.56%

The optimizer exploits surrogate model error after roughly 15 iterations:
surrogate-space loss keeps falling while the recovered IC moves away from the
truth. This checkpoint is a useful self-consistent benchmark solver, but it is
not yet a drop-in inverse model for XLB observations.

Cross-model recovery failure mode

Validation and artifacts

  • packaged Tesseract API check passed in its generated Enroot image
  • focused unit tests: 4 passed
  • Ruff lint and format checks passed
  • GitHub Python 3.12/3.14, pre-commit, config validation, and title checks passed
  • hosted solver builds and benchmarks skipped via benchmark:none

Supporting data: artifact index,
manifest and job IDs,
held-out field/JVP evaluation,
conditioning spectra,
XLB recovery envelope,
surrogate recovery envelope,
and cross-model recovery.

@andrinr andrinr added the benchmark:none Skip benchmarks (maintainer trusts no answer-changing code) label Jul 26, 2026
@PasteurBot

Copy link
Copy Markdown
Contributor

📊 View the full benchmark results

No benchmarks ran for this PR, so there is no status report.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

benchmark:none Skip benchmarks (maintainer trusts no answer-changing code)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants