| name | mooring-design |
| description | Design and analyze mooring systems including CALM and SALM buoys, catenary moorings, and spread mooring configurations. Covers mooring line design, safety factors, environmental loading, and compliance with DNV, API, and ABS standards. |
| updated | 2026-01-07 |
Mooring Design Skill
Design and analyze mooring systems for floating offshore structures, including CALM buoys, SALM buoys, and spread mooring configurations.
Version Metadata
version: 1.0.0
python_min_version: '3.10'
dependencies:
orcaflex-modeling: '>=2.0.0,<3.0.0'
hydrodynamics: '>=1.0.0,<2.0.0'
orcaflex_version: '>=11.0'
compatibility:
tested_python:
- '3.10'
- '3.11'
- '3.12'
- '3.13'
os:
- Windows
- Linux
- macOS
Changelog
[1.0.0] - 2026-01-07
Added:
- Initial version metadata and dependency management
- Semantic versioning support
- Compatibility information for Python 3.10-3.13
Changed:
- Enhanced skill documentation structure
When to Use
- CALM (Catenary Anchor Leg Mooring) buoy design
- SALM (Single Anchor Leg Mooring) buoy analysis
- Spread mooring configuration design
- Mooring line sizing and material selection
- Environmental load calculations
- Safety factor verification
- Mooring analysis setup for OrcaFlex
Mooring System Types
CALM Buoy Systems
- Tanker mooring terminal
- Multi-point catenary anchor legs
- Weathervaning capability
- Typical 4-8 anchor legs
SALM Buoy Systems
- Single anchor leg with swivel
- Weathervaning around single point
- Suitable for deep water
- Simpler installation
Spread Mooring
- Fixed heading systems
- Multiple mooring lines (8-16 typical)
- Semi-submersible and FPSO applications
- Symmetric or asymmetric configurations
Implementation Pattern
Mooring System Configuration
from dataclasses import dataclass, field
from typing import List, Dict, Optional, Tuple
from enum import Enum
import numpy as np
import logging
logger = logging.getLogger(__name__)
class MooringType(Enum):
CALM = "calm"
SALM = "salm"
SPREAD = "spread"
TURRET = "turret"
class LineType(Enum):
CHAIN = "chain"
WIRE = "wire"
POLYESTER = "polyester"
COMBINATION = "combination"
@dataclass
class MooringLineProperties:
"""Properties of a mooring line segment."""
line_type: LineType
length: float
diameter: float
mbl: float
weight_water: float
ea: float
drag_coeff: float = 2.4
@dataclass
class AnchorProperties:
"""Anchor properties."""
anchor_type:
holding_capacity:
location: [, , ]
:
line_id:
segments: [MooringLineProperties]
anchor: AnchorProperties
fairlead_location: [, , ]
pretension: =
:
system_type: MooringType
water_depth:
lines: [MooringLine]
vessel_type:
design_life_years: =
:
wave_hs:
wave_tp:
wave_direction:
current_speed:
current_direction:
wind_speed:
wind_direction:
return_period: =
Catenary Analysis
class CatenaryAnalyzer:
"""Analyze catenary mooring line geometry and tensions."""
def __init__(self, water_depth: float):
self.water_depth = water_depth
def solve_catenary(
self,
line: MooringLineProperties,
horizontal_tension: float,
touchdown_distance: float = None
) -> Dict:
"""
Solve catenary equations for mooring line.
Args:
line: Line properties
horizontal_tension: Horizontal tension at fairlead (kN)
touchdown_distance: Distance to touchdown point (m)
Returns:
Dictionary with catenary geometry and tensions
"""
w = line.weight_water * 9.81 / 1000
H = horizontal_tension
a = H / w
z = self.water_depth
s = a * np.sinh(z / a) if z / a < 20 else a * np.exp(z / a) / 2
x = a * np.arccosh(1 + z / a) if z / a < 20 else a * np.log(2 * z / a)
T_fairlead = np.sqrt(H**2 + (w * s)**2)
T_touchdown = H
angle_fairlead = np.degrees(np.arctan(w * s / H))
{
: H,
: T_fairlead,
: T_touchdown,
: s,
: x,
: angle_fairlead,
: a,
: (, line.length - s)
}
() -> :
H = catenary_result[]
w = line.weight_water * /
a = catenary_result[]
x = catenary_result[]
k_geom = w * np.cosh(x / a) / np.sinh(x / a)**
s = catenary_result[]
k_elastic = line.ea / s
k_total = / (/k_geom + /k_elastic) k_elastic > k_geom
k_total
Mooring Design Calculations
@dataclass
class DesignLoadCase:
"""Design load case for mooring analysis."""
name: str
condition: str
environment: EnvironmentalConditions
safety_factor_required: float
@dataclass
class MooringDesignResult:
"""Results from mooring design analysis."""
line_id: str
load_case: str
max_tension: float
min_mbl: float
safety_factor: float
utilization: float
passes: bool
class MooringDesigner:
"""Design and verify mooring systems."""
SAFETY_FACTORS = {
'intact': {
'quasi-static': 2.0,
'dynamic': 1.67
},
'damaged': {
'quasi-static': 1.43,
'dynamic': 1.25
},
'transient': {
'quasi-static': 1.10,
'dynamic': 1.05
}
}
def __init__(self, system: MooringSystem):
self.system = system
self.analyzer = CatenaryAnalyzer(system.water_depth)
() -> :
Lbp = vessel_data.get(, )
B = vessel_data.get(, )
draft = vessel_data.get(, )
Hs = environment.wave_hs
rho =
g =
Cwd =
F_wave_drift = Cwd * rho * g * Hs** * B / /
Cd_current =
A_current = Lbp * draft
V_current = environment.current_speed
F_current = * rho * Cd_current * A_current * V_current** /
rho_air =
Cd_wind =
A_wind = vessel_data.get(, )
V_wind = environment.wind_speed
F_wind = * rho_air * Cd_wind * A_wind * V_wind** /
{
: F_wave_drift,
: F_current,
: F_wind,
: F_wave_drift + F_current + F_wind
}
() -> [MooringDesignResult]:
results = []
sf_required = .SAFETY_FACTORS[][]
line .system.lines:
fairlead = np.array(line.fairlead_location)
anchor = np.array(line.anchor.location)
offset_x, offset_y, rotation = vessel_offset
fairlead[] += offset_x
fairlead[] += offset_y
h_dist = np.sqrt(
(fairlead[] - anchor[])** +
(fairlead[] - anchor[])**
)
total_length = (seg.length seg line.segments)
main_segment = line.segments[]
catenary = .analyzer.solve_catenary(
main_segment,
horizontal_tension=line.pretension
)
max_tension = catenary[] *
mbl = (seg.mbl seg line.segments)
sf_actual = mbl / max_tension max_tension > ()
results.append(MooringDesignResult(
line_id=line.line_id,
load_case=,
max_tension=max_tension,
min_mbl=max_tension * sf_required,
safety_factor=sf_actual,
utilization= / sf_actual sf_actual > ,
passes=sf_actual >= sf_required
))
results
() -> [MooringDesignResult]:
results = []
sf_required = .SAFETY_FACTORS[][]
remaining_lines = [l l .system.lines l.line_id != damaged_line_id]
load_increase_factor = (.system.lines) / (remaining_lines)
line remaining_lines:
main_segment = line.segments[]
catenary = .analyzer.solve_catenary(
main_segment,
horizontal_tension=line.pretension * load_increase_factor
)
max_tension = catenary[] * * load_increase_factor
mbl = (seg.mbl seg line.segments)
sf_actual = mbl / max_tension max_tension > ()
results.append(MooringDesignResult(
line_id=line.line_id,
load_case=,
max_tension=max_tension,
min_mbl=max_tension * sf_required,
safety_factor=sf_actual,
utilization= / sf_actual sf_actual > ,
passes=sf_actual >= sf_required
))
results
OrcaFlex Model Generator
class OrcaFlexModelGenerator:
"""Generate OrcaFlex model files for mooring analysis."""
def __init__(self, system: MooringSystem):
self.system = system
def generate_line_data(self, line: MooringLine) -> Dict:
"""Generate OrcaFlex line data for a mooring line."""
line_data = {
'Name': line.line_id,
'LineType': [],
'Length': [],
'TargetSegmentLength': [],
'EndAConnection': 'Fixed',
'EndAX': line.anchor.location[0],
'EndAY': line.anchor.location[1],
'EndAZ': line.anchor.location[2],
'EndBConnection': 'Vessel1',
'EndBX': line.fairlead_location[0],
'EndBY': line.fairlead_location[1],
'EndBZ': line.fairlead_location[2],
}
for i, seg in enumerate(line.segments):
line_data['LineType'].append(self._get_line_type_name(seg))
line_data['Length'].append(seg.length)
line_data['TargetSegmentLength'].append(min(10, seg.length / 20))
line_data
() -> :
() -> :
{
: ._get_line_type_name(seg),
: seg.line_type.value.capitalize(),
: seg.diameter / ,
: seg.weight_water + * np.pi * (seg.diameter/)**,
: seg.ea * ,
: ,
: seg.drag_coeff,
: ,
}
() -> :
yaml
model = {
: {
: .system.water_depth,
: ,
},
: {
: ,
: ,
},
: [],
: [],
}
line_types_seen = ()
line .system.lines:
seg line.segments:
type_name = ._get_line_type_name(seg)
type_name line_types_seen:
model[].append(.generate_line_type(seg))
line_types_seen.add(type_name)
line .system.lines:
model[].append(.generate_line_data(line))
(output_path, ) f:
yaml.dump(model, f, default_flow_style=)
output_path
YAML Configuration
system:
type: calm
water_depth: 100.0
design_life_years: 20
vessel:
type: tanker
length: 280.0
beam: 46.0
draft: 17.5
windage_area: 6000.0
mooring_pattern:
n_lines: 6
anchor_radius: 450.0
first_line_heading: 30.0
line_configuration:
segments:
- type: chain
length: 400.0
diameter: 84.0
grade: R4
- type: polyester
length: 200.0
diameter: 140.0
anchors:
type: suction_pile
capacity: 5000.0
environment:
100_year:
wave_hs: 8.5
wave_tp:
Usage Examples
Basic Design
from mooring_design import (
MooringSystem, MooringLine, MooringLineProperties,
AnchorProperties, MooringType, LineType, MooringDesigner
)
chain = MooringLineProperties(
line_type=LineType.CHAIN,
length=400.0,
diameter=84.0,
mbl=8500.0,
weight_water=145.0,
ea=850000.0
)
anchor = AnchorProperties(
anchor_type="suction",
holding_capacity=5000.0,
location=(400.0, 0.0, -100.0)
)
line1 = MooringLine(
line_id="ML1",
segments=[chain],
anchor=anchor,
fairlead_location=(20.0, 0.0, -10.0),
pretension=500.0
)
system = MooringSystem(
system_type=MooringType.CALM,
water_depth=100.0,
lines=[line1],
vessel_type="tanker"
)
designer = MooringDesigner(system)
results = designer.analyze_intact_condition(
vessel_offset=(10.0, 5.0, 5.0),
environment=env
)
for result in results:
print(f"{result.line_id}: SF={result.safety_factor:.2f} ({'PASS' if result.passes else 'FAIL'})")
Generate OrcaFlex Model
from mooring_design import OrcaFlexModelGenerator
generator = OrcaFlexModelGenerator(system)
generator.generate_model_yml('models/mooring_analysis.yml')
Standards Reference
DNV-OS-E301 (Position Mooring)
- Safety factors for ULS and ALS
- Line tension limits
- Fatigue requirements
API RP 2SK (Station Keeping)
- Design criteria
- Environmental loads
- Analysis methods
ABS (Position Mooring Systems)
- Material specifications
- Testing requirements
- Survey requirements
Best Practices
Design Principles
- Provide redundancy (n+1 or n+2 lines)
- Consider full range of environmental directions
- Account for manufacturing tolerances
- Include fatigue in line sizing
Analysis Approach
- Perform quasi-static and dynamic analysis
- Check all intact and damaged conditions
- Verify anchor capacity
- Include VIM/VIV effects if applicable
Documentation
- Document all assumptions
- Include environmental data sources
- Provide clear load case definitions
- Show safety factor compliance
Related Skills