Skip to content

feat(aero): phase-correct blade flapping + flapback H-force (v0.8.0)#10

Merged
mcroomp merged 3 commits into
mainfrom
feat/h-force-in-plane-hub-force
Jul 19, 2026
Merged

feat(aero): phase-correct blade flapping + flapback H-force (v0.8.0)#10
mcroomp merged 3 commits into
mainfrom
feat/h-force-in-plane-hub-force

Conversation

@mcroomp

@mcroomp mcroomp commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the rotor in-plane hub force (H-force) to the BEM-family aero models and reworks blade flapping into a phase-correct, aero-damped 1/rev harmonic solve that feeds both the transmitted hub moment and a new flapping-tilt H-force. Bumps the published package 0.7.0 -> 0.8.0.

Changes

Aero core (dynbem_rs)

  • In-plane hub force (H-force): profile/induced-drag H-force assembled in the psi-loop sweep, validated for direction (rearward drag in forward flight; downwind under crosswind; vanishes as the disk aligns with the wind).
  • Phase-correct blade flapping: replaces the scalar hub_moment_factor with apply_flap_dynamics — a gamma-based, aerodynamically-damped 1/rev harmonic flap solve shared by all three models (quasi-static BEM, Pitt-Peters, Oye). Produces a phase-correct flapback that drives:
    • the transmitted hub moment (via centrifugal + spring stiffness), and
    • a flapping-tilt H-force (thrust vector tilting into the disk plane).
  • Removed the now-unused hub_moment_factor path from the Rust core, the PyO3 wrapper, and the Python FlapProperties class (no backward-compat shim).

Validation (validation_rs)

  • h_force: added the flapback case (11 asserts total, all pass) — freely-hinged blade transmits ~0 moment but still produces a rearward flapback H-force.
  • New harris_hforce_empirical: QS BEM Rotor CH vs Harris NASA CR-2008-215370 PCA-2 tabulated appendix (pages 504-505). Method: trim collective to match the tabulated Rotor CT, then compare the resulting Rotor CH with a freely-hinged flap. CT trims exactly; CH agrees best mid-mu (0.5-18%) and degrades at the extremes (~40-80%), the expected simple-BEM bias at high advance ratio. Per-case ceilings self-calibrate via REWRITE_EMPIRICAL_CSV=1.

Research data

  • Extracted the Harris PCA-2 coefficient appendix (CT/CH/CY vs advance ratio, 4 RPM series) straight from the report text layer (HIGH confidence) into Research/Harris_CR-2008-215370/pages_504_505_appendix_pca2_coeffs.md + CSV mirror.

Docs

  • Synced AGENTS.md, docs/BEM_COMMON.md, docs/EMPIRICAL_VALIDATION.md, dynbem_rs/README.md, and the field-mapping docs to the phase-correct solve (no old-behavior references).

Version

  • Workspace crates (dynbem, dynbem_rs) and the published dynbem package: 0.7.0 -> 0.8.0 (new features + removed API).

Validation

  • dynbem_rs: unit tests pass
  • validation_rs: full suite 162/162 pass (was 150; +12 Harris CH cases)
  • Python suite: 200 passed / 5 xfailed / 1 xpassed (from prior run of this branch's core changes)

Breaking changes

  • FlapProperties.hub_moment_factor (Rust, PyO3, and Python) is removed. Flapping is now configured purely via I_blade_flap_kgm2 + omega_nr_rad_s.

mcroomp added 3 commits July 19, 2026 14:52
AeroResult.F_world was always purely axial (hub_axis * -T) across all
aero models, so a level rotor disk in a pure crosswind produced zero
net force -- the model had no way to represent the profile/induced-drag
H-force that pushes a rotor disk downwind, or (equivalently) the drag
that opposes an aircraft's forward flight through still air.

- bem_common.rs: SweepCtx::run now also accumulates Fx_hub/Fy_hub by
  reusing the already-computed per-element dQ (dFt = dQ/r), projected
  onto the fixed hub axes with the same sin(psi)/cos(psi) weighting
  already used for Mx_hub/My_hub. assemble_result now builds a full
  in-plane + axial hub force vector instead of assuming pure axial
  thrust.
- Wired through quasi_static_bem.rs, pitt_peters.rs, oye.rs.
- vpm/mod.rs passes 0.0, 0.0 with a TODO -- VPM's free-wake march
  doesn't yet accumulate this; left as follow-up.
- Documented scope: this covers only the profile/induced-drag
  contribution to H-force. The classical flapping-tilt contribution
  (often the dominant term for articulated/hingeless rotors) is not
  modeled, since FlapProperties::hub_moment_factor is a static scalar
  that only reduces Mx_hub/My_hub and never feeds Fx_hub/Fy_hub.

New validation: validation_rs/src/checks/h_force.rs (registered in
checks/mod.rs), checking:
- level disk + crosswind + zero collective -> zero vertical force,
  force along the wind direction, no cross-axis leakage
- reversing wind reverses the force
- zero wind -> zero in-plane force
- disk tilting into the wind shrinks the H-force monotonically to ~0
- forward flight through still air produces a rearward force,
  matching the textbook H-force definition (drag opposing flight
  direction), not just "wind pushes a stationary disk downwind"

Verified: cargo test -p dynbem_rs (76/76 pass, no regressions) and
cargo run --release -p validation_rs (147/147 pass).
Replace the scalar hub_moment_factor with a gamma-based, aero-damped
1/rev harmonic flap solve (apply_flap_dynamics) shared by all three
BEM-family models (quasi-static, Pitt-Peters, Oye). This produces a
phase-correct flapback that feeds BOTH the transmitted hub moment and a
new flapping-tilt in-plane hub force (H-force), replacing the previous
magnitude-only moment scaling.

- Remove the now-unused hub_moment_factor path from the Rust core, the
  PyO3 wrapper, and the Python FlapProperties class (no back-compat).
- Add the flapback case to validation_rs h_force (11 asserts, all pass).
- Add harris_hforce_empirical: QS BEM Rotor CH vs Harris CR-2008-215370
  PCA-2 tabulated appendix (pages 504-505, extracted to Research/), using
  a trim-to-CT then compare-CH method with a freely-hinged flap. CT trims
  exactly; CH agrees best mid-mu (0.5-18%), degrades at the extremes as
  expected for a simple BEM at high advance ratio.
- Sync AGENTS.md, BEM_COMMON.md, EMPIRICAL_VALIDATION.md, READMEs, and
  field-mapping docs to the phase-correct solve (no old-behavior text).

Bump workspace crates and the published dynbem package 0.7.0 -> 0.8.0
(new features + removed hub_moment_factor API).
@mcroomp
mcroomp merged commit b85e08b into main Jul 19, 2026
4 checks passed
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