Skip to content
mooring-design logo

Mooring Design Skill

mooring-design

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.

mattnigh/skills_collection0installs24stars

SKILL.md

Full skill instructions

Mooring Design Skill

Design and analyze mooring systems for floating offshore structures, including CALM buoys, SALM buoys, and spread mooring configurations.

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            # meters
    diameter: float          # mm
    mbl: float              # Minimum Breaking Load (kN)
    weight_water: float     # Weight in water (kg/​m)
    ea: float               # Axial stiffness EA (kN)
    drag_coeff: float = 2.4 # Normal drag coefficient


@dataclass
class AnchorProperties:
    """Anchor properties."""
    anchor_type: str         # drag, suction, pile
    holding_capacity: float  # kN
    location: Tuple[float, float, float]  # (x, y, z) in meters


@dataclass
class MooringLine:
    """Complete mooring line configuration."""
    line_id: str
    segments: List[MooringLineProperties]
    anchor: AnchorProperties
    fairlead_location: Tuple[float, float, float]
    pretension: float = 0.0  # kN


@dataclass
class MooringSystem:
    """Complete mooring system configuration."""
    system_type: MooringType
    water_depth: float
    lines: List[MooringLine]
    vessel_type: str
    design_life_years: float = 20.0


@dataclass
class EnvironmentalConditions:
    """Environmental loading conditions."""
    wave_hs: float           # Significant wave height (m)
    wave_tp: float           # Peak period (s)
    wave_direction: float    # degrees from North
    current_speed: float     # m/​s
    current_direction: float # degrees
    wind_speed: float        # m/​s at 10m
    wind_direction: float    # degrees
    return_period: float = 100  # years

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  # kN/​m
        H = horizontal_tension

        # Catenary parameter
        a = H / w

        # Calculate geometry
        # Vertical height from seabed
        z = self.water_depth

        # Arc length from touchdown to fairlead
        s = a * np.sinh(z / a) if z / a < 20 else a * np.exp(z / a) / 2

        # Horizontal distance from touchdown to fairlead
        x = a * np.arccosh(1 + z / a) if z / a < 20 else a * np.log(2 * z / a)

        # Tension at fairlead
        T_fairlead = np.sqrt(H**2 + (w * s)**2)

        # Tension at touchdown (vertical = 0)
        T_touchdown = H

        # Angle at fairlead
        angle_fairlead = np.degrees(np.arctan(w * s / H))

        return {
            'horizontal_tension': H,
            'fairlead_tension': T_fairlead,
            'touchdown_tension': T_touchdown,
            'arc_length': s,
            'horizontal_distance': x,
            'fairlead_angle': angle_fairlead,
            'catenary_parameter': a,
            'grounded_length': max(0, line.length - s)
        }

    def calculate_stiffness(
        self,
        line: MooringLineProperties,
        catenary_result: Dict
    ) -> float:
        """
        Calculate horizontal stiffness of mooring line.

        Args:
            line: Line properties
            catenary_result: Result from solve_catenary

        Returns:
            Horizontal stiffness (kN/​m)
        """
        H = catenary_result['horizontal_tension']
        w = line.weight_water * 9.81 / 1000
        a = catenary_result['catenary_parameter']
        x = catenary_result['horizontal_distance']

        # Geometric stiffness
        k_geom = w * np.cosh(x / a) / np.sinh(x / a)**2

        # Elastic stiffness contribution
        s = catenary_result['arc_length']
        k_elastic = line.ea / s

        # Combined (series)
        k_total = 1 / (1/​k_geom + 1/​k_elastic) if k_elastic > 0 else k_geom

        return k_total

Mooring Design Calculations

@dataclass
class DesignLoadCase:
    """Design load case for mooring analysis."""
    name: str
    condition: str  # intact, damaged, transient
    environment: EnvironmentalConditions
    safety_factor_required: float


