Skip to content

Test solve! on a body built from two wings - #339

Merged
1-Bart-1 merged 2 commits into
mainfrom
agent/143-add-test-for-multiple-wings
Sep 16, 2026
Merged

1-Bart-1 merged 2 commits into
mainfrom
agent/143-add-test-for-multiple-wings

Conversation

@1-Bort-1

@1-Bort-1 1-Bort-1 commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

TL;DR

A new testset solves a BodyAerodynamics built from two wings and checks the result against the same wing on its own. Until now the only multi-wing test checked set_va!, so nothing would have caught a break in how the solver or the result bookkeeping steps from one wing's panels to the next.

What the test checks

solve! on a two-wing body in test/body_aerodynamics/test_body_aerodynamics.jl uses a 4 m × 1 m flat INVISCID wing: 3 sections, 6 panels, va = [10, 0, 1]. The single-wing baseline must itself come out FEASIBLE.

  • Wings 10 km apart: each wing must behave like the wing alone. That means 12 panels, FEASIBLE, projected area ×2, circulation and cl_unrefined_dist equal to the single wing's repeated twice, force ×2 and the same force coefficients, all to rtol=1e-6. The largest relative circulation difference measured was 6.3e-9.
  • Wings 1 m (one chord) apart: they must affect each other. The circulation must be mirror-symmetric about the gap, the two facing tips must carry more than 1.05× the isolated tip circulation (measured 1.779 vs 1.636, i.e. 1.087×), and the lift must exceed twice the isolated lift (203.7 N vs 194.8 N).

Nothing in src/ changed. Bart confirmed on the issue that the feature works, and the test agrees.

Does it catch a break?

There was no bug to reproduce, so I broke the source on purpose in two runs and reverted each afterwards. The first run carried two changes at once, so which assertion caught which of those two is inferred, not measured:

  • Stopped calc_forces! from advancing unrefined_idx between wings (src/solver.jl:520) and took projected_area from wings[1] only (src/body_aerodynamics.jl:316). 3 failures: projected area, cl_unrefined_dist (wing 2 came out as zeros), force coefficients (0.787 vs 0.394).
  • Zeroed the AIC entries between the two wings. 2 failures: tip circulation 1.636 is not > 1.718, and lift 194.8 N is not > 194.8 N.

Found on the way, not changed here

These all change behaviour, so they are not in this PR. They are why the test uses equal n_panels, the default ZEROS initial circulation, and no artificial damping or viscosity.

  • results["wing_span"] and results["aspect_ratio_projected"] use wings[1].span over the projected area summed over all wings (src/body_aerodynamics.jl:997). For a multi-wing body both numbers are wrong.
  • calc_forces! and calculate_results take the lift and side directions from wings[1].spanwise_direction for every panel (src/solver.jl:393, src/body_aerodynamics.jl:860). Wings pointing different ways would get wrong directions.
  • type_initial_gamma_distribution=ELLIPTIC, linearize and make_dual_shadow throw for more than one wing.
  • The artificial-viscosity Laplacian and smooth_circulation! treat all panels as one span, so they smooth across the gap between wings.
  • cl_unrefined_dist is not symmetric on a symmetric single wing: [0.371, 0.435, 0.327] while the circulation is symmetric to 1e-15. This looks like how panels are mapped to unrefined sections, not a multi-wing issue. I did not dig further.

Verification

  • Reproduced first: n/a. Test for a working feature; the two mutant runs above fail it (3 + 2 failures)
  • test/body_aerodynamics/test_body_aerodynamics.jl after the helper merge: 4870 pass, 0 fail, 0 error (juliaserver, Julia 1.12.7)
  • Local full suite (agent ci-local, Julia 1.12.7, fail-fast): PASS in 8 min, exit 0 on 7f2d15f · GitHub CI: all 7 checks green on 7f2d15f
  • Up to date with origin/main · docs and changelog: n/a (test only) · no REUSE in this repo
  • Benchmark: n/a
  • Risk: the 1.05× tip threshold depends on the solver's physics. A deliberate change to the induction model could move it, but it has 3.7 percentage points of margin.

Scope

+63 / -25 in one test file: the new testset, a solve_wings helper, and inviscid_wing(section_y; n_panels). That helper also replaces the same three-section wing the file built by hand in Origin Translation, the distributed-inflow set_va! test and the multi-wing set_va! test. The multi-wing set_va! test now refines with LINEAR instead of UNCHANGED. Its sections are evenly spaced, and its assertions compare each panel's va with its own control point, so what it checks is unchanged. I searched test/ and examples/ for an existing flat-wing helper. flat_plate_wing in test/solver/test_solver.jl uses a stalling LEI polar, flat_wing in test_backend_comparison.jl is local to its testset and takes polar matrices, and build_flat_wing in test_billowing.jl has its chord pointing to -x. None of them fits.

