Skip to content

Write linearization (.lin) output at full precision, independent of OutFmt#3393

Open
mayankchetan wants to merge 3 commits into
OpenFAST:devfrom
mayankchetan:f/lin-full-precision
Open

Write linearization (.lin) output at full precision, independent of OutFmt#3393
mayankchetan wants to merge 3 commits into
OpenFAST:devfrom
mayankchetan:f/lin-full-precision

Conversation

@mayankchetan

@mayankchetan mayankchetan commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Feature or improvement description

Write linearization (.lin) output at full precision, independent of the OutFmt set in the OpenFAST input file.

The glue code currently formats everything in the .lin files — the Jacobian matrices
(A/B/C/D, dUdu/dUdy, module blocks), the operating-point column, and the header scalars
(including Rotor Speed, which MBC3 postprocessors consume) — with the OpenFAST input's tabular
OutFmt, whose documented default "ES10.3E2" carries only ~4 significant digits.

For models whose state matrices span a wide dynamic range (e.g. BeamDyn blades with fully
populated sectional mass/stiffness matrices, where the assembled A spans ~15 orders of
magnitude), 4 digits is not enough to round-trip the matrix through disk: every downstream
eigenanalysis (openfast_toolbox / pyFAST, MBC3 / Campbell workflows, ACDC) then reports
physically impossible results for a parked, passive structure — spurious positive
eigenvalues, negative damping ratios, and merged or missing modes. The corruption is
invisible in the .lin file itself and easily misread as a physics or solver defect.

This PR introduces a fixed full-double-precision format for all numeric .lin output:

character(*), parameter :: LinFmt = 'ES24.15E3'

Tabular time-series output continues to honor the user's OutFmt, unchanged. Workaround on
released versions: set OutFmt "ES18.9E3" in any OpenFAST input file used for linearization.

Related issue, if one exists

Fixes #3395. Discovered alongside the independent BeamDyn rotating-frame defect #3394 (fix: #3396); the two PRs are independent.

Impacted areas of the software

  • modules/openfast-library/src/FAST_ModGlue.f90 only: all matrix writes, the
    operating-point column formats, and the header-scalar format now use LinFmt; the
    operating-point tab stop is sized from the new width. No change to what is computed —
    only to how it is written.
  • .lin files grow ~2.4× per numeric field. They are analysis artifacts, not time series,
    so the size cost is negligible against the correctness gain.
  • Parsers are unaffected (ES24.15E3 is standard Fortran scientific notation; verified
    with openfast_toolbox ReadFASTLinear).
  • r-test: any checked-in .lin baselines will differ textually (wider fields, more
    digits); values agree with the old files to the old files' precision, so baselines need
    a regeneration pass, not tolerance changes.

Generative AI usage

Developed with Anthropic Claude (Claude Code) under human direction using OAK's workflows.

Co-authored-by: Anthropic Claude claude@anthropic.com

Test results, if applicable

  • Clean build (macOS arm64, gfortran, RelWithDebInfo, double precision).
  • A/B verification on an IEA-15-240-RWT BeamDyn linearization case whose OpenFAST input
    uses the default OutFmt: before the patch, eigenanalysis of the written A matrix
    yields a spurious positive real eigenvalue and a merged tower pair; after the patch,
    the same input yields 0 unstable eigenvalues and the correctly split tower pair,
    matching a control run whose input sets a wide OutFmt explicitly.
  • need to update r-test linearization results.

mayankchetan and others added 3 commits April 1, 2025 09:39
…less of OutFmt

The .lin Jacobian matrices (A/B/C/D, dUdu/dUdy/dXdy/J and the module-level
blocks), the operating-point column, and the header values (incl. Rotor Speed,
consumed by MBC3 tools) were formatted with the deck's tabular OutFmt, whose
default "ES10.3E2" carries ~4 significant digits. Assembled Jacobians of
coupled-section BeamDyn blades span ~15 orders of magnitude, so the write
itself corrupted downstream eigenanalysis: physically impossible results
(spurious positive real eigenvalues, negative damping ratios, merged or
missing tower modes) for parked, passive structures on IEA-15/3.4/10/22
class models, while near-diagonal-section models (NREL 5-MW) escaped.

Fix: a fixed module-level format LinFmt='ES24.15E3' (full double precision)
for all numeric .lin output in FAST_ModGlue; tab-stop width updated to match.
Tabular time-series output keeps honoring OutFmt, unchanged.

Verification: IEA-15-240-RWT structure-only standstill case with default
OutFmt, patched dev build: A-matrix eigenvalues go from 1 spurious positive
real eigenvalue + merged tower mode (0.2163 Hz) to 0 unstable and a correctly
split tower pair (0.2369/0.2386 Hz vs ElastoDyn 0.2350/0.2366); identical to
the ES18.9E3-deck control on the unpatched binary. Rounding a clean A to 4
significant digits in numpy reproduces the corrupted eigenvalues exactly,
confirming the mechanism.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mayankchetan
mayankchetan requested review from Copilot and luwang00 July 17, 2026 20:25
@mayankchetan mayankchetan changed the title F/lin full precision Write linearization (.lin) output at full precision, independent of OutFmt Jul 17, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the fidelity of OpenFAST linearization (.lin) outputs by switching all numeric .lin formatting to a fixed, full double-precision scientific format, independent of the user’s tabular OutFmt, to avoid precision-loss that can corrupt downstream eigenanalysis results.

Changes:

  • Introduces a fixed .lin numeric format (LinFmt = ES24.15E3) and applies it to .lin header scalars, operating-point tables, and all written Jacobian/state matrices.
  • Updates the operating-point table tab-stop calculation to match the new fixed field width.
  • Modifies the Apache 2.0 LICENSE appendix boilerplate line.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
modules/openfast-library/src/FAST_ModGlue.f90 Writes all .lin numeric output using a fixed full-precision format to prevent loss of significant digits in linearization artifacts.
LICENSE Updates the appendix boilerplate copyright placeholder line.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread LICENSE
identification within third-party archives.

Copyright {yyyy} {name of copyright owner}
Copyright 2025 NREL
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.

2 participants