@dataclass
class MooringDesignResult:
    """Results from mooring design analysis."""
    line_id: str
    load_case: str
    max_tension: float        # kN
    min_mbl: float           # Required MBL (kN)
    safety_factor: float
    utilization: float
    passes: bool


class MooringDesigner:
    """Design and verify mooring systems."""

    # Safety factors per DNV-OS-E301
    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)

    def calculate_environmental_loads(
        self,
        vessel_data: Dict,
        environment: EnvironmentalConditions
    ) -> Dict:
        """
        Calculate environmental loads on vessel.

        Args:
            vessel_data: Vessel particulars
            environment: Environmental conditions

        Returns:
            Dictionary with load components
        """
        # Wave drift force (simplified)
        Lbp = vessel_data.get('length', 200)
        B = vessel_data.get('beam', 40)
        draft = vessel_data.get('draft', 15)

        # Mean wave drift (Newman approximation)
        Hs = environment.wave_hs
        rho = 1025  # kg/​m³
        g = 9.81

        # Drift force coefficient (approximate)
        Cwd = 0.5
        F_wave_drift = Cwd * rho * g * Hs**2 * B / 2 / 1000  # kN

        # Current force
        Cd_current = 1.0
        A_current = Lbp * draft
        V_current = environment.current_speed
        F_current = 0.5 * rho * Cd_current * A_current * V_current**2 / 1000  # kN

        # Wind force
        rho_air = 1.225
        Cd_wind = 1.0
        A_wind = vessel_data.get('windage_area', 5000)  # m²
        V_wind = environment.wind_speed
        F_wind = 0.5 * rho_air * Cd_wind * A_wind * V_wind**2 / 1000  # kN

        return {
            'wave_drift': F_wave_drift,
            'current': F_current,
            'wind': F_wind,
            'total': F_wave_drift + F_current + F_wind
        }

    def analyze_intact_condition(
        self,
        vessel_offset: Tuple[float, float, float],
        environment: EnvironmentalConditions
    ) -> List[MooringDesignResult]:
        """
        Analyze mooring system in intact condition.

        Args:
            vessel_offset: Vessel offset (x, y, rotation)
            environment: Environmental conditions

        Returns:
            List of design results per line
        """
        results = []
        sf_required = self.SAFETY_FACTORS['intact']['dynamic']

        for line in self.system.lines:
            # Calculate line tension (simplified)
            # In practice, use OrcaFlex or similar
            fairlead = np.array(line.fairlead_location)
            anchor = np.array(line.anchor.location)

            # Apply vessel offset
            offset_x, offset_y, rotation = vessel_offset
            fairlead[0] += offset_x
            fairlead[1] += offset_y

            # Calculate horizontal distance
            h_dist = np.sqrt(
                (fairlead[0] - anchor[0])**2 +
                (fairlead[1] - anchor[1])**2
            )

            # Total line length
            total_length = sum(seg.length for seg in line.segments)

            # Estimate tension (catenary)
            main_segment = line.segments[0]
            catenary = self.analyzer.solve_catenary(
                main_segment,
                horizontal_tension=line.pretension
            )

            max_tension = catenary['fairlead_tension'] * 1.5  # Approximate dynamic factor

            # Calculate safety factor
            mbl = min(seg.mbl for seg in line.segments)
            sf_actual = mbl / max_tension if max_tension > 0 else float('inf')

            results.append(MooringDesignResult(
                line_id=line.line_id,
                load_case='intact',
                max_tension=max_tension,
                min_mbl=max_tension * sf_required,
                safety_factor=sf_actual,
                utilization=1 / sf_actual if sf_actual > 0 else 1.0,
                passes=sf_actual >= sf_required
            ))

        return results

    def analyze_damaged_condition(
        self,
        damaged_line_id: str,
        vessel_offset: Tuple[float, float, float],
        environment: EnvironmentalConditions
    ) -> List[MooringDesignResult]:
        """
        Analyze mooring system with one line failed.

        Args:
            damaged_line_id: ID of failed line
            vessel_offset: Vessel offset
            environment: Environmental conditions

        Returns:
            List of design results for remaining lines
        """
        results = []
        sf_required = self.SAFETY_FACTORS['damaged']['dynamic']

        remaining_lines = [l for l in self.system.lines if l.line_id != damaged_line_id]

        # Recalculate with increased loads on remaining lines
        load_increase_factor = len(self.system.lines) / len(remaining_lines)

        for line in remaining_lines:
            main_segment = line.segments[0]
            catenary = self.analyzer.solve_catenary(
                main_segment,
                horizontal_tension=line.pretension * load_increase_factor
            )

            max_tension = catenary['fairlead_tension'] * 1.5 * load_increase_factor

            mbl = min(seg.mbl for seg in line.segments)
            sf_actual = mbl / max_tension if max_tension > 0 else float('inf')

            results.append(MooringDesignResult(
                line_id=line.line_id,
                load_case=f'damaged_{damaged_line_id}',
                max_tension=max_tension,
                min_mbl=max_tension * sf_required,
                safety_factor=sf_actual,
                utilization=1 / sf_actual if sf_actual > 0 else 1.0,
                passes=sf_actual >= sf_required
            ))

        return 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],
        }

        # Add segments
        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))

        return line_data

    def _get_line_type_name(self, seg: MooringLineProperties) -> str:
        """Generate line type name."""
        return f"{seg.line_type.value}_{seg.diameter}mm"

    def generate_line_type(self, seg: MooringLineProperties) -> Dict:
        """Generate OrcaFlex line type definition."""
        return {
            'Name': self._get_line_type_name(seg),
            'Category': seg.line_type.value.capitalize(),
            'OD': seg.diameter / 1000,  # Convert to meters
            'MassPerUnitLength': seg.weight_water + 1025 * np.pi * (seg.diameter/​2000)**2,
            'EA': seg.ea * 1000,  # Convert to N
            'EI': 0,  # Flexible line
            'NormalDragCoefficient': seg.drag_coeff,
            'AxialDragCoefficient': 0.1,
        }

    def generate_model_yml(self, output_path: str) -> str:
        """
        Generate YAML configuration for OrcaFlex model.

        Args:
            output_path: Path to save YAML file

        Returns:
            Path to generated file
        """
        import yaml

        model = {
            'General': {
                'WaterDepth': self.system.water_depth,
                'UnitsSystem': 'SI',
            },
            'Environment': {
                'WaterDensity': 1025,
                'KinematicViscosity': 1.19e-6,
            },
            'LineTypes': [],
            'Lines': [],
        }

        # Collect unique line types
        line_types_seen = set()
        for line in self.system.lines:
            for seg in line.segments:
                type_name = self._get_line_type_name(seg)
                if type_name not in line_types_seen:
                    model['LineTypes'].append(self.generate_line_type(seg))
                    line_types_seen.add(type_name)

        # Add lines
        for line in self.system.lines:
            model['Lines'].append(self.generate_line_data(line))

        with open(output_path, 'w') as f:
            yaml.dump(model, f, default_flow_style=False)

        return output_path

YAML Configuration

# config/​mooring_design.yaml

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  # degrees

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  # kN

environment:
  100_year:
    wave_hs: 8.5
    wave_tp: 12.5
    current_speed: 1.2
    wind_speed: 25.0

analysis:
  load_cases:
    - name: intact_100yr
      condition: intact
      environment: 100_year
    - name: damaged_100yr
      condition: damaged
      environment: 100_year

Usage Examples

Basic Design

from mooring_design import (
    MooringSystem, MooringLine, MooringLineProperties,
    AnchorProperties, MooringType, LineType, MooringDesigner
)

# Define line segments
chain = MooringLineProperties(
    line_type=LineType.CHAIN,
    length=400.0,
    diameter=84.0,
    mbl=8500.0,
    weight_water=145.0,
    ea=850000.0
)

# Define anchor
anchor = AnchorProperties(
    anchor_type="suction",
    holding_capacity=5000.0,
    location=(400.0, 0.0, -100.0)
)

# Create mooring line
line1 = MooringLine(
    line_id="ML1",
    segments=[chain],
    anchor=anchor,
    fairlead_location=(20.0, 0.0, -10.0),
    pretension=500.0
)

# Create system
system = MooringSystem(
    system_type=MooringType.CALM,
    water_depth=100.0,
    lines=[line1],  # Add more lines
    vessel_type="tanker"
)

# Analyze
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

More skills from mattnigh

spring-framework-patterns logo
mattnigh/skills_collection

spring-framework-patterns

Comprehensive Spring Framework and Spring Boot best practices including dependency injection patterns, bean lifecycle and scopes, REST API development, Spring Data JPA, service layer design, Spring Security, testing strategies, caching, AOP, async processing, error handling, and common anti-patte...

24 0
View

TypeScript厳格モードによる型安全性設計を専門とするスキル。 📖 参照書籍: - 『Effective TypeScript』(Dan Vanderkam): 型設計 📚 リソース参照: - `resources/Level1_basics.md`: レベル1の基礎ガイド - `resources/Level2_intermediate.md`: レベル2の実務ガイド - `resources/Level3_advanced.md`: レベル3の応用ガイド - `resources/Level4_expert.md`: レベル4の専門ガイド - `resources/di...

24 0
View
deploying-cloud-k8s logo
mattnigh/skills_collection

deploying-cloud-k8s

Deploys applications to cloud Kubernetes (AKS/GKE/DOKS) with CI/CD pipelines. Use when deploying to production, setting up GitHub Actions, troubleshooting deployments. Covers build-time vs runtime vars, architecture matching, and battle-tested debugging.

24 0
View
moai-alfred-agent-guide logo
mattnigh/skills_collection

moai-alfred-agent-guide

19-agent team structure, decision trees for agent selection, Haiku vs Sonnet model selection, and agent collaboration principles. Use when deciding which sub-agent to invoke, understanding team responsibilities, or learning multi-agent orchestration.

24 0
View
mermaid-diagram-generator logo
mattnigh/skills_collection

mermaid-diagram-generator

Converts architecture descriptions, module specs, or workflow docs into Mermaid diagrams. Use when visualizing brick module relationships, workflows (DDD, investigation), or system architecture. Supports: flowcharts, sequence diagrams, class diagrams, state machines, entity relationship diagrams,...

24 0
View
pre-flight-check logo
mattnigh/skills_collection

pre-flight-check

INVOKE FIRST before any code work. Validates git workflow (branch, issue, worklog) and checks approach. Use at START of every task and END before completing. Prevents skipped steps.

24 0
View
browser-dev-tools logo
mattnigh/skills_collection

browser-dev-tools

This skill should be used when working with browser-rendered artifacts (i.e. Bun, React/React Native) to proactively validate that development work on localhost is being built appropriately and to support debugging browser-rendered content. Use this skill after making frontend changes to verify t...

24 0
View
lead-dev logo
mattnigh/skills_collection

lead-dev

Lead Développeur - Coordination technique opérationnelle, code review, mentoring et livraison. Pair de web-dev-process au niveau OPÉRATIONS.

24 0
View
worker-monitor logo
mattnigh/skills_collection

worker-monitor

Monitor Docker workers, RQ queue health, and auto-scale workers (max 4). Use when: checking job progress, monitoring queue depth, scaling workers up/down, diagnosing slow processing, or waiting for jobs to complete. Referenced by data-quality skill during reprocessing.

24 0
View
quality-advisor logo
mattnigh/skills_collection

quality-advisor

Proactive quality guidance system that monitors artifact creation and provides real-time feedback on documentation quality

24 0
View
bump-version logo
mattnigh/skills_collection

bump-version

This skill should be used when the user wants to bump the version number in the workspace. It updates versions across all pyproject.toml files (root, tde, and tda packages) and the CHANGELOG.md to keep them synchronized.

24 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View