Skip to content

release: CableDyn 0.4.1 - #106

Open
SMI-Lab-Inha wants to merge 19 commits into
mainfrom
release/0.4.1
Open

SMI-Lab-Inha wants to merge 19 commits into
mainfrom
release/0.4.1

Conversation

@SMI-Lab-Inha

Copy link
Copy Markdown
Owner

Summary

Release CableDyn 0.4.1: dev with #87 to #104, the version bump to 0.4.1 (2026-11-08), and the experiment records rerun with the 0.4.1 build. The CHANGELOG section lists every change and, under Upgrading, the outputs that change.

  • Version: CMake, the Fortran banner, the OpenFAST module, the C API and header (patch 1, ABI 1.4), the Python package and CITATION.cff. check_release_metadata.py passes.
  • Docs: the coupling-boundary page now lists the ABI 1.4 calls.
  • Experiment records: Holcombe and Bergdahl rerun with the release build, byte-identical in every summary. Only Holcombe's two hashed static profiles change, in their curvature and bend-moment columns, by at most 1.1e-4 relative.

Checks on this tree

  • Builds: fresh GNU Release and Debug builds, 0 warnings.
  • CTest: 365 of 365 in Release on the default kernel and on Prescott, Nehalem, Sandybridge, Haswell and Zen, and in Debug.
  • Example scan: 54 decks with no fallback note on each of the five kernels. SkylakeX runs on a Linux runner (ci: one-off SkylakeX run on the 0.4.1 tree (not for merge) #105).
  • Python: pytest 2872 passed, 47 skipped. The sdist and wheel build and pass twine check.
  • Repository checks: pre-commit, the release-tree audit and the bodies suite (102 of 102) pass.
  • Timing: 53 example decks against v0.4.0, at a geometric-mean ratio of 0.967; the total falls from 155.8 to 123.1 s.

The release record validation/RELEASE_0_4_1.md follows with the asset, clean-machine and linearisation results. It also corrects one row of the 0.4.0 record: its six-kernel claim was five, because the Windows OpenBLAS ran Haswell for SkylakeX, and its example scan could not see the relaxed-tolerance note.

CableDyn_UpdatePointFluidFields and CableDyn_CalcOutputDerivatives
refused a deck on the coupled aggregate by naming bodies and rods only,
so a deck with a finite-EI line and neither read as a wrong diagnosis.
Both messages now name finite-EI lines, bodies and rods.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
…d note (#90)

The LINES flag r now works in single-turbine coupled OpenFAST runs: the
shell samples committed steps from RangeStart and writes
<RootName>.CD.Line<L>.range.out at the end of a run that reaches TMax.
The accumulators survive a restart, so OtherState gains the range state
and checkpoints from earlier builds cannot be restarted. A FAST.Farm
shared mooring and the C API refuse the flag by name.

An initialisation note and doc/openfast.rst state how coarse the deepest
interval of SeaState's depth grid is when it exceeds 5 % of the depth and
a line reaches into it.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
A deck with TMax 0 and no dtM stopped with a message about a dynamic run.
A static check needs no time step, so it now runs on every standalone
route: the parser builds the deck on a nominal step marked as a
static-check clock, which no caller can march on, and a motion record is
read for its t = 0 row only. The C API keeps needing dtM on finite-EI,
body and rod decks, because CableDyn_Step marches on it, and says so.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
The component wave sum took 70-80 % of a step on a long elevation record.
GNU Fortran did not vectorise the sine, cosine and exponential at all. The
sum stays exact: block kernels take the quadrant and exponent from the bits
of the rounded value, sums run in 64 interleaved lanes added in a fixed
order, components past the first 1024 are no longer evaluated twice, and the
depth ratios take one division. Spectral seas, wave trains and spread seas
share the gain. Results change at round-off.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
On a deck with finite-EI lines, bodies or rods the C API and Python ran in
still water only: a deck current was refused, and no call reached the line
nodes.

- A steady deck current (current, WaterKin CurrentMod 1, MoorDyn-C
  Currents 1) is marched in-process, in the static start and in every
  step, also from host start positions.
- A host can supply the ambient fluid at every node instead (ABI 1.4):
  CableDyn_SetHostFluid before the initialization, then
  CableDyn_NFluidNodes, CableDyn_GetFluidNodePositions and
  CableDyn_UpdateFluidFields; in Python set_host_fluid, n_fluid_nodes,
  fluid_node_positions and update_fluid_fields. A steady deck current
  then sets the static start only, as a host's current does in OpenFAST.
- The field follows the standalone march and OpenFAST: sampled at t + dt
  at the step-start nodes and held over the step. The first field, at
  t = 0, sets the start acceleration, on EI = 0 lines too, and a step
  without a field is refused.

Stepped in current and regular waves, a cable matches the standalone
driver to the digits of its output (NRMSE 2e-7), with a stiffener and
as-laid seabed friction too; SaveState and RestoreState carry the field.

With a host field the deck is read by the coupled rules, so SEASTATE and
WaveKinMod 2 policies reach the aggregate and no TMax is needed.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
Under a tapered bend stiffener the stiffness is one value per element, so
every node sits on a small step the section does not have. The node
outputs took the softer side, which overstated curvature by about
h |EI'| / (2 EI); the element outputs carried a bias of the same size, of
either sign depending on the deck.

A stiffened line now keeps EI(s) at every node, one limit per side, and the
larger-side rule compares those limits, so a real step stays a step. The
.elements.out peaks and OutputRecovery element on sleeved elements report
the section moment over EI(s), with the same soft-section fallback as the
node path. Lines without a stiffener are bit-identical.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
A Linux job runs the full CTest on the Prescott OpenBLAS kernel, confirms
the kernel took effect, and runs every shipped example deck, failing on a
fallback note where a deck should converge cleanly. A test that passes on
one kernel and fails on another is a bug. tests/check_example_fallbacks.py
holds the scan and example_fallback_scan tests it.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
read_output could not read the two-table <root>.modes.out file. It now
returns NaturalModes, the frequency table, with .shapes holding a
ModeShapes table, and DriverResult gains modes_output and read_modes().

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
CableDyn now has init_line, init_lines and calc_output_derivatives, which
bind CableDyn_InitLine, CableDyn_InitLines and
CableDyn_CalcOutputDerivatives. Arguments follow the C API; shape, finiteness
and dtype are checked in Python before the call and the library judges value
ranges.

python/tests/test_raw_lines.py compares a raw line with the same line from a
deck and the Jacobians with central differences.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
… EI = 0 azimuth range (#97)

CD_C_LINE_SECTION_CURVATURE and Line.section_curvature() return CurvX and
CurvY at every node of a finite-EI line in one evaluation.

CableDyn_GetLineValues reads position, velocity, acceleration, tension,
curvature, bend moment, declination and azimuth in one pass, without a text
token per node. The per-node rules moved into helpers shared with the channel
evaluator, and line_values_match_channels compares the two bit for bit. An
EI = 0 tension read was O(n^2) and is now linear.

A line whose deck chord heads within 45 degrees of +X reported its azimuth in
[0, 360) instead of (-180, 180] outside the standalone EI = 0 route, because
commit_model_copy dropped azimuth_signed. Those values read 360 degrees lower.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
…and full notes (#98)

A solver step retry works at any dtM/DT. The glue copies the step-start
OtherState back over the predicted one, which the shell read as a rewound
checkpoint: at dtM = DT it rebuilt the model on every retry, and at dtM > DT
it stopped. A retry now restores the aggregate's step-start snapshot and the
load predictor is mirrored back into OtherState. The committed-force cache
survives a restore.

CalcSteady keeps its state map through a rebuild and runs to the end of the
run with more than one operating point. Range graphs are written when the
host reports a completed run, in OpenFAST and FAST.Farm, and not after an
error; a turbine's own instance writes
<RootName>.T<n>.CD.Line<L>.range.out. Initialisation notes of a coupled line
reach the console in full, and a restart no longer rewrites .CD.static.out.

Parameter gains Linearize and Misc gains HostComplete, so checkpoints from
earlier builds cannot be restarted.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
…d line (#99)

The node outputs of a finite-EI line read the conjugate of the tangent as
the moment. The element energy is EI k^2/2 per unstretched length, so that
conjugate has normal length EI k/(1+e)^2, which put Curv 2e and BendMom e
below their definitions.

Curv, CurvX and CurvY are now the geometric curvature of the stretched line,
the reciprocal of the bend radius. BendMom is the moment that balances the
forces, EI k/(1+e), and StfMom the sleeve's share of it, so
BendMom (1+e) = EI x Curv. Tension, positions and forces do not change.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
…ecords (#96)

wave_frequencies.txt (WaveKin 7) takes a different beta on each row, as
MoorDyn-C reads it, so a component file can describe a short-crested sea.
Short-crested tables use their own branch of the component sum, so the
single-direction path is unchanged.

The new options WaveRefX and WaveRefY (m, default 0) say where a wave record
or the component phases are referenced, for WaveKin 3, WaveKin 7 and WaterKin
WaveKinMod 1. They extend the MoorDyn-C format. Vessel RAOs take each row's
heading and the vessel position relative to the point.

DeckFile now reads the files a deck names and refuses what the solver
refuses, on spelling aliases and static checks too. RAO headings are judged
by the bins that carry energy. A direction bin below the smallest normal
weight is exactly zero natively, so which bins carry the sea depends on the
spreading and the bin count alone.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
…ts (#100)

CableDyn_GetInitNotes and CableDyn.init_notes return the notes of the last
deck initialisation on the point route and the aggregate, for a host that does
not read the standard streams. The Python binding is optional, so a library
without the call still loads and only init_notes refuses.

An initialisation note names the lines that a current can move along a seabed
without friction, and a route that rejects frictionMu says so.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
A coupled run restarts from a checkpoint at any glue step: ChkptTime need not
be a multiple of dtM, and the restarted run matches the uninterrupted one bit
for bit. Nothing in the solver moves between commits, so a new OtherState
field, commit_input, holds what the last commit was reached with, and a
rebuild stands on it at the commit's clock. A restart on the last glue step
evaluates the committed loads first. Only a time outside the mooring step is
still refused. CalcSteady and -VTKLin work at dtM larger than DT.

A restart before the first commit keeps a body or rod at its start. An earlier
run's range graphs go as soon as the deck is parsed, so an initialisation that
stops after that leaves none. The module driver keeps its orientation in double
precision, so a rotating motion runs in a single-precision build.

Checkpoints from earlier builds cannot be restarted.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
Records everything merged since 0.4.0 in the Unreleased section, with an
Upgrading part for the outputs that change.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
)

A non-zero omega = 0 row of wave_frequencies.txt (WaveKin 7), or the mean of
wave_elevation.txt (WaveKin 3), is now added to the elevation alone, as
MoorDyn-C does: the wave numbers stay those of WtrDpth, and the Wheeler
stretching maps the water under the total elevation. CableDyn took the wave
numbers at WtrDpth plus the level and measured z from it. The mean of a
WaterKin WaveKinMod 1 record still raises the still-water level; the docs now
say that MoorDyn-F drops it.

CD_Component_Wave_Kinematics takes an optional eta_offset, a steady level in
the surface the stretching maps.

A new wavekin_modes case runs both files with a 0.8 m level against MoorDyn-C
v2.7.2, with six WaveKin 7 components in six directions. WaveKin 7 matches to
1e-8 of its scale, where the previous rule was 7.7e-3 m off in elevation and
1e-2 in velocity. WaveKin 3 matches to the existing grid tolerances, where it
was 6e-3 off in velocity.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
Set the version to 0.4.1 (2026-11-08) in the build, the Fortran banner, the
OpenFAST module, the C API and its header, the Python package and CITATION.cff,
and date the CHANGELOG section. The coupling-boundary page now lists the calls
of ABI minor extension 4.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
Holcombe and Bergdahl rerun with the 0.4.1 GNU Release build. Both reproduce
their summaries, metrics and refinement figures byte for byte. Of the files
provenance.json hashes, only the two Holcombe static profiles change: their
curvature and bend-moment columns, by at most 1.1e-4 relative, from the
geometric curvature of a stretched line. The Bergdahl waveform comparison
still stands from the 0.3.0 run.

Signed-off-by: Jae Hoon Seo <jaehoon.seo@inha.ac.kr>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-08T02:22:23.253706Z f8f1e1a Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@SMI-Lab-Inha

Copy link
Copy Markdown
Owner Author

@codex review

@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 CableDyn | 🛠️ Build #35727225 | 📁 Comparing f8f1e1a against latest (3d04008)

  🔍 Preview build  

22 files changed · ± 22 modified

± Modified

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: f8f1e1ac24

ℹ️ 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".

This branch is waiting to be deployed

1 waiting deployment
testpypi — f8f1e1ac Waiting Nov 8, 2026 by SMI-Lab-Inha via publish-testpypi #112
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