Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@ All notable changes to CableDyn are recorded in this file. The format follows

## [Unreleased]

### Added

- Bend stiffeners (`STIFFENERS` table): a tapered polyurethane sleeve over an end of a finite-EI
line, given as conical segments from the root outward (outer diameters, bore, modulus,
density). Each element it covers takes the compliance average of the cable-plus-sleeve
bending stiffness and the sleeve's mass, buoyancy and drag; standalone and coupled, with the
Python reader and builder. A hang-off clamped through a 5 m stiffener follows an independent
solution of the planar elastica within 0.2 % of the root moment, and its curvature follows
OrcaFlex 11.6d within 0.8 %. Initialisation notes name a stiffener spanning fewer than 10
elements and one at a pinned end. Example `lazy_wave_bend_stiffener.dat`.
- Output channels `StfMom<L>N<J>`, the share of the section moment a bend stiffener carries,
and `FairDefl<L>`/`AnchDefl<L>`, the deflection of the end force from the direction a held
END CONNECTIONS row declares (with the end tension, a stiffener's load case).

### Changed

- Under a bend stiffener, `BendMom<L>N<J>` (and the `BendMoment` columns of the static profile,
range graphs and element file) report the cable's own moment, the line type's EI times the
curvature; lines without stiffeners are unchanged.

## [0.3.0] - 2026-10-23

### Added
Expand Down
19 changes: 18 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,14 @@ file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/line_attachments)
add_test(NAME line_attachments COMMAND test_line_attachments WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/line_attachments)
set_tests_properties(line_attachments PROPERTIES LABELS "fortran;static;dynamic;validation")

# Bend stiffeners (STIFFENERS): element properties against closed forms and a fine integration,
# the deck grammar, and the stiffener's end on a stock-order LINES row.
add_executable(test_bend_stiffener tests/test_bend_stiffener.f90)
target_link_libraries(test_bend_stiffener PRIVATE cabledyn_core)
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bend_stiffener)
add_test(NAME bend_stiffener COMMAND test_bend_stiffener WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bend_stiffener)
set_tests_properties(bend_stiffener PROPERTIES LABELS "fortran;driver;static")

# OpenFAST CompMooring=5 aggregate: one deck carrying BOTH EI=0 mooring lines AND finite-EI
# Hermite cables composed behind the same FMF moving-point facade. Proves pure-mooring
# equivalence to CD_FMF (bit-for-bit), mixed-deck composition + column routing, pure-cable
Expand Down Expand Up @@ -2293,6 +2301,15 @@ if(Python3_Interpreter_FOUND)
set_tests_properties(driver_touchdown_recovery PROPERTIES
LABELS "python;driver;integration;static"
ENVIRONMENT "${_cabledyn_python_test_environment}")
# A hang-off through a tapered bend stiffener follows the planar elastica (scipy solve_bvp)
# within 2 % of the root moment and 1 cm; skipped where scipy is not installed.
add_test(NAME driver_bend_stiffener
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/check_bend_stiffener.py
$<TARGET_FILE:cabledyn>)
set_tests_properties(driver_bend_stiffener PROPERTIES
LABELS "python;driver;integration;static;validation"
SKIP_RETURN_CODE 77
ENVIRONMENT "${_cabledyn_python_test_environment}")
endif()
# A clamped finite-EI cable with a buoyant section on a Rigid6 body: the body static solve
# holds the objects at their deck poses, warns once, and reports no balanced clamped end loads.
Expand Down Expand Up @@ -2772,7 +2789,7 @@ endforeach()
# spectra, stream waves, anisotropic friction, modal analysis, clamped ends on bodies, MoorDyn-C
# kinematics files, bodies and rods, line failure): every shipped deck must run to completion.
foreach(_feature_example IN ITEMS
lazy_wave_vessel_motion lazy_wave_vessel_rao lazy_wave_buoyancy_modules lazy_wave_buoyancy_smeared
lazy_wave_vessel_motion lazy_wave_vessel_rao lazy_wave_bend_stiffener lazy_wave_buoyancy_modules lazy_wave_buoyancy_smeared
chain_range_tdp chain_torsethaugen_spread chain_two_train_sea stream_wave_shallow_chain
airy_wave_shallow_chain laid_cable_cross_current chain_modes lazy_wave_modes buoy_clamped_cable
moordynC_wavekin/chain_wavekin7_currents1 spar_pinned_rods mixed_body_rods_points
Expand Down
13 changes: 13 additions & 0 deletions VALIDATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ article's methods, are compared in
| **L3-6d** | Moving-touchdown dynamic contact | OrcaFlex 11.6d installed | curv 0.48/0.58%, tension 0.74/0.90/0.80%, TDP 0.08 m, migration 2–3 m/cycle | curv <3–5%, tension <2–3%, TDP excursion bounds <1.5 m | Pass |
| **L3-6e** | Out-of-plane / 3D whirl response | OrcaFlex 11.6d | 3D curv 0.52%, interior Y env ≤1.0 mm, sag ≤22 mm, tension 0.14/0.17/0.12% | curv <3%, env <5 cm, tension <2–3% | Pass |
| **L3-7** | 1-hour VolturnUS-S mooring dynamic | OrcaFlex 11.6d | `FairTen` mean 0.27%, std 0.26%, min/max 0.50/0.43%, Fourier 0.27/1.14% | ≤5% | Pass |
| **L3-8** | Bend stiffener at a clamped hang-off (5 m tapered polyurethane) | OrcaFlex 11.6d (stiffener attachment) / planar elastica | curvature 0.74% of root; cable moment 0.74%, section moment 0.18%, deflection angle 0.003° | <1.5% / <2%, 0.05° | Pass |
| **L3-H** | Holcombe static lazy-wave experiment | measured marker geometry | position RMSE 1.07–1.89% of suspended length; peak marker-curvature error 0.34–5.54% | end-restraint bracket | Pass |
| **L3-B** | Bergdahl chain experiment, 30 orbit conditions | measured upper-end force | RMSE 1.58 N; MAPE 3.13%; Pearson 0.993; Lin concordance 0.989 | full published matrix | Pass |
| **L-fig** | Along-arc curvature overlay (CableDyn / OrcaFlex / MoorDyn-F ±4×) | 3-code committed record | CableDyn peak 0.11% from OrcaFlex | <0.5% | Pass |
Expand Down Expand Up @@ -261,6 +262,18 @@ initialisation.
offset of L2-V in its mean and extremes. The force-blended `EI = 0` step moved the
minimum by +7 kN (0.15% before) and the other statistics by at most 0.01%; no step of this
drive needs the rotation- and snap-resolved sub-steps, so they leave it unchanged bit for bit.
- **L3-8 bend stiffener at a clamped hang-off** (`driver_bend_stiffener`): a 60 m power
cable (EI 20 kN·m²) clamped horizontal and pulled 30° off by its weight through a 5 m
polyurethane stiffener (0.5 m cylinder of 0.60 m, cone to 0.22 m, bore 0.20 m, E 50 MPa;
16 times the cable's EI at the root), on 0.05 m elements. The static curvature over the
stiffener and 3 m beyond follows OrcaFlex 11.6d with the stiffener given as a line attachment
within **0.74% of the root curvature** (root 0.4523 against 0.4522 1/m;
[`orcaflex_bend_stiffener.py`](https://github.com/SMI-Lab-Inha/CableDyn/blob/main/validation/scripts/orcaflex_bend_stiffener.py)).
Against an independent collocation solution of the planar extensible elastica with
`EI(s)` and the sleeve's weight, the cable's own moment follows within **0.74%** of its root
value, cable and sleeve moments add up to the section moment within **0.18%**, the node
positions within **0.6 mm**, and the end force's deflection from the clamp axis within
**0.003°** (32.37°).
- **L-fig curvature overlay**: `l3_lazywave_dynamic` writes each site's along-arc
curvature profile.
[`validation/scripts/curvature_profile_overlay.py`](https://github.com/SMI-Lab-Inha/CableDyn/blob/main/validation/scripts/curvature_profile_overlay.py)
Expand Down
6 changes: 6 additions & 0 deletions doc/capabilities.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ Line and constitutive capability
- Supported
- lumped at nodes of a finite-EI cable, standalone and coupled; rejected on the two-moving-end
compatibility solver
* - Bend stiffeners (``STIFFENERS``)
- Supported with limits
- tapered linear-elastic sleeve over a finite-EI line end, adding bending stiffness, mass,
buoyancy and drag per element, standalone and coupled; nonlinear (moment–curvature)
materials and bend restrictors are not provided; rejected on the two-moving-end
compatibility solver
* - Modal analysis (``nModes``)
- Standalone only
- natural frequencies and mode shapes of each line about its static equilibrium (all
Expand Down
4 changes: 2 additions & 2 deletions doc/concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ line type and its own mesh density:
1 buoy 50.0 16
1 bare 55.0 18 <- End B (anchor) side

A bare cable + a buoyancy stretch + a bend stiffener is **three sections of one line**, not
three lines. A single-material chain is **one section**. The unstretched length is the sum of
A bare cable + a buoyancy stretch + more bare cable is **three sections of one line**, not
three lines; a bend stiffener over its end is a ``STIFFENERS`` row on that line. A single-material chain is **one section**. The unstretched length is the sum of
the section lengths; the mesh is refined per section.

.. admonition:: Porting from MoorDyn
Expand Down
81 changes: 73 additions & 8 deletions doc/driver_format.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,17 @@ except that `SYROPE IC` must come **after** `LINES`, because its rows name lines
exist. A conventional layout is:

LINE TYPES → BODIES → EXTERNAL LOADS → ROD TYPES → RODS → POINTS → TURBINES → LINES → SYROPE IC →
SECTIONS → END CONNECTIONS / EQUIVALENT BUOYANCY / ATTACHMENTS / FAILURE / CONTROL → OPTIONS →
OUTPUTS
SECTIONS → END CONNECTIONS / EQUIVALENT BUOYANCY / ATTACHMENTS / STIFFENERS / FAILURE / CONTROL →
OPTIONS → OUTPUTS

Within LINE TYPES, the header row must precede the data rows because it selects their column
order.

A **line is one object spanning two end points** (End A = `NodeA`, End B = `NodeB`), built from
an ordered list of **sections**, each with its own line type and mesh density (the same
line-and-section arrangement OrcaFlex uses): a bare cable, a bend stiffener, and a buoyancy
stretch are sections of one line. A single-material line is one section. MoorDyn composites written
line-and-section arrangement OrcaFlex uses): a bare cable and a buoyancy stretch are sections of
one line, and a bend stiffener over its end is a [STIFFENERS](#stiffeners-optional-finite-ei-lines)
row. A single-material line is one section. MoorDyn composites written
as separate lines
joined at a `Connect` point are also valid.

Expand Down Expand Up @@ -208,6 +209,7 @@ are collapsed. It must match one of the spellings below; any other name fails wi
| END CONNECTIONS | `END CONNECTIONS`, `END CONNECTION` |
| EQUIVALENT BUOYANCY | `EQUIVALENT BUOYANCY`, `EQUIVALENT SECTIONS`, `BUOYANCY SECTIONS` |
| ATTACHMENTS | `ATTACHMENTS`, `LINE ATTACHMENTS`, `CLUMPS` |
| STIFFENERS | `STIFFENERS`, `STIFFENER`, `BEND STIFFENERS`, `BEND STIFFENER` |
| FAILURE | `FAILURE`, `FAILURES` |
| CONTROL | `CONTROL`, `CONTROLS` |
| TURBINES | `TURBINES`, `TURBINE` |
Expand Down Expand Up @@ -687,8 +689,9 @@ as written.
| `Length` | section unstretched length [m]; > 0 and at most 1e6, with `Length/NumSegs` at least 1e-6 |
| `NumSegs` | section element count, 1 to 1 000 000. A finite-EI line needs far fewer: its static solve is verified up to 20 480 elements on the 80 m reference cable (elements of about 8 mm) and does not converge at 40 960 (about 4 mm). Keep finite-EI elements longer than about `sqrt(EI/EA)`, and refine only where the curvature needs it |

A single-material line is one `SECTIONS` row; a bare cable with a buoyancy stretch and a bend
stiffener is three sections of one line.
A single-material line is one `SECTIONS` row; a bare cable with a buoyancy stretch is three sections
of one line (bare, buoyant, bare). A bend stiffener over a line end is a
[STIFFENERS](#stiffeners-optional-finite-ei-lines) row, not a section.

- A standalone deck with a finite-EI section needs `dtM`/`TMax`, unless it is a mixed
`EI = 0` + finite-EI deck, which may be static-only.
Expand Down Expand Up @@ -760,7 +763,8 @@ Behaviour:
with `vesselMotion` or `vesselRAO` it is stored in vessel axes (equal to global axes at the
reference pose) and turns with the vessel.
- The connection moment equals the bending moment of the line at its end node, so
`BendMom<L>N1` (End A) and `BendMom<L>N<NumSegs+1>` (End B) report it.
`BendMom<L>N1` (End A) and `BendMom<L>N<NumSegs+1>` (End B) report it; under a bend stiffener
it is `BendMom` plus `StfMom` at that node.
- On a `Body<N>` point the direction is given in the body frame, like the point offset, and
turns with the body. On a rod end it must be parallel to the rod axis (either sense, in the
frame of the rod's deck coordinates); another direction is rejected by name. The connection
Expand Down Expand Up @@ -931,6 +935,65 @@ Behaviour:
attachments at theirs; a checkpoint restart is bit-identical. They are rejected on the
two-moving-end compatibility route.

### STIFFENERS (optional, finite-EI lines)

A bend stiffener: a tapered polyurethane sleeve over a line end, usually at a hang-off, that
spreads the bending of the cable over its length. The sleeve is not a separate object; it adds
its bending stiffness, mass, buoyancy and drag to the elements it covers. Each row is one
conical segment, and the rows of one line end follow each other outward from the stiffener
root, each starting where the previous one ends. A cylindrical root, a cone and a tip are three
rows.

```text
--------------------- STIFFENERS ------------------------------------
LineID End Length RootOD TipOD InnerD E Density
(-) (-) (m) (m) (m) (m) (Pa) (kg/m^3)
1 A 0.4 0.45 0.45 0.17 5.0e7 1150
1 A 3.6 0.45 0.18 0.17 5.0e7 1150
```

| Column | Meaning |
|--------|---------|
| `LineID` | existing `LINES` id of a finite-EI line |
| `End` | the end the stiffener sleeves: `A` or `B` (also `EndA`, `EndB`) |
| `Length` | length of the segment along the line [m] |
| `RootOD` | outer diameter at the segment's root side [m] |
| `TipOD` | outer diameter at the segment's tip side [m]; the diameter varies linearly in between |
| `InnerD` | inner (bore) diameter [m], smaller than both outer diameters |
| `E` | Young's modulus of the sleeve material [Pa] |
| `Density` | density of the sleeve material [kg/m³] |

Behaviour:

- Over the stiffener the section bends as cable and sleeve together:
`EI(s) = EI_cable + E π/64 (OD(s)⁴ − InnerD⁴)`. The sleeve carries no axial load and no
torque, so `EA` and `GJ` are the cable's. Each element takes the compliance average of
`EI(s)` over its length, `L / ∫ ds/EI(s)`, the cable mass plus the mean sleeve mass, a
diameter of the displaced area of cable plus solid sleeve, `√(d² + OD² − InnerD²)`, for its
buoyancy, added mass and drag alike, as a line type has one diameter (the sleeve's outer
diameter when `InnerD` is the cable diameter; see [theory](theory.rst), *Bend stiffeners*). Elements the stiffener does not reach keep
their line type's values exactly.
- The element properties are piecewise constant, one value per deck element, so the deck mesh
must resolve the taper: an initialisation note names a stiffener that spans fewer than 10
elements and the element length that resolves it. Split the section at the stiffener tip and
mesh the part under it finely (about 0.1–0.2 m elements for a typical 3–8 m stiffener).
- The stiffener root takes the moment only where the end is held in rotation: declare the end
`Rigid`, or a rotational spring, in [END CONNECTIONS](#end-connections-optional-finite-ei-lines).
A stiffener at a pinned end prints a note.
- Outputs: `Curv<L>N<J>` is the curvature cable and sleeve share; `BendMom<L>N<J>` the cable's
own moment (the line type's `EI` × curvature, the value to check against the cable's limits);
`StfMom<L>N<J>` the sleeve's share, so that the two add up to the section moment the root
connection carries. `FairDefl<L>`/`AnchDefl<L>` give the angle between the end force and the
held direction, which with `FairTen`/`AnchTen` is the stiffener's load case. Keep the fine
mesh a couple of metres past the stiffener tip, where the cable's curvature can peak.
- The material is linear elastic. A row fails if the line is not finite-EI, a value is
non-finite, above 1e15 or out of range (`Length`, `RootOD`, `TipOD` and `E` must be positive,
`InnerD` and `Density` non-negative, `InnerD` below both outer diameters), or the stiffeners
of End A and End B together are longer than the line. On a stock-order line (anchor as
`NodeA`) the `End` column follows the written row, so the stiffener stays on the same physical
end. Stiffeners run wherever the cubic-Hermite cable does, standalone and coupled; they are
rejected on the two-moving-end compatibility route.

### FAILURE (optional, EI = 0 decks)

A FAILURE row detaches line ends from a point during a dynamic run, with MoorDyn's trigger rules.
Expand Down Expand Up @@ -1295,13 +1358,15 @@ bending moment. None of these channels is mandatory.
| `FairDecl<L>` | line L fairlead (End A) declination from +GZ (0 = up, 90 = horizontal, 180 = down) | deg |
| `AnchDecl<L>` | line L anchor (End B) declination from +GZ (0 = up, 90 = horizontal, 180 = down) | deg |
| `FairAngle<L>` / `AnchAngle<L>` | aliases of `FairDecl<L>` / `AnchDecl<L>` | deg |
| `FairDefl<L>` / `AnchDefl<L>` | line L deflection of the End-A / End-B end force from the direction a `Rigid` or rotational-spring END CONNECTIONS row holds there (0 when the line leaves along it); only at such an end | deg |
| `Point<P>p{x,y,z}` | point P position component | m |
| `Con<P>p{x,y,z}` | alias of `Point<P>p{x,y,z}` (MoorDyn v1 spelling) | m |
| `Body<N>…`, `Rod<N>…` | Rigid6 body and rod channels in the MoorDyn-F names: position, attitude, velocity and acceleration (`P`, `R`, `V`, `RV`, `A`, `RA`), net force and moment (`F`, `M`), rod end tensions (`TenA`, `TenB`), submerged fraction (`Sub`) and rod node positions (`Rod<N>N<k>P`). Available on every route that carries bodies or rods, OpenFAST included; the full list and units are in [Outputs](outputs.rst) | see Outputs |
| `Point<P>F{x,y,z}`, `Point<P>FH` | resultant of the line-end and cable end forces on point P (each the `FairTen`/`AnchTen` end force): the anchor load of a Fixed point shared by several lines, the line load a free point balances; `FH` is its horizontal magnitude. Available on every route (static, `EI = 0`, finite-EI, multibody and OpenFAST) except the two-moving-end finite-EI route, which rejects it by name | N |
| `Ten<L>N<J>` | line L effective tension at node J. EI = 0 lines: the mean of the two adjacent segment tensions. Finite-EI lines: the axial component of the section force recovered from nodal equilibrium (`OutputRecovery element`: the length-weighted mean of the adjacent element-mean axial forces). End nodes report the line-end force of `FairTen`/`AnchTen` | N |
| `Curv<L>N<J>` | line L curvature at node J. `EI = 0` lines: geometric curvature of the circle through the node and its two neighbours (end nodes take the adjacent interior value). Cubic-Hermite lines: `BendMom<L>N<J>` / EI, the larger of the two sides at a section junction (`OutputRecovery element`: exact curvature of the continuous centreline, the larger one-sided element value at an interior node) | 1/m |
| `BendMom<L>N<J>` | line L bend moment = EI × curvature **relative to the stress-free reference shape** (≈ 0 at the reference; the finite-EI reference is straight). Finite-EI lines: recovered from nodal equilibrium, the moment the neighbouring elements carry (`OutputRecovery element`: EI × the larger one-sided exact curvature); 0 on EI = 0 lines | N·m |
| `BendMom<L>N<J>` | line L bend moment = EI × curvature **relative to the stress-free reference shape** (≈ 0 at the reference; the finite-EI reference is straight). Finite-EI lines: recovered from nodal equilibrium, the moment the neighbouring elements carry (`OutputRecovery element`: EI × the larger one-sided exact curvature); 0 on EI = 0 lines. Under a bend stiffener: the cable's own share, the line type's EI × curvature | N·m |
| `StfMom<L>N<J>` | line L share of the section moment a bend stiffener carries at node J (the section moment less `BendMom<L>N<J>`; 0 outside the stiffener); only on a line with STIFFENERS | N·m |
| `L<L>N<J>p{x,y,z}` | line L node J position component | m |
| `L<L>N<J>v{x,y,z}` | line L node J velocity component (0 in static-only runs) | m/s |
| `L<L>N<J>a{x,y,z}` | line L node J acceleration component (0 in static-only runs) | m/s² |
Expand Down
Loading
Loading