API contract
pybmodes is on a stable 1.x baseline. The public surface
enumerated below is semver-frozen across 1.x minor releases.
Renaming or removing any name on this list requires a major-
version bump (2.x). Adding new keyword arguments with defaults,
new dataclass fields, and brand-new entry points is non-
breaking.
Versioning policy
We follow Semantic Versioning 2.0 for
the API surface. The version string is in
[project] version of pyproject.toml and is mirrored at
pybmodes.__version__.
Bump |
Example |
Triggers |
|---|---|---|
Major (X.y.z) |
1.7.0 → 2.0.0 |
Renaming or removing any name on this page; changing a function’s required parameter; tightening a return- type so callers must adapt; dropping a Python version. |
Minor (x.Y.z) |
1.6.0 → 1.7.0 |
New entry points; new keyword arguments with sane defaults; new dataclass fields with sane defaults; new optional dependency extra; new CLI subcommand. |
Patch (x.y.Z) |
1.7.0 → 1.7.1 |
Bug fixes; numerical-accuracy improvements that change output values (always called out in the changelog); documentation; internal refactors. |
Numerical outputs may shift between minor and patch
releases when validation tightens or a modelling correction
lands. Every such shift is called out in Changelog
under Fixed / Changed with magnitude and affected case.
For reproducible numerics across runs, pin to an exact
version (pybmodes==1.7.0) and only upgrade after reading
the changelog.
Deprecation policy
When a public name is being renamed or removed for a future major version, we follow a two-minor-release deprecation window:
First minor release introduces the new name; keeps the old name working but emits a
DeprecationWarningwith a pointer to the replacement.Second minor release keeps the old name working but prints the warning at module-import time, in addition to call-time.
Next major release removes the old name entirely.
Deprecation warnings name the minimum version a fix is available in, so:
warnings.warn(
"RotatingBlade.legacy_method is deprecated since 1.x; "
"use RotatingBlade.method instead (available from 1.7.0). "
"The legacy name will be removed in 2.0.",
DeprecationWarning,
stacklevel=2,
)
There are currently no deprecations in flight on the 1.x line.
Stable public names
The authoritative list is the docstring of
pybmodes.__init__; the table below is a categorised
summary.
Model constructors
Name |
From |
|---|---|
|
|
|
|
Results + serialisation
pybmodes.models.ModalResult— return value of.run(); carries frequencies + per-node mode shapes + optional participation + optional fit residuals; shipssave(.npz)/load(.npz)andto_json(.json)/from_json(.json)with embedded pyBmodes version + UTC timestamp + source-file + git-hash metadata.
As of Phase 3 PR C1 of the 1.x refactor, pybmodes.campbell is
a sub-package rather than a single 1301-line module. The public API
(CampbellResult, campbell_sweep(),
plot_campbell()) is unchanged and re-exported from
pybmodes.campbell; internal helpers live in private
sub-modules (_models / _classify / _mac / _sweep /
_plot) so each file covers one concern.
pybmodes.campbell.CampbellResult— output ofcampbell_sweep; shipssave(.npz)/load(.npz),to_csv(.csv); carries frequencies + omega_rpm + labels + participation +mac_to_previousper-step tracking confidence + integer mode counts.
Solvers + sweeps
pybmodes.campbell.campbell_sweep()— rotor-speed sweep with MAC-tracked blade modes + constant-frequency tower modes.pybmodes.campbell.plot_campbell()— engineering-report- style diagram (four family keys: Blades, Tower, Platform, Blade Passing) with operating-window shading + inline labels.
Polynomial fitting + validation
pybmodes.elastodyn.compute_blade_params()pybmodes.elastodyn.compute_tower_params()pybmodes.elastodyn.compute_tower_params_report()— same plus aTowerSelectionReportexposing FA / SS family scoring + rejected-mode lists.pybmodes.elastodyn.patch_dat()pybmodes.elastodyn.validate_dat_coefficients()
Floating coupled-vs-cantilever diagnostic
pybmodes.elastodyn.report_floating_frequency_gap()runs a cantilever and a coupled solve on the same floating deck and returns the gap between the polynomial-basis 1st FA / SS and the coupled-system 1st FA / SS that an OpenFAST linearisation will report. Useful for reconciling pyBmodes-generated polynomial coefficients against linearisation output without re-deriving the cantilever-vs-coupled architecture.pybmodes.elastodyn.FloatingFrequencyGapcarries the four frequencies plusgap_fa_1_pct/gap_ss_1_pctproperties and aformat_report()rendering.
Soil-pile interaction
pybmodes.MudlineFoundationcarries the three coupled mudline springsK_hh/K_hr/K_rrand the pile-behaviour / soil-profile / formula discriminators. Classmethodfrom_soil_properties(pile_diameter, pile_length_embedded, pile_EI, soil_E, soil_nu=0.3, soil_profile="homogeneous", pile_behaviour="auto", formula="shadlou")applies Randolph (1981) classification and dispatches to Shadlou and Bhattacharya (2016) per Yu and Amdahl (2023) Table 1 or to Psaroudakis et al. (2021) per Yu Eq 25.as_mooring_K()returns a 6 x 6 block in OpenFAST DOF order that drops straight intoPlatformSupport.mooring_Kof ahub_conn = 3BMI.
Pre-solve sanity + comparison
Numerical options (1.x architecture refactor — Phase 1)
Frozen dataclasses that centralise numerical thresholds previously scattered as module-level constants. Adding fields with sensible defaults is non-breaking; removing or renaming a field is a semver-major change.
pybmodes.SolverOptions— FEM solver dispatch (sparse_ndof_threshold,symmetry_rtol).pybmodes.FitOptions— polynomial-fit + family-selection thresholds (polynomial_rms_threshold,torsion_contamination_threshold,fit_cond_warn,fit_cond_fail).pybmodes.CheckOptions—check_model()thresholds (stiffness_jump_factor,ei_ratio_min/_max,support_asymmetry_rtol,fit_cond_warn/_fail).
Reports
pybmodes.report.generate_report()— Markdown / HTML / CSV bundled analysis report (eight sections: summary, assumptions, frequencies, classification, polynomial coefficients with fit residuals, validation, check_model warnings, Campbell sweep).
Workflows (Phase 2 of the 1.x architecture refactor)
The pybmodes.workflows sub-package exposes each CLI
subcommand as a typed library function returning a
WorkflowResult subclass. Lets notebooks and external
scripts run the same flows the CLI uses without going through
subprocess. The CLI in pybmodes.cli is now a thin
argparse + delegate + format result + map exit code layer.
pybmodes.workflows.WorkflowResult— base dataclass withexit_code/messages/errors.pybmodes.workflows.run_validate()/pybmodes.workflows.ValidateResult— coefficient- consistency check on one ElastoDyn deck.pybmodes.workflows.run_examples_copy()/pybmodes.workflows.ExamplesResult— vendorsample_inputsand / orreference_decksout of the installed wheel.pybmodes.workflows.run_patch()/pybmodes.workflows.PatchResult— regenerate the tower + blade polynomial coefficient blocks of an ElastoDyn deck. Five mutually-supportive output modes (default in-place,backup,output_dir,dry_run,diff);diffattaches a coefficient-only diff with per-block RMS-improvement ratios tomessages.pybmodes.workflows.run_report()/pybmodes.workflows.ReportResult— modal solve + optional coefficient validation + optional Campbell sweep on one deck, rendered to Markdown / HTML / CSV.pybmodes.workflows.run_batch()/pybmodes.workflows.BatchResult— walk a directory of ElastoDyn decks, validate + optionally patch each, write a summary CSV plus per-deck validation reports. As of 1.8.0 the patch path carries the same safety contract asrun_patch():dry_runfor no-write previews,output_dirfor redirected writes, andbackup(now defaulting toTrue) for.bak-sibling preservation under in-place rewrites — a stronger default than the single-deck path sincebatchmutates a tree of files surfaced by discovery rather than a single hand-typed filename.pybmodes.workflows.run_campbell()/pybmodes.workflows.CampbellWorkflowResult— rotor-speed sweep + Campbell-diagram PNG + per-mode-tracked CSV.pybmodes.workflows.run_windio()/pybmodes.workflows.WindioResult— one-click WindIO ontology entry point: discovers the ontology + companion OpenFAST decks scoped to the turbine root (pybmodes.workflows.discover_windio_inputs()returning apybmodes.workflows.WindioDiscovery), solves blade + tower (or coupled floating tower + platform), optionally runs a Campbell sweep, and writes a bundled report. As of 1.8.0 the workflow carries anon_skippolicy parameter (default"fail-on-data") so a computational skip — e.g. the blade composite reduction raised — togglesexit_code = 1instead of silently returning a partial report; presentation-only skips (Campbell plot, environmental-spectra plot) still warn. Passon_skip="warn"to recover the pre-1.8.0 permissive behaviour.
With this PR the full pybmodes CLI surface is library-
callable; pybmodes.cli is purely argparse + delegation.
Mooring + hydro
As of Phase 3 PR C2 of the 1.x refactor, pybmodes.mooring is a
sub-package rather than a single 1202-line module. The four public
names (LineType, Point, Line,
MooringSystem) are unchanged and re-exported from
pybmodes.mooring; the implementation lives in types (data
classes + Line.solve_static()) and system
(MooringSystem with multi-line force assembly + 6×6 stiffness
and the two from_* parsers), plus the private _catenary /
_rotation math primitives and the _moordyn_parser MoorDyn
.dat row tokenisers.
pybmodes.mooring.MooringSystem—from_moordyn,from_windio_mooring,stiffness_matrix(body_r6=None).
I/O
pybmodes.io.out_parser.read_out()(with thestrict=Trueoption)pybmodes.io.errors.ParseError— unified base class for everypybmodes.io.*parser exception; inheritsValueErrorso existingexcept ValueErrorcallers are backward-compatible. SubclassesBMIParseError,ElastoDynParseError,SubDynParseError,WAMITParseError,MoorDynParseError,WindIOParseError, and the existingBModeOutParseError(now re-rooted under the new base). Structuredfile/line/column/contextfields +format_diagnostic()for uniform error messages across formats.
Plot helpers ([plots] extra)
pybmodes.plots.apply_style()— engineering-paper defaults (black / red / blue / green).plot_mac(re-exported frompybmodes.mac)plot_campbell(re-exported frompybmodes.campbell)
CLI subcommands
The pybmodes console script declared in
[project.scripts]. Subcommand names and their flag
semantics are part of the semver contract.
Subcommand |
Purpose |
|---|---|
|
Coefficient-consistency report on one ElastoDyn deck. |
|
Regenerate polynomial blocks; |
|
Rotor-speed sweep → Campbell diagram PNG + CSV. |
|
Walk a directory of decks; per-deck validate + patch + summary CSV. |
|
Bundled Markdown / HTML / CSV analysis report. |
|
One-click WISDEM/WindIO → composite blade + tubular tower + coupled platform + Campbell. |
|
Vendor |
Stability tiers
Not every module is at the same stability level. The public names above (and only those) are the stable surface.
Public + stable
Listed above. Semver-frozen.
Public but experimental
Currently none. When a name is introduced experimentally (e.g. a new constructor for a niche WindIO dialect), it’s flagged in its docstring with:
.. note::
Experimental — may change without notice until the next
X.Y.0 release at the earliest.
Internal (underscore-prefixed)
Modules under src/pybmodes/ whose name starts with an
underscore (_pipeline.py, _serialize.py,
_elastodyn/, _precomp/) and module-level attributes
starting with an underscore. These can change in any release
including patch versions.
Don’t import from them; if you find yourself wanting to, open an issue — that’s a signal we have a real-use-case gap in the public surface, and we’d rather fix that than have you depend on something we’ll break.
Runtime dependency contract
The default install pulls in ``numpy`` and ``scipy``
only. Every other dependency is gated behind an extra
(Installation). Adding a runtime dependency to the
core requires alignment — the numpy + scipy-only stance is
itself part of the contract.
Tier |
Examples |
Semver impact |
|---|---|---|
Core |
|
Tightening the version pin is a minor bump; adding a new core dep is a major bump. |
Extras |
|
Adding a new extra is a minor bump; renaming or removing an extra is a major bump. |
How to track changes
Changelog — every release, called-out numerical shifts.
Validation matrix — the per-case validation matrix, mechanically audited by
scripts/audit_validation_claims.pyin CI.CHANGELOG.mdat the repo root — the source of truth (the docs page above is included from it).GitHub Releases — release-notes copies of the
[X.Y.Z]changelog block, with merge-PR backlinks.Read the Docs version selector — version-pinned docs for every published tag.