Skip to content

BeamDyn linearization with RotStates=True returns frozen-frame Jacobians flagged RotatingFrame=T — spurious spin-softening in MBC3/Campbell results #3394

Description

@mayankchetan

Bug description

When BeamDyn is linearized with rotating states (RotStates = True, the default), the state
Jacobians it returns are expressed in a frozen, root-aligned inertial snapshot of the blade
frame, but the .lin file flags those rows/columns RotatingFrame = T. MBC3-based
postprocessors (openfast_toolbox / pyFAST Campbell workflows, ACDC) trust that flag and apply
their rotating-frame Ω-corrections, which injects spurious spin-softening: coupled mode
frequencies droop with rotor speed following f² = f₀² − αΩ² even for modes that should be
speed-independent.

Observable symptom: in a Campbell diagram of the NREL 5-MW with BeamDyn blades, the tower
side-side branch droops from 0.3221 Hz at standstill to 0.2915 Hz at 25 rpm (α ≈ 0.108,
fit residual 9e-4; 2.29 % droop already at 12 rpm). The ElastoDyn-blade reference is flat, and
a RotStates = False control shows only mild physical stiffening — no droop. The same defect
reproduces on the official IEA-15/3.4/10/22 reference models at v5.0.0 tags
(α = 0.143 / 0.267 / 0.124 / 0.234 respectively; raw droop up to ~8 % on IEA-22).

Mechanism: two frame effects are missing from the returned Jacobians —

  1. the states are anchored to OtherState%GlbRot (frozen at initialization) rather than the
    rotating root frame the RotatingFrame = T flag promises, and
  2. the transport (Coriolis-type) term of the frame change is absent.

The rotation-only part of this transform existed once (PR #2063) but was removed in
5fbd380f8; note the fix below is not a revert — the deleted code was ≈identity at the
operating point and lacked the transport term, so it never fixed the droop either.

The consistent similarity transform, applied per paired (q, dq/dt) state triplet
(pairing offset Nx/2), is

A_r = S·A·S⁻¹ + blkdiag(−ω̃)     with  S = [[I, 0], [−ω̃, I]],
B_r = S·B,   C_r = C·S⁻¹

where ω is the full 3-vector root RotationVel mapped into the GlbRot basis (scalar Ω is
not sufficient — e.g. precone puts a z-component of −0.0548 rad/s at 12 rpm on the 5-MW). The
transform is exactly identity at standstill.

To Reproduce

  1. Compile dev (double precision) at or near 0160d29a0.
  2. Run a NREL 5-MW CompElast = 2 linearization sweep, 0–25 rpm (CalcSteady, 1 azimuth
    snapshot suffices), with OutFmt "ES18.9E3" so the .lin write precision does not add a
    second artifact (see the companion OutFmt issue).
  3. Post-process with any MBC3/Campbell tool and track the tower side-side branch.
  4. The branch follows f² = f₀² − αΩ² instead of staying flat; repeating with ElastoDyn
    blades or RotStates = False removes the droop.

Expected behavior

Jacobians flagged RotatingFrame = T are frame-consistent with that flag, so
speed-independent branches stay flat: with the fix below, 5-MW tower-SS flatness across
0–25 rpm improves from 2.29 % (at 12 rpm) to 0.015 %, and the IEA fleet flattens to
0.111 % / 0.029 % / 0.026 % / 0.379 % (IEA-15/3.4/10/22) — the IEA-22 residual is also present
in the independent python-side reference transform (0.361 %) and is a known second-order
effect (large-prebend blade / Wiener-Milenković first-order limit), not part of this defect.

Fix

Implemented and fleet-verified on branch
mayankchetan/openfast:f/bd-rotstates-framefix
— PR to follow. The transform is applied only at linearization snapshots (a new optional
IsLin flag threaded from the glue), so the tight-coupling solver and AeroMap keep the raw
frozen-frame Jacobians their Newton iterations require. Standstill .lin output is
bit-identical to unpatched.

Known limitation (documented, not addressed): floating platforms — platform/yaw rates fold
into the root ω, where MBC3's scalar-Ω assumption independently breaks down anyway.

OpenFAST Version

dev @ 0160d29a0 (also reproduced on v5.0.0 tags of the IEA reference models); double
precision, gfortran, RelWithDebInfo, macOS (arm64).

Additional context

Discovered while chasing anomalous tower frequencies in BD-blade Campbell diagrams. A second,
independent defect was isolated during the same investigation — .lin files are written with
the tabular OutFmt (~4 significant digits), which corrupts wide-dynamic-range BD Jacobians
on disk — filed separately with fix PR #3393. The 5-MW evidence above is immune to that
artifact by construction (diagonal sectional matrices) and was additionally re-baselined with
wide-format decks.

Developed with Anthropic Claude (Claude Code) under human direction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions