Skip to content

Per-panel pitch rates for flow curvature - #261

Closed
1-Bart-1 wants to merge 2 commits into
feat/flow-curvaturefrom
feat/flow-curvature-distributed
Closed

Per-panel pitch rates for flow curvature#261
1-Bart-1 wants to merge 2 commits into
feat/flow-curvaturefrom
feat/flow-curvature-distributed

Conversation

@1-Bart-1

Copy link
Copy Markdown
Member

Stacked on #260 — review that one first.

Why

#260 reads the flow-curvature rate as ω ⋅ y_airf. The projection is genuinely
per-panel (panels at different dihedral see different rates from one body rate),
but the source is a single rigid-body ω, so a deformation field cannot be
expressed at all. Twist and flapping — the modes where this moment is largest,
because a strip's torsional inertia is small while the moment scales with
could not reach the term.

What

What the moment actually responds to is the chordwise gradient of normal velocity
across the panel, not a body rate. So the input becomes that:

  • pitch_rate_dist on BodyAerodynamics, one rate per panel, positive nose-up.
  • set_va!(body_aero, va, omega) fills it by projecting onto each y_airf
    — behaviour identical to Optional flow-curvature pitch-rate moment #260.
  • set_va!(body_aero, va_distribution; pitch_rate_dist) takes it directly, so a
    structural model passes rates it computed itself.
  • section_pitch_rate(velocity_leading, velocity_trailing, z_airf, chord),
    exported, builds one entry from a section's edge velocities.

section_pitch_rate reduces exactly to ω ⋅ y_airf under rigid motion
(v_TE − v_LE = ω × c·x_airf, and y × x = −z), so one expression covers both
cases and the sign convention — where an error flips damping into divergence — is
pinned in one place instead of being rediscovered by each caller. There is a test
asserting that reduction.

Also fixes a trap

The distributed set_va! never set omega, so #260 would have read whatever the
rigid form last left there. Omitting the keyword now zeroes the rates rather than
silently reusing a stale value.

Tests

31 pass, including 16 for the distributed path: an antisymmetric twist rate that
no rigid ω can produce, per-panel cm_dist increments matching
flow_curvature_cm exactly, opposite signs on the two half-wings, and a length
mismatch throwing.

🤖 Generated with Claude Code

1-Bart-1 and others added 2 commits August 17, 2026 10:48
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.

Off by default. Enabled through the `flow_curvature` solver setting, applied in
both force paths (`calc_forces!` behind `solve!`, and `calculate_results`
behind `solve`). Independent of the pivot, so it needs the rate only and not a
rotation centre.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The moment increment responds to 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, so flapping and torsion modes could not reach the term.

BodyAerodynamics now carries pitch_rate_dist, one rate per panel. The rigid
set_va! fills it by projecting omega onto each y_airf, which already differs per
panel under dihedral. The distributed set_va! takes it as a keyword, so a
structural model can pass rates it computed itself.

section_pitch_rate builds one entry from a section's leading and trailing edge
velocities. It reduces to omega . y_airf for rigid motion, so one expression
covers both cases and 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 from whenever the
rigid form was last called.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@1-Bart-1
1-Bart-1 force-pushed the feat/flow-curvature branch from 030ee89 to aebfd96 Compare August 17, 2026 09:41
@1-Bart-1

Copy link
Copy Markdown
Member Author

Folded into #260 — single PR, rebased onto main.

@1-Bart-1 1-Bart-1 closed this Aug 17, 2026
@1-Bart-1
1-Bart-1 deleted the feat/flow-curvature-distributed branch August 17, 2026 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant