Repository navigation
Feature/curved bound vortex regularisation - #165
Merged
Merged
Conversation
The quarter-chord flow that sets the force directions (TAT3) held the other panels' bound segments evaluated on the bound line itself. On a curved or swept line that self-induction is logarithmically singular (Li, Gaunaa, Pirrung, Ramos-Garcia & Horcas 2020, "LL-P&S"), and because the on-blade induced drag is rho*Gamma*(w cos a + u sin a) with w only ~1 deg of induced angle, the chordwise u it produces moved the V3 drag by 10% and kept moving it with the panel count: on-blade over Trefftz 0.93 / 0.90 / 0.86 at 20 / 50 / 150 panels. Leaving the term out is worse (swept wings collapse, because the streamwise legs carry the opposite singularity), and reusing Li's 3/4-chord difference at the quarter chord breaks straight wings here. Replace the term by the difference between the actual vortex system and the same wing unrolled onto each panel's tangent line, with the bound vorticity and the leg starting points of every ring spread along the chord with the thin-airfoil distribution sqrt((c-x)/x). The quarter-chord velocity is then Prandtl's downwash of the unrolled wing plus a bracket that is identically zero on straight wings, finite on curved ones (the distribution fixes the cut-off at 0.15 c, no tunable length) and mesh-independent. Same mechanism as the effective-lifting-line / jointed-vortex method of Reid & Hunsaker (2020), whose two empirical lengths it removes; discrete counterpart of the inner solution of curved lifting-line theory (Guermond 1990). On-blade over Trefftz induced drag, inviscid: straight 1.000 (unchanged); arc R=4c 0.999 at 40, 80 and 160 panels; V3 1.007 / 1.008 / 1.010; swept 30 deg 0.97 -> 0.99; swept-anhedral elliptic wing of Gaunaa et al. 1.01. V3 viscous polars: lift unchanged, CD +0.001 at 5 deg, +0.006 at 10 deg, +0.011 at 13 deg, onto the RANS values. Cost: one numba kernel evaluated once per solve (about 1 s at 80 panels). Docs: Solver.md section on the consistent coupling, figures 03 (regenerated), 08 (mechanism and fix) and 09 (V3 polars) with README entries. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…und-vortex regularisation docs/validation/curved_bound_vortex_validation.py reproduces every table of the report from the committed solver: on-blade over Trefftz induced drag against panel count for a straight wing, skewed ribs, a 30 deg swept wing, a circular arc, the TORQUE 2026 swept-anhedral elliptic wing and the V3, for the regularisation and for the alternatives that were tried and rejected (trailed system only, bound segments on the line as on develop before, the literal Li et al. 2020 recipe, the Reid & Hunsaker 2020 effective-line construction with its joint and blending parameters), the arc mid-span self-induction (polyline vs chordwise-spread sheet), the V3 viscous polars, and figures 08 and 09. Full run 193 s; results in the JSON next to it. docs/validation/curved_bound_vortex_report.tex/.pdf: problem statement, cause, literature (Li 2018/2020, Gaunaa 2026 and its online appendix, Reid & Hunsaker, Guermond 1990, core methods), the formulation, the verification tables and the V3 polars against RANS and the wind tunnel, plus the two points where the code still deviates from the published Li/Gaunaa prescription. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… the regularisation in place docs/validation/leg_direction_study.py repeats the September leg-direction comparison with the curved bound-vortex regularisation (f43bcdb) instead of the singular bound-on-line term: on-blade over Trefftz induced drag on the arc, the swept-anhedral elliptic wing, the inviscid V3 and a kinked 30 deg swept wing, with the attached-trailed force on and off, and the V3 viscous polars against RANS, for rib legs and for span-perpendicular (CP1) legs. Results in leg_direction_study.json (149 s). Outcome: the rib legs stay. Perpendicular legs cannot be built on the kinked planform (adjacent perpendiculars cross, NaN), lower the V3 inviscid lift by 6% and the agreement with RANS (mean |dCL| 0.031 against 0.020), and with the attached-trailed force sit 2.5-4% above the Trefftz plane on the swept V3 and elliptic lines, the same excess the TORQUE 2026 appendix shows on the authors' swept wings. Rib legs are within 1.5% on every curved case. No solver change. Report: new Section 4.3 with the table, status item 2 and the open items updated; PDF rebuilt (10 pages). Figures README entry 07 carries the new numbers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… discrepancy 118e91d stated that the TORQUE 2026 appendix shows the same 1-6% excess of on-blade over Trefftz induced drag that perpendicular legs give here. The sign is the opposite: in Gaunaa, Li & Pirrung (2026) Table 2 and the appendix the on-blade induced drag of LL-Gaunaa is 1-5% below the Trefftz plane on the swept wings (e_Osw,Blade above e_Osw,Trefftz), and their VLM reference is 3% below as well. The report now states this, quotes the paper's own wording that the leg direction is a modelling choice not fixed by theory, and notes that the paper runs the legs up to the trailing edge while the perpendicular legs tested here have a fixed length. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ged with a vortex-lattice referee BodyAerodynamics(..., leg_direction="rib" | "streamwise" | "perpendicular"), also on instantiate(). "rib" (default, unchanged behaviour) keeps the legs along the interpolated input sections. "perpendicular" is the TORQUE 2026 recipe: legs along the CP1 chord direction, perpendicular to the quarter-chord line, up to the trailing-edge curve; the line tangent is averaged over one leg length so the legs fan out instead of crossing at a planform kink (no free parameter), the leg ends at the closest point of the trailing-edge curve (extended at its ends for skewed tips), and the control point moves between the panel's own legs (without that, kinked wings diverge). "streamwise" projects the apparent velocity onto the surface and rebuilds the legs whenever va is set. utils.perpendicular_leg_end_points, Panel.set_leg_end_points. Legs that still cross raise ValueError. Referee: docs/validation/vlm_referee.py runs the AeroSandbox VLM (flat-plate sections) on straight, yawed, kinked-swept, arc, swept-anhedral elliptic wings and the inviscid V3, with the Trefftz drag of the VLM circulation (its near-field drag is low on non-planar wings). Rib and streamwise legs reproduce the VLM lift within 1% on all planar and curved wings (streamwise 2% low on the arc); the perpendicular legs lose 9% on the kinked wing and 8% on the V3, where they also cross at the tips above 80 panels. On the V3 against RANS the streamwise legs give the closest polars (drag within 0.3% up to 10 deg). The rib legs stay the default; the earlier fixed-length perpendicular test (118e91d) is superseded. Docs: report Section 4.3 rewritten with the three constructions, the referee tables and figures 10 (geometry: legs, aerodynamic centres, control points, VLM lattice) and 11 (referee); status item 2 and open items updated; docs/Solver.md and figures README. Tests: tests/BodyAerodynamics/ test_leg_direction.py (11 tests: equality with ribs where ribs are perpendicular or streamwise, skewed ribs give the straight wing, kinked wing builds and converges, crossing raises, legs follow the inflow). Full suite 181 passed, 5 skipped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
BodyAerodynamics(leg_direction="streamwise") becomes the default (was "rib"). The legs run along the apparent velocity projected onto the surface, up to the trailing-edge curve, and are rebuilt whenever va is set; they depend only on the quarter-chord line, the trailing edge and the flow, not on how the input sections were drawn, follow the inflow in sideslip, and give the closest V3 polars to RANS (drag within 0.3% up to 10 deg, lift slope equal to the RANS one). Known cost, from the AeroSandbox referee: 1-3% less lift than a lifting surface on the nearly vertical tips of an arc wing at 4-15 deg (rib legs: -0.2 to +1.6%), with the induced drag closer; up to 7% less lift at high angle of attack on the thesis curved-wing case. The change is physical: the vortex system differs where the ribs are not aligned with the flow (kite tips, sideslip); identical results on wings whose ribs are drawn along the flow. An inflow without a mean direction (pure rotation about the centroid) has no streamwise legs: the rib legs are used for that inflow and a warning is logged (Panel.reset_legs_to_ribs). After a geometry rebuild (rotate, update_from_points) the legs follow the stored inflow distribution. Tests that verify the thesis vortex system (tests/utils.py, the create_geometry_general oracle, the curved-wing and V3 verification cases) and the regularisation tests (chordwise legs isolate the bound-vortex term) now pass leg_direction="rib" explicitly; make_pr_figures.py and the regularisation validation script likewise, so figures 01-09 and the report's Sections 2-4 stay reproducible. New test: fallback for pure rotation. Report (decision paragraph, status, open items), Solver.md and the figures README state the new default and its cost. Suite: 182 passed, 5 skipped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Reverts the default of def20bb. The code's main use is trim finding with an inflow that varies along the span (body rates, distributed va), where the streamwise construction can only use the mean inflow direction and is rebuilt at every inflow; the rib legs give a fixed vortex system of the same accuracy (better on arc-shaped tips against the VLM). The streamwise and perpendicular constructions, the referee, the tests and the figures are unchanged; the report, Solver.md and the figures README state the reasoning and the mean-direction limitation. Suite: 182 passed, 5 skipped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d validation docs/Aerodynamic_model.pdf held chapter 4 of the 2022 MSc thesis, with no source in the repository and sections left empty. It is replaced by an 18-page document whose source is docs/aerodynamic_model/aerodynamic_model.tex (latexmk; the compiled file is copied to docs/Aerodynamic_model.pdf). Contents: scope and assumptions; geometry and the CP1 panel frame; the vortex system (filaments, Biot-Savart, cores, influence matrices, wake, the three attached-trailed leg constructions); the inner-outer coupling (TAT1-3, Gamma = 1/2 |V_inner| c Cl, quarter-chord directions, the curved bound-vortex regularisation, the attached-trailed force, the spanwise viscous correction, artificial viscosity, the LLT variant); solver, inflow, outputs, Trefftz drag and bridle lines; validation (horseshoe and elliptic analytical cases, Trefftz consistency, the AeroSandbox VLM referee on planar, swept, arc, elliptic and V3 wings, the V3 against RANS and the wind tunnel, mesh convergence, the regression cases); limits; a table of conventions. Every figure names the script that generates it. New figures 12 (classical wings against Prandtl and the VLM; the LLT loses its Trefftz consistency on a curved quarter-chord line, the VSM does not) and 13 (mesh convergence), from docs/validation/aerodynamic_model_figures.py. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ror) 1105122 (Copilot Autofix, "Refactor ratio and gate condition") replaced five lines with one: it kept the new ratio expression but deleted the crossed_gate assignment and the opening `if not finite(trial) or (` with its condition, leaving a bare `):` at Solver.py:1447. Every `import VSM` on main raised SyntaxError: unmatched ')', so every fresh install of a package that depends on VSM@main (AWETrim) failed. Restores the condition and keeps the autofix's intended change: a trial with exactly zero residual now has ratio = inf (accepted) instead of 0 (rejected). (cherry picked from commit beb0a4f)
…metry The quarter-chord correction (assemble_curved_bound_correction_AIC) depends on the panel geometry only: the wake terms cancel between the actual and the unrolled systems and the inflow speed does not change the result (bit identical on the V3 at 10, 20 and 40 m/s). It costs about 0.5 s at 50 panels and was rebuilt on every solve, which multiplied in a coupled aerostructural trim that solves one deformed geometry hundreds of times (231 s against 60 s for one LEI-V3 wireframe case with the old force directions). It is now cached on a hash of the arrays the kernel reads (evaluation and bound points, leg ends, chord directions, chords) plus the chord fractions, so a rebuild, a rotation, a moved point or a changed leg construction invalidates it; a solve on an unchanged geometry takes about 0.1 s at 54 panels. Results are unchanged. Test: one kernel evaluation for two inflows on the same panels, identical results to a fresh body, and a recomputation after a rotation. Suite: 183 passed, 5 skipped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tion A trim that rotates the body for every residual evaluation (AWETrim's quasi-steady trim) rebuilds the panels each time, so the per-geometry cache of 2644b5c never hit: profiling one LEI-V3 coupled case showed the kernel on all 280 solves, 135 s of 222 s. The cache now stores the evaluation, bound and leg-end points, the chord directions and chords of the computed geometry; when the current panels are that geometry up to a rigid rotation and translation (Kabsch fit, residual below 1e-9 of the size), the stored matrix is rotated instead of rebuilt, since its entries are velocity vectors that rotate with the body. A different shape recomputes. Test: one kernel evaluation for a rotated body, the same lift and drag as a body built in the rotated position, and a recomputation after a trailing-edge point is moved. Suite: 183 passed, 5 skipped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nd the model document docs/validation/unrolling_figure.py draws, for the arc wing, the kinked swept wing and the V3, the straight reference wing that the curved bound-vortex regularisation builds on each evaluation panel's own tangent (one per panel, nodes at their arc-length distances, legs along that panel's chord direction), and the distance between actual and unrolled nodes against the distance from the panel: the near field coincides and cancels in the difference, the far field is the curvature effect. Figure 14 in docs/figures, placed after eq. 6 of the regularisation report and in Section 5.3 of the aerodynamic model document; both PDFs rebuilt. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
docs/validation/chord_spread_figure.py draws the 24 thin-airfoil strips on real and unrolled panels of the arc wing, the chordwise velocity one neighbouring segment induces at the quarter-chord point as a filament and as a sheet (equal beyond a chord, finite within it only for the sheet, levelling at the 0.15 c cut-off), and the running sum of the neighbours from far to near at 40 to 320 panels (filaments keep rising, sheets settle). Figure 15 in docs/figures, placed after the spreading paragraph of the regularisation report and in Section 5.3 of the aerodynamic model document; both PDFs rebuilt. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e printing New Section 4.2 'Reading of the formulation': the quarter-chord construction is the same handover rule as TAT1 at the three-quarter chord (3D minus what the 2D section already contains, with the unrolled wing as the section's straight continuation); the chordwise sheet is the vorticity the inner model is made of, with a table showing that the three-quarter chord sums converge and need no sheet while the quarter-chord sums do not; the two sheet terms are the same panel in two positions. 'Other approaches' gains the per-panel segment-minus-infinite-line subtraction, tested and divergent like one over the panel width squared. Table 4's perpendicular-leg rows now use the current construction (the earlier rows were the superseded fixed-length legs). Open items gain the body-rate direction velocity (effective torsional rate, Li, Gaunaa and Pirrung 2026 preprint). Abstract mentions the leg referee; title block and date updated; 17 pages. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…othesised LL-Gaunaa term Report Section 4.2: derivation of the velocity two line vortices meeting at a kink induce on each other (Gamma (1 - cos theta) / (4 pi r sin theta), unbounded at the kink), its sum over a curved line (the logarithm of the span over the panel width) and the same sum for chord-spread sheets (the logarithm of the span over 0.15 c, mesh-independent), with figure 16 from docs/validation/kink_figure.py. Report Section 3.1: the form that reproduces the published behaviour of LL-Gaunaa, curved-minus-straight bound segments as single filaments at the three-quarter-chord control point reused at the quarter chord, is now implemented in the validation script (--hypothesis) and tabulated: it is mesh-independent and within 1-2 % of the Trefftz plane with the paper's perpendicular legs, and fails with rib legs on the V3 (0.81 -> 0.74) and the kinked wing, because skewed legs carry their own logarithm that a bound-only difference cannot see. Open item and status updated accordingly. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…p loading Replace the flat-plate thin-airfoil strip weights by the NeuralFoil loading (gamma = ue_upper - ue_lower) of the V3 centre section at 5, 10 and 15 deg and of a NACA 4412. The effective cut-off moves from 0.16 c to 0.13 c and the centroid aft of the quarter chord; the arc wing changes by at most 0.3 % and the V3 induced drag by 0.5-1.5 %, within the referee's own uncertainty. The flat-plate weights are kept (solution-independent, cached per shape). Script docs/validation/strip_weight_sensitivity.py, report Section 4.2 (Table tab:strips). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…hysics Narrative: Prandtl's straight wing as the exact baseline and why; curvature makes two line vortices at an angle induce an unbounded velocity on each other, hence the logarithm and the mesh drift; Li and Gaunaa avoid the quarter-chord point and assume the velocity constant along the chord and the legs perpendicular; a section is a chordwise sheet and two sheets at an angle see a finite velocity; the correction is the real wing as sheets minus the wing straightened at the section as sheets, added to Prandtl, so that curvature is isolated and the section's own field never enters; results against the Trefftz plane, a vortex lattice and RANS. Alternatives tested, strip-loading sensitivity, the leg study in detail and the implementation status move to appendices. 16 pages (was 19). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Curved bound vortex at the quarter chord: chord-regularised correction, leg direction option, validation
Problem
Since the September consistency commits the sectional force direction is taken from the velocity at the quarter chord (
is_aoa_corrected=True). On a straight wing that velocity is Prandtl's downwash and the on-blade induced drag equals the Trefftz plane exactly. On a curved wing the neighbouring bound vortex is no longer on the line: two line vortices meeting at a small angle induce an unbounded velocity on each other, so the quarter-chord velocity grows by a constant at every mesh doubling and the induced drag drifts. On the V3 the on-blade over Trefftz ratio went 0.93 → 0.85 between 20 and 160 sections. Leaving the bound segments out is worse: the trailed legs carry a second logarithm wherever they are not perpendicular to the line.Solution
Seen from closer than a chord a section is a sheet, not a line, and two sheets at an angle induce a finite velocity on each other.
assemble_curved_bound_correction_AIC(utils.py) builds, for each panel, the wing straightened onto that panel's tangent and evaluatesThe bound vorticity and the leg starts in the bracket are spread with the flat-plate thin-airfoil distribution (24 strips, strip legs collinear with the actual legs). The bracket is identically zero on a straight wing, so Prandtl is recovered exactly; it is finite on curved wings with a cut-off of 0.15 c fixed by the distribution, no parameter; and it differences legs as well as bound segments, so any leg direction converges. The section's own field never enters. Only the quarter-chord velocity is touched; the circulation solve at the control points is unchanged. The correction is one influence matrix per shape (Numba, ~1 s at 80 panels), cached and reused under rigid motion of the body, rebuilt on deformation.
Leg direction
BodyAerodynamics(leg_direction="rib" | "streamwise" | "perpendicular"), also oninstantiate. Rib stays the default. Judged against an AeroSandbox vortex lattice for lift and the Trefftz plane for drag: rib and streamwise legs reproduce the lattice lift within 1 %; the paper's perpendicular legs lose 8–9 % of the lift on kinked and kite-like wings and are kept only as an option.Results (on-blade / Trefftz induced drag, inviscid polars, rib legs)
V3 induced drag rises by about 10 % at 50 panels (CD +0.005 at 10°) and lands on the RANS values up to 10°. Lift is unchanged.
Documentation
docs/validation/curved_bound_vortex_report.pdf(16 pages): Prandtl baseline, the curvature logarithm, what Li and Gaunaa do, the sheet correction, results; appendices with the alternatives tested (Li 2020 literal, curved-minus-straight at the control point, Reid–Hunsaker, vortex core, sheets as baseline), strip-loading sensitivity, the leg study and the implementation status. All tables reproduced bycurved_bound_vortex_validation.py,leg_direction_study.py,vlm_referee.py,strip_weight_sensitivity.py.docs/Aerodynamic_model.pdfrebuilt from a new LaTeX source (docs/aerodynamic_model/): formulation, conventions, validation cases.docs/Solver.md,docs/figures/README.md(figures 08–16).Tests
tests/BodyAerodynamics/test_curved_bound_vortex.py(zero on straight wings, mesh convergence on the arc, cache reuse under rotation, rebuild under deformation) andtests/BodyAerodynamics/test_leg_direction.py. Full suite: 183 passed, 5 skipped.Also in this branch
fix(solver): restores the reject condition broken by 1105122 (SyntaxError on develop), same commit asfix/solver-syntax-error.Open items (not in this PR)