Skip to content

feat(solver): add full-field XLB cylinder surrogate#117

Draft
andrinr wants to merge 2 commits into
feat/ns-grid-solver-in-loopfrom
feat/ns-grid-surrogate-solver
Draft

feat(solver): add full-field XLB cylinder surrogate#117
andrinr wants to merge 2 commits into
feat/ns-grid-solver-in-loopfrom
feat/ns-grid-surrogate-solver

Conversation

@andrinr

@andrinr andrinr commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add a differentiable, full-field surrogate for the fixed N=32, Re=20
    cylinder-flow drag-optimization task
  • package only inference code, a model card, and the 3.0 MiB trained weight
    bundle; dataset generation and training remain external to this repository
  • decode final velocity plus tail-averaged velocity/pressure fields, then compute
    drag with the shared drag_jax surface integral (there is no scalar drag head)
  • preserve XLB's two exact no-slip wall-endpoint null directions in the
    full-field Jacobian
  • categorically exclude the task-specific model from out-of-distribution
    benchmark cells

This PR is stacked on feat/ns-grid-solver-in-loop.

Model and data

The residual MLP maps the 32-value inflow profile to 128 POD coefficients. Its
decoder reconstructs four 32 x 32 fields: final u_x, final u_y,
tail-averaged u_x, and tail-averaged pressure. The first two form the public
canonical velocity result; the latter two feed the same surface-traction drag
functional used by the projection solvers.

The external XLB-generated dataset contains 4,096 stable profiles split
3,072/512/512 for training/validation/test. Profile families include smooth
Fourier, multiscale, localized, and near-flat controls over the optimizer's
[0, 1.5] bounds.

  • dataset SHA-256: 2832fecfb85d1ced442b38b608c512c71aca224c9a3b982d39e736d2bdf16ac8
  • weights SHA-256: 6089ba29d9644e1f3b87404302b0b19aaeb7ea6ee0b359d7aa5fe395ef04626c

Offline accuracy and performance

All measurements below were run offline on RTX 5090 cluster nodes using the
same Slurm runner, Buildah, Enroot/Pyxis, and remote-Tesseract workflow as the
solver-in-the-loop work. benchmark:none is the PR disposition: CI solver
builds and benchmark execution are skipped.

Measurement Result
held-out final-velocity relative L2, mean / p95 (n=512) 0.99% / 4.47%
held-out drag MAE / R2 (n=512) 2.39e-4 / 0.99925
float64 XLB final-velocity relative L2 (n=8) 0.30%
float64 XLB drag MAE (n=8) 5.81e-5
drag-gradient cosine, mean / min (n=8) 0.9950 / 0.9885
drag-gradient relative L2, mean (n=8) 9.06%
compiled kernel forward speedup vs XLB 113x
compiled kernel VJP speedup vs XLB 206x

The compiled speedups measure synchronized, in-process JAX calls after
compilation. The full benchmark below exercises the remote Tesseract protocol
for every forward/VJP, including HTTP/base64 serialization, request scheduling,
client bookkeeping, and periodic checkpoint writes. Those fixed costs dominate
this small 32 x 32 model: the full optimization is therefore 1.17x faster
end-to-end (31.09 / 26.50) rather than 113x.

A separate 250-update exploitation check reached surrogate drag -0.04689;
float64 XLB re-evaluation of the final profile gave -0.04758. The packaged
Tesseract's full harness run independently reproduced this: its final
full-field surface-integral drag was -0.04699, and float64 XLB re-evaluation
of the saved final profile was -0.04758.

Full-field Jacobian conditioning

For J = d(final velocity) / d(inflow profile), both XLB and the surrogate
have rank 30. The two exact null directions are the profile samples at the
no-slip wall endpoints: XLB overwrites those inlet corners with no-slip states,
and the surrogate now preserves the same gradient semantics without changing
its forward predictions.

The table reports median values over eight held-out profiles. Since the raw
condition number is infinite in both models, kappa_resolved is
sigma_max / sigma_min over singular values above a relative 1e-6 threshold.

Output region XLB kappa_resolved Surrogate kappa_resolved Jacobian Frobenius cosine
full returned velocity 4.79 5.03 0.9788
interior (without inlet, walls, cylinder) 15.36 40.38 0.9729
wake (x >= 0.5) 46.49 51.13 0.9758

The inlet identity makes the full returned-field spectrum look especially
well-conditioned; the interior number is the more revealing dynamics-only
diagnostic. The surrogate is more ill-conditioned there, although the
Jacobian orientation and wake spectrum remain close to XLB.

Held-out XLB and surrogate full-field Jacobian spectra

Full optimization/drag_opt benchmark

Solver Initial drag Final drag Reduction Updates Harness wall time
XLB -0.068912 -0.047789 30.65% 250 31.09 s
XLB surrogate -0.068863 -0.046985 31.77% 250 26.50 s
PICT -0.023863 -0.017738 25.67% 250 2148.98 s
PhiFlow -0.000835 -0.000710 15.04% 250 461.90 s

Offline optimization fields

Media is generated from the completed offline runs. The full-field GIF replays
the 14 saved optimizer-profile checkpoints through the packaged surrogate; its
frames are actual decoded velocity fields, not interpolation. Because this is a
direct profile-to-final-state model, the animation axis is optimization update,
not physical simulation time.

Offline optimization summary and kernel-versus-harness timing

Final full velocity and vorticity fields for all solvers

XLB-surrogate full-field evolution over saved optimization checkpoints

All-solver inflow-profile evolution over saved optimization checkpoints

Supporting data: artifact index,
run manifest,
held-out/gradient/timing evaluation,
full-field Jacobian conditioning,
and float64 XLB final-profile re-evaluation.

Validation

  • ruff check mosaic tests
  • ruff format --check mosaic tests (156 files already formatted)
  • full cluster suite: 492 passed, 3 skipped
  • Buildah image build plus Enroot/Pyxis round trip and packaged
    tesseract-runtime check
  • offline full optimizations: XLB 1533241, XLB surrogate 1533244,
    PICT 1533248, and PhiFlow 1533243
  • float64 XLB final-profile check 1533250, field-history replay 1540226,
    final render 1540227, and Jacobian conditioning 1540907

@andrinr andrinr added the benchmark:none Skip benchmarks (maintainer trusts no answer-changing code) label Jul 25, 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