Closes #143 · task VortexStepMethod.jl-143

Two copies of a rectangular wing far apart must each reproduce the
isolated wing (circulation, unrefined distribution, force, coefficients);
one chord apart they must induce on each other.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@1-Bort-1 1-Bort-1 added agent:running Agent task state agent:ci Agent task state and removed agent:running Agent task state labels Sep 16, 2026

@1-Bort-1 1-Bort-1 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent review (advisory)

Verdict: APPROVE WITH COMMENTS · 2 inline, 0 off the diff

Good

  • Matches the card's scope: one test file, +56/-0, no src/ changes; the diff is exactly the two helpers and the one testset the card describes
  • The far-apart case compares against the same wing solved alone, with rtol=1e-6, so a bookkeeping break shows up as a clear mismatch; the card's mutant runs show it fails for unrefined_idx and projected_area
  • The one-chord case checks mirror symmetry and more circulation at the facing tips; the zeroed cross-AIC mutant shows these fail when the wings stop inducing on each other
  • Testset names say what behaviour they protect (wings far apart each act as the isolated wing); only three small solves, so it adds no real CI time
  • Checked for conflicts: rg finds no other rectangular_wing or solve_wings function in test/ or examples/, so the top-level helpers cannot clash in runtests' shared scope
  • No line in the new block is over 92 characters (checked by grep for 93+ character lines)
  • The card explains why flat_plate_wing in test/solver/test_solver.jl can't be reused (stalling LEI polar, no y offset), and that holds up

Not good

  • test/body_aerodynamics/test_body_aerodynamics.jl:516 — The same file already builds this flat 3-section INVISCID wing by hand three times (lines ~123, ~446, ~474–482, including the existing two-wing set_va! test), and the new helper doesn't replace any of them. That leaves two ways to build the same wing in one file, which the §7 compaction pass should have merged.
  • test/body_aerodynamics/test_body_aerodynamics.jl:538 — Every call passes n_panels=6, span=4.0, the same as the defaults, and chord and va are never passed. That is flexibility no caller uses (§6/§7), and 6 and 4.0 now live in two places that can drift apart.
  • The single-wing baseline's solver_status is never checked; if the reference solve stopped converging, the far-apart comparisons would pass or fail against a bad baseline
  • The card says it broke the source 'three ways, one run per mutant' but lists two runs, and the first run combined two changes, so which assertion catches which change is inferred, not measured
  • Five real defects found on the way (wing_span/aspect_ratio_projected using wings[1], lift and side directions from wings[1], ELLIPTIC/linearize/dual-shadow throwing for more than one wing, smoothing across the gap, asymmetric cl_unrefined_dist) are only PR notes; Closes #143 will close the one open multi-wing thread, so they need their own issues or they get lost
  • The far-apart test compares against single.cl_unrefined_dist, which the card itself says looks wrong on a symmetric wing, so the test locks in current output, not correct output
  • The rectangular_wing docstring gives no units for y_center, span and chord ([m]), which §4 asks for when the name doesn't carry them

claude, rubric CLEAN_CODE.md. A different lab from the implementer
on purpose: a reviewer sharing its blind spots would not flag its mistakes.

@1-Bort-1 1-Bort-1 added agent:review Agent task state and removed agent:ci Agent task state labels Sep 16, 2026
@codecov

codecov Bot commented Sep 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@1-Bort-1 1-Bort-1 added agent:queued Agent task state agent:running Agent task state and removed agent:review Agent task state agent:queued Agent task state labels Sep 16, 2026
The file built the same three-section INVISCID wing by hand in three
testsets beside rectangular_wing; inviscid_wing(section_y; n_panels) now
builds all four. solve_wings drops its unused va keyword, and the
single-wing baseline checks its own solver status.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@1-Bort-1

1-Bort-1 commented Sep 16, 2026 •

Copy link
Copy Markdown
Member Author

Local full suite: PASS (9 min, Julia 1.12.7, one cell of the matrix)

@1-Bort-1 1-Bort-1 added agent:queued Agent task state agent:running Agent task state agent:ci Agent task state agent:review Agent task state and removed agent:running Agent task state agent:queued Agent task state agent:ci Agent task state labels Sep 16, 2026
@1-Bart-1
1-Bart-1 merged commit b83d4c1 into main Sep 16, 2026
7 checks passed
@1-Bart-1
1-Bart-1 deleted the agent/143-add-test-for-multiple-wings branch September 16, 2026 22:05
@1-Bort-1 1-Bort-1 added agent:done Agent task state and removed agent:review Agent task state labels Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:done Agent task state

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add test for multiple wings

2 participants