Conversation
…il's The ram-air wing's tip sections are ~70%-thick slices (#361) on which NeuralFoil returns Cd=1 at every alpha, and those outputs differ with the runner's CPU, so the LOOP solve lands on one of two different solutions depending on the runner. Tables that are affine in (alpha, delta) make the bilinear interpolation exact, keep every panel attached, and are the same bits on every machine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1-Bort-1
left a comment
There was a problem hiding this comment.
Independent review (advisory)
Verdict: APPROVE WITH COMMENTS · 2 inline, 0 off the diff
Good
- The change goes after the cause: affine tables make bilinear interpolation exact, so no grid knot can be a kink, and the tables no longer depend on the CPU; the three-dispatch CI result in the card, with norm_fwd bit-identical across 15 cells, backs this
- The solver settings, operating point, input indices, rtol and the
< 1e-4assertion are unchanged (the unchanged context lines confirm it), so no test was weakened - The knot-offset comment block is gone: it described a mechanism the card shows was wrong (the runners land on two solutions 11° apart, not near a knot)
- No existing helper duplicates this one:
rgfinds onlyram_air_matrix_wingintest/test_data_utils.jl(NeuralFoil) and a local two-sectionflat_wingclosure intest_backend_comparison.jl - The card names the
ram_*→matrix_*rename and scopes it to the testset's locals;src/is untouched and the diff stays at one idea
Not good
test/solver/test_forwarddiff.jl:8— This is a two-line comment block explaining why the tables are affine, which is the kind of why §3/§5 route to the PR card. At most keep one line, e.g. 'affine tables: bilinear interpolation is exact'.test/solver/test_forwarddiff.jl:79— The Windows ForwardDiff norm of 2.0576, which matched neither converged solution while norm_fd was bit-identical to ubuntu, is left unexplained, and this swap is what stops it being exercised. Under §5 that needs its own issue linked from the PR, or a possible Dual-path bug goes silent with the flake.- The card's 'Where I would push back' items (test_results.jl has the same NeuralFoil exposure,
fail-fast: falsein CI.yml) are noted but not linked to an issue; #361 covers the first only by implication - The check now runs only on smooth attached flow with affine tables, so it no longer tests ForwardDiff through a real table's curvature or near stall; the card names this as the risk, but no other test picks that coverage up
affine_matrix_wing(n_panels)has a single caller that passes 8; the argument is harmless but a literal inside the helper would say the same thing
claude, rubric CLEAN_CODE.md. A different lab from the implementer
on purpose: a reviewer sharing its blind spots would not flag its mistakes.
|
|
||
| relative_error(jac, reference) = maximum(abs.(jac .- reference)) / maximum(abs, reference) | ||
|
|
||
| # Four-section arc whose POLAR_MATRICES tables are affine in (alpha, delta), so the |
There was a problem hiding this comment.
MINOR: This is a two-line comment block explaining why the tables are affine, which is the kind of why §3/§5 route to the PR card. At most keep one line, e.g. 'affine tables: bilinear interpolation is exact'.
| ) | ||
| ram_body = BodyAerodynamics([ram_wing]) | ||
| ram_solver = Solver(ram_wing.n_panels, ram_wing.n_unrefined_sections; | ||
| matrix_wing = affine_matrix_wing(8) |
There was a problem hiding this comment.
MINOR: The Windows ForwardDiff norm of 2.0576, which matched neither converged solution while norm_fd was bit-identical to ubuntu, is left unexplained, and this swap is what stops it being exercised. Under §5 that needs its own issue linked from the PR, or a possible Dual-path bug goes silent with the flake.
…ide it Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Local full suite: PASS (12 min, Julia 1.13.0, one cell of the matrix) |
|
This is not the solution right and should be closed. |
…ompiles for Dual{10} on Zen 4/5
panel_body_loads (@noinline) now returns panel_loads plus the moment about the
reference point, for calc_forces! and for the body_aerodynamics results loop,
which carried the same moment line. The POLAR_MATRICES testset also checks that
the Jacobian does not depend on the ForwardDiff chunk size.
Refs #360, #379
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…bounds=yes Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TL;DR
The
AutoForwardDiff matches AutoFiniteDiff (LOOP, POLAR_MATRICES)check now runs on a four-section arc whose polar tables are affine in (alpha, delta). Before, it ran on the NeuralFoil ram-air wing. That wing's tip polars are junk that changes with the runner's CPU, so each runner solved a different flow and the check was a coin flip.What was wrong
The issue blamed alpha knots. The grid offset it suggested was already on
main(-2:5:23), and the check still fired: 0.0571 on Windows in #372's run 35653997846. So I printed the converged panel alphas on every CI cell, from a throwaway diagnostic branch dispatched three times (since deleted). Runners converge to two different solutions of the same code:norm(jac)That is 11° apart on panel 1, not a hair's width across a knot. The cause is in the tables. At n_sections=4,
ram_air_matrix_wing's tip slices are ~70% thick (airfoils/1.datspans −0.46 to 0.23 chord; this is #361). NeuralFoil's answer on them is out of distribution: Cd = 1 at every alpha, cl negative on one tip and flat on the other. An out-of-distribution network output moves with BLAS kernel roundoff, so the table, and with it the converged flow, depends on which CPU the job lands on. At zero sideslip the wing even carries a side-force coefficient of 0.128.Locally, on one table, the solution is unique from every initial guess (elliptic, zero, mirrored, tip-stalled), so this is not a multiple-root problem inside the solver.
What changed
affine_matrix_wing(8):cl,cdandcmaffine in (alpha, delta) on a 5° grid.rtoland the< 1e-4assertion are unchanged.Locally, fwd vs FD agree to 5.8e-9 to 4.5e-8 at every aoa from 0° to 12°, including 7.5° + 1e-9°. No setting lands near a boundary.
Where I would push back
norm_fdwas bit-identical to ubuntu 1.13's (2.0741507267422183), yet ForwardDiff gave 2.0576, which matches neither solution. Locally the Dual solve's primal is bit-identical to the Float64 one, repeated Dual Jacobians are identical, and filling everyLazyBufferCachebuffer with NaN changes nothing. All three diagnostic Windows cells landed on S2, and ForwardDiff matched there. This PR removes the junk-table, post-stall operating point that the mismatch only ever showed up on; it does not show that a Windows-only Dual difference cannot exist.test/body_aerodynamics/test_results.jlcheckslinearizeagainst the same NeuralFoil ram-air tables, with loose 5e-3/1e-1 tolerances. It has the same exposure but has not fired. It is left alone here; march_edges gives each station the previous station's leading-edge step, so a cut near a closing tip grazes the surface and reports an 80%-thick section #361 fixes the tip slices it depends on..github/workflows/CI.ymlcarriesfail-fast: false, which AGENTS.md §4 wants removed in acleanup:PR. Not touched here.Verification
0.057102607132145794 < 0.0001(run 35653997846). The flake could not be made to fail locally: the old test passed at 2.27e-8 on this box's table. The two-solution split above comes from diagnostic CI runs 35661076607, 35661081582 and 35661086944.test/solver/test_forwarddiff.jlpasses after the change: 10/10, POLAR_MATRICES rel. error 1.3e-8 (juliaserver, Julia 1.13.0). There is no local red before the change, because the failure depends on the runner.agent ci-local, Julia 1.13, fullPkg.test): PASS in 5 minnorm_fwd= 2.84152755639267 in every cell, on Windows, macOS and ubuntu, Julia 1.12 and 1.13;norm_fddiffers only in the 11th digit, on ubuntu 1.12main(9ed3cd6)Scope
+24 / −16 in
test/solver/test_forwarddiff.jl: theaffine_matrix_winghelper (+19) replaces the knot-offset comment and theram_air_matrix_wingcall. The locals are renamed fromram_*tomatrix_*, since the wing is no longer the ram-air kite.src/is untouched.Closes #360 · task
VortexStepMethod.jl-360