Skip to content

feat: WindIO material overrides (#133) and per-mode modal mass/stiffness (#134)#135

Merged
SMI-Lab-Inha merged 2 commits into
masterfrom
feat/windio-overrides-modal-mass
Jul 10, 2026
Merged

feat: WindIO material overrides (#133) and per-mode modal mass/stiffness (#134)#135
SMI-Lab-Inha merged 2 commits into
masterfrom
feat/windio-overrides-modal-mass

Conversation

@SMI-Lab-Inha

Copy link
Copy Markdown
Owner

Ships the two features that came out of the recent tower-comparison threads.

#133 — material / outfitting overrides on the WindIO paths

Tower.from_windio and Tower.from_windio_with_monopile accept optional E, rho, nu and outfitting_factor keywords. Each defaults to None (use the ontology value); pass a number to override it, so a sensitivity sweep runs straight off a WindIO file without editing the yaml. On the combined path the override applies to both the monopile and the tower segment. Existing callers are unaffected.

Tower.from_windio(yaml, E=1.9e11, outfitting_factor=1.0)   # sweep off the file

#134 — per-mode generalised mass and stiffness on the result

A solve attaches generalized_mass (kg) and generalized_stiffness (N/m) arrays to ModalResult, one entry per mode, normalised to unit tip lateral displacement, so a mode's modal mass and stiffness can be read off and compared against another tool's modal output. Re-dimensionalised from the FEM generalised form phi^T gm phi via ref_mr = RM*radius over the squared tip lateral-displacement DOF; stiffness = (2*pi*f)^2 * mass by construction. A rigid-body platform mode (tip barely moves) yields NaN.

res = Tower.from_windio(yaml, lumped_rna_cal=True).run(4)
res.generalized_mass[0], res.generalized_stiffness[0]   # kg, N/m

Notes

  • Both additive and non-breaking; the public positional ABI of ModalResult is preserved (new fields appended at the end, compare=False).
  • Tests: tests/test_material_override_and_modal_mass.py covers the override scalings (E, rho, outfitting, monopile+tower, None-is-ontology) and the modal mass/stiffness (populated, and sqrt(K/M)/2pi reproduces each frequency).
  • Full suite 1005 passed, ruff + mypy (3.11/3.12) clean.

…ess (#134)

#133: Tower.from_windio and from_windio_with_monopile gain optional E, rho,
nu and outfitting_factor keywords. Each defaults to None (use the ontology
value); a number overrides it so a material / outfitting sensitivity sweep
runs straight off a WindIO file without editing the yaml. On the combined
monopile+tower path the override applies to both segments. Existing callers
are unaffected.

#134: a solve attaches per-mode generalised_mass (kg) and
generalised_stiffness (N/m) to ModalResult, normalised to unit tip lateral
displacement, so a mode's modal mass and stiffness can be read off and
lined up against another tool's modal report. Re-dimensionalised from the
FEM generalised form phi^T gm phi via ref_mr = RM*radius over the squared
tip lateral displacement DOF; stiffness = omega^2 * mass. Rigid-body
platform modes (tip barely moves) yield NaN.
@SMI-Lab-Inha

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 929be1375e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/pybmodes/models/_pipeline.py Outdated
Comment on lines +68 to +70
if tip2 <= 0.0 or not np.isfinite(gm_form) or gm_form <= 0.0:
continue
m = ref_mr * gm_form / tip2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard near-zero tip motion before dividing

For modes whose tip has only numerical lateral motion, such as a floating heave/yaw or torsion-dominated mode, tip2 can be tiny but still positive, so this exact-zero check skips the intended undefined path and then divides by that tiny value. That can report enormous or infinite generalized_mass / generalized_stiffness instead of NaN; use a scale-aware tolerance for tip2 before normalizing.

Useful? React with 👍 / 👎.

The generalised-mass normalisation divided by the squared tip lateral
displacement with only an exact-zero guard. A torsion / heave / yaw
-dominated mode has a tiny but non-zero tip, which slipped through and
produced a huge or infinite modal mass instead of NaN. Gate on the tip
motion being a real fraction (>1e-8) of the mode's largest DOF amplitude,
so only genuine lateral modes are normalised and the rest report NaN.
@SMI-Lab-Inha

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 28185ceee6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@SMI-Lab-Inha SMI-Lab-Inha merged commit 74d6599 into master Jul 10, 2026
6 checks passed
@SMI-Lab-Inha SMI-Lab-Inha deleted the feat/windio-overrides-modal-mass branch July 10, 2026 10:47
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