Skip to content

feat(mechanical): single canonical mechanical spin ODE + bearing friction#9

Merged
mcroomp merged 2 commits into
mainfrom
feat/canonical-mechanical-ode-integrator
Jul 19, 2026
Merged

feat(mechanical): single canonical mechanical spin ODE + bearing friction#9
mcroomp merged 2 commits into
mainfrom
feat/canonical-mechanical-ode-integrator

Conversation

@mcroomp

@mcroomp mcroomp commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary

Consolidates the rotor's mechanical (rigid-body spin) ODE into one canonical implementation, dynbem_rs::mechanical, exposed to Python as dynbem.mechanical.omega_derivative / dynbem.mechanical.step_omega, and audits the whole codebase for remaining hand-rolled duplicates.

  • Adds Coulomb (dry) bearing friction as a first-class parameter (bearing_friction_Nm, default 0.0).
  • step_omega is semi-implicit in the aerodynamic torque term: it freezes a local damping time constant tau = I*omega/Q_aero over the step, so pure aero drag can never overshoot omega past zero. Motor torque and friction are treated explicitly with a zero-crossing clamp so friction alone can't reverse rotation direction.
  • Bug fix: at omega ~= 0, step_omega previously dropped Q_aero entirely, so a windmill/driving torque acting on a stopped rotor would never spin it up. Both the omega~=0 branch and the invalid-tau fallback now share one full_explicit_step helper.
  • New windmill-mode and realistic corner-case unit tests: spin-up from rest under windmill torque, autorotation-entry branch crossing, equilibrium shift under friction, no chattering near Q_aero sign flips, settle-and-stay-at-rest.
  • Consistency audit: replaced every remaining hand-rolled/duplicate explicit-Euler omega step with the canonical integrator:
    • dynbem_rs/src/quasi_static_bem.rs (spindown time-integration test)
    • vpm_viz/src/main.rs (standalone VPM visualization binary)
    • envelope/point_mass.py (2 call sites)
    • tests/test_oye.py (1 call site)
    • Refreshed a stale doc comment in dynbem_rs/src/aero_io.rs that pointed at the old ad hoc formula.
  • Bumped dynbem to 0.7.0 (Cargo workspace version.workspace, dynbem/pyproject.toml).

Scope note

This branch was created directly off origin/main (post-merge of #8) so it contains only the mechanical-ODE work above — no windmill/helicopter BEM branch changes are included since those are already merged.

Testing

  • cargo fmt
  • cargo test --release --workspace — 76 passed, 0 failed
  • cargo check --workspace (post version bump) — clean, Cargo.lock unchanged

mcroomp added 2 commits July 19, 2026 10:31
…tion

- Add dynbem_rs::mechanical (omega_derivative + step_omega) as the one
  canonical place the rigid-body rotor spin ODE is evaluated/stepped,
  with Coulomb bearing friction as a first-class parameter.
- step_omega is semi-implicit in the aerodynamic torque term (freezes a
  local damping time constant tau = I*omega/Q_aero), so pure aero drag
  can never overshoot omega past zero; motor torque and friction are
  treated explicitly with a zero-crossing clamp so friction alone can't
  reverse rotation direction.
- Fix a real bug: at omega ~= 0, step_omega previously dropped Q_aero
  entirely, so a windmill/driving torque on a stopped rotor would never
  spin it up. Both the omega~=0 branch and the invalid-tau fallback now
  share one full_explicit_step helper.
- Add windmill-mode and realistic corner-case unit tests (spin-up from
  rest, autorotation-entry branch crossing, equilibrium under friction,
  no chattering near Q_aero sign flips, settle-and-stay-at-rest).
- Consistency pass: replace every remaining hand-rolled/duplicate
  explicit-Euler omega step with the canonical integrator --
  quasi_static_bem.rs test, vpm_viz/src/main.rs, envelope/point_mass.py
  (2 call sites), tests/test_oye.py -- and refresh stale doc comments in
  aero_io.rs pointing at the old ad hoc formula.
- Bump dynbem to 0.7.0 (Cargo workspace + dynbem/pyproject.toml).
…le map

- README.md / docs/API.md: replace old omega_derivative + plain-Euler
  examples (and stale "semi_implicit_step_omega" name) with the canonical
  step_omega(omega, spin_angle, ...) call.
- dynbem_rs/README.md: add mechanical.rs to the module map, fix
  omega_rad_s / Q_spin field docs to point at crate::mechanical::step_omega
  instead of the old raw formula, bump the Cargo.toml usage snippet to
  dynbem_rs = "0.7".
@mcroomp
mcroomp merged commit 2b98718 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