Optional flow-curvature pitch-rate moment - #260
Merged
Conversation
A section rotating about its own spanwise axis sees an incidence that varies linearly along the chord. In thin airfoil theory that is the same boundary condition as parabolic camber, giving A1 = q*c/(2V) and A2 = 0, hence cm_c/4 = (pi/4)(A2 - A1) = -(pi/4) q_hat. The lift half of the same effect was already exact: A0 + A1/2 collapses to the effective incidence at three-quarter chord, which is where the inflow is sampled, so no correction belongs there. Only the moment was missing, and one control point per section cannot represent it because it is an A1 term rather than an A0 shift. What the moment responds to is the chordwise gradient of normal velocity across a panel. For rigid motion that gradient is omega . y_airf, but a deforming wing has a twist rate that varies along the span and no single body rate expresses it. BodyAerodynamics therefore carries pitch_rate_dist, one rate per panel: the rigid set_va! fills it by projection, the distributed set_va! takes it as a keyword, and section_pitch_rate builds an entry from a section's edge velocities. That helper reduces to omega . y_airf for rigid motion, so the sign convention is pinned in one place rather than rediscovered by every caller. Omitting the keyword zeroes the rates. The distributed set_va! never set omega, so reading it there would have fed the moment a stale rate. Off by default, applied in both force paths: calc_forces! behind solve! and calculate_results behind solve. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1-Bart-1
force-pushed
the
feat/flow-curvature
branch
from
August 17, 2026 09:41
030ee89 to
aebfd96
Compare
Arrow became a direct dependency but never reached either default manifest, so seeding a fresh checkout from them left the package unloadable. Regenerated both with bin/install --update, which also carries the routine version bumps that had accumulated since the last refresh. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Regenerating the default manifests needs one resolve per supported Julia version, but bin/install could only be pointed at a version through a stdin menu, and it moved the juliaup default to get there — so refreshing the 1.11 manifest left the shell on 1.11 afterwards. --version X.Y and +X.Y select the channel for one run and only juliaup add it, leaving the default alone. bin/update_default_manifests uses that to do both versions in one command, matching the script in SymbolicAWEModels.jl. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Documenter parses [flow_curvature_cm](@ref) as emphasis, so the link text reaches cross-reference resolution as flow*curvature*cm and the docs build fails. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
flow_curvature_cm rests on cm_c/4 = (pi/4)(A2 - A1), which nothing in the suite pinned: the existing tests check the code matches that formula, not that the formula is right, so a sign or factor error in it would pass everything and be wrong by exactly that amount everywhere. A rotating section is the A1 = q c / (2 v_rel), A2 = 0 case of the same relation. Applying it instead to NACA 4-digit mean lines, where measured section values exist, gives -0.053 for the 2412 against a measured -0.047 and -0.106 for the 4412 against -0.093, both inside the accuracy thin airfoil theory is expected to have, and exactly zero for the symmetric 0012. The zero-lift angle is asserted from the same coefficients so an error cannot hide in the moment alone. Relation and coefficient definitions: MIT OCW 16.01 Unified Engineering, Fluids Lecture 3 notes pp. 2-3. Co-Authored-By: Claude Opus 5 (1M context) <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.
Adds an opt-in
flow_curvaturesolver setting (defaultfalse) giving eachsection the thin-airfoil pitch-rate moment increment, driven by a per-panel rate
so deformation modes reach it.
What is missing today
A section rotating about its own spanwise axis at rate
qsees an incidence thatvaries linearly along the chord,
α_eff(x) = α + q(x − x_p)/V. Thin airfoil theorycannot tell that apart from parabolic camber, so the Fourier coefficients pick up
The lift half is already exact in VSM:
Cl = 2π(A₀ + A₁/2) = 2π[α + (q/V)(3c/4 − x_p)]is just the effective incidence at three-quarter chord — precisely where
set_va!samples the inflow (
control_points = LE·0.25 + TE·0.75). Nothing to fix there.The moment is not, because it lives in
A₁rather thanA₀:One control point per section can represent an incidence but not an incidence
gradient. A chordwise-refined VLM recovers this from the discretisation; a
lifting line has to add it analytically. It is independent of the pivot (
x_ponly enters
A₀), so only the rate is needed — the arm effect is already handledby the existing
(aero_center − reference_point) × Fsum.Per-panel rates
What the moment responds to is the chordwise gradient of normal velocity across a
panel. For rigid motion that gradient is
ω ⋅ y_airf, but a deforming wing has atwist rate that varies along the span and no single body rate expresses it — which
matters because this moment is largest exactly there (a strip's torsional inertia
is small while the moment scales with
c²).So the input is the gradient, not a body rate:
pitch_rate_distonBodyAerodynamics, one rate per panel, positive nose-up.set_va!(body_aero, va, omega)fills it by projecting onto eachy_airf, sopanels at different dihedral see different rates from one body rate.
set_va!(body_aero, va_distribution; pitch_rate_dist)takes it directly.section_pitch_rate(velocity_leading, velocity_trailing, z_airf, chord),exported, builds one entry from a section's edge velocities.
section_pitch_ratereduces exactly toω ⋅ y_airfunder rigid motion(
v_TE − v_LE = ω × c·x_airf, andy × x = −z), so one expression covers bothcases and the sign convention — where an error flips damping into divergence — is
pinned in one place instead of being rediscovered by each caller.
It also closes a trap: the distributed
set_va!never setomega, so reading itthere would have used a stale rate. Omitting the keyword now zeroes it.
Verification
q > 0is nose-up: a station 0.1c aft ofthe aero centre gains a positive
z_airfvelocity component, i.e. moreincidence, matching the derivation.
dM · ω < 0for both signs ofω— it damps rather than drives.πρVSc²/16per rad/s(predicted 19.24 N·m at the test condition, measured 19.245).
ω = 0, so default-off results are untouched.ωcan produce, per-panelcm_distincrements matchingflow_curvature_cm, opposite signs on the twohalf-wings, length mismatch throwing.
the code. A rotating section is the
A₁ = q c/(2 v_rel),A₂ = 0case ofcm_c/4 = (π/4)(A₂ − A₁); applying the same relation to NACA 4-digit meanlines gives
−0.053for the 2412 against a measured−0.047,−0.106for the4412 against
−0.093, and exactly zero for the symmetric 0012. The zero-liftangle is asserted from the same coefficients (
−2.08°against a measured−2.1°), so a sign or factor error cannot hide in the moment alone.Applied in both force paths —
calc_forces!behindsolve!andcalculate_resultsbehindsolve.Caveats
apparent-mass part (
−(π/2) q̂) is larger and belongs in the dynamics layer.Arrowhad become a directdependency without reaching either, so seeding a fresh checkout from them left
it unloadable. Unrelated to the physics change.
References
The relation this rests on, and the coefficient definitions used above:
Only the substitution of the rotation-induced camber slope into those definitions
is done here; the integrals are in the description above and the resulting
relation is exercised against measured section data in the test suite.
For the apparent-mass term named in the caveats, which this PR does not add:
Eq. (III) carries the
π(1/8 + a²)b²α̈andbaπḧterms, i.e. the added moment ofinertia about the rotation axis and the added-mass force acting at midchord —
the
−(π/2) q̂moment and the added-mass matrix discussed above both follow fromit. Note NTRS catalogues the scan under 1949, the year of the Annual Report
volume it was reprinted in; the report itself is 1935.
🤖 Generated with Claude Code