Skip to content

Commit c2ee87e

Browse files
authored
Merge pull request #153 from hivanov-nrel/mooring
Mooring module
2 parents 884beef + 86d96e0 commit c2ee87e

14 files changed

Lines changed: 9115 additions & 3 deletions

changelog.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Current development
22

3+
## PR 153 - Mooring Module
4+
5+
- Author: @hivanov-nrel
6+
- Addition of the mooring module, which includes
7+
- Read in MoorDyn files into MATLAB
8+
- Function to calculate mooring line lay length
9+
- Functions to visualize mooring line dynamics in 2D or 3D.
10+
- Example LiveScript demonstrating the functionality of the mooring module
11+
312
## PR 170 - WDRT leftovers
413

514
- Author: @hivanov-nrel

examples/data/mooring/Test.MD.out

Lines changed: 4803 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--------------------- MoorDyn Input File ------------------------------------
2+
Mooring system for OC4-DeepCwind Semi
3+
FALSE Echo - echo the input file data (flag)
4+
----------------------- LINE TYPES ------------------------------------------
5+
Name Diam MassDen EA BA/-zeta EI Cd Ca CdAx CaAx
6+
(-) (m) (kg/m) (N) (N-s/-) (-) (-) (-) (-) (-)
7+
main 0.0766 113.35 7.536E8 -1.0 0 2.0 0.8 0.4 0.25
8+
---------------------- POINTS --------------------------------
9+
ID Attachment X Y Z M V CdA CA
10+
(-) (-) (m) (m) (m) (kg) (m^3) (m^2) (-)
11+
1 Fixed 418.8 725.383 -200.0 0 0 0 0
12+
2 Fixed -837.6 0.0 -200.0 0 0 0 0
13+
3 Fixed 418.8 -725.383 -200.0 0 0 0 0
14+
4 Vessel 20.434 35.393 -14.0 0 0 0 0
15+
5 Vessel -40.868 0.0 -14.0 0 0 0 0
16+
6 Vessel 20.434 -35.393 -14.0 0 0 0 0
17+
---------------------- LINES --------------------------------------
18+
ID LineType AttachA AttachB UnstrLen NumSegs Outputs
19+
(-) (-) (-) (-) (m) (-) (-)
20+
1 main 1 4 835.35 20 -
21+
2 main 2 5 835.35 20 -
22+
3 main 3 6 835.35 20 -
23+
---------------------- SOLVER OPTIONS ---------------------------------------
24+
0.001 dtM - time step to use in mooring integration (s)
25+
3.0e6 kbot - bottom stiffness (Pa/m)
26+
3.0e5 cbot - bottom damping (Pa-s/m)
27+
2.0 dtIC - time interval for analyzing convergence during IC gen (s)
28+
60.0 TmaxIC - max time for ic gen (s)
29+
4.0 CdScaleIC - factor by which to scale drag coefficients during dynamic relaxation (-)
30+
0.01 threshIC - threshold for IC convergence (-)
31+
------------------------ OUTPUTS --------------------------------------------
32+
FairTen1
33+
FairTen2
34+
FairTen3
35+
AnchTen1
36+
AnchTen2
37+
AnchTen3
38+
END
39+
------------------------- need this line --------------------------------------

examples/data/mooring/line1_test.out

Lines changed: 3583 additions & 0 deletions
Large diffs are not rendered by default.

examples/mooring_example.html

Lines changed: 210 additions & 0 deletions
Large diffs are not rendered by default.

examples/mooring_example.m

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
%% Mooring Module Example
2+
% In this example, we'll explore the functionalities of the Mooring module of
3+
% the Marine and Hydrokinetic Toolkit (MHKiT). As of now, this module primarily
4+
% supports output from MoorDyn, an innovative tool for simulating the complex
5+
% dynamics of mooring lines used in marine applications.
6+
%
7+
% The objective will be to analyze the MoorDyn output data of a single mooring
8+
% line. The steps are:
9+
%%
10+
% # *Import Data* - Import the MoorDyn output
11+
% # *Lay Length* - Calculate the lay length parameter
12+
% # *Visualize* - Create graphical animations
13+
% Importing Data
14+
% The first step is to import the MoorDyn output file. This file contains the
15+
% key data that we'll be analyzing throughout this notebook. If support for other
16+
% types of output is desired, please raise an issue or reach out to the MHKiT
17+
% team!
18+
%
19+
% The code below provides paths to two files:
20+
%%
21+
% * |fpath| = MoorDyn output file of a single mooring line containing node positions
22+
% and segment tensions
23+
% * |inputfile| = Path to MoorDyn input file that corresponds to the output.
24+
% This is an optional argument which parses the input parameters and writes them
25+
% a struct for reference. Note: the input file provided here does not match the
26+
% output and is only meant for demonstration purposes.
27+
28+
% define the paths
29+
fpath = "./examples/data/mooring/line1_test.out";
30+
inputfile = "./examples/data/mooring/TestInput.MD.dat";
31+
% load in data
32+
[data, input] = read_moordyn(fpath, inputfile)
33+
% Calculating the Lay Length with MoorDyn Data
34+
% Next, we turn our focus to calculating the 'lay length'. Lay length is the
35+
% measure of how much of the mooring line is in contact with the seabed.
36+
%
37+
% To calculate the lay length, we'll use the MoorDyn output data we imported
38+
% in the previous step. We also need to define two key parameters:
39+
%%
40+
% * The |depth| of the seabed, which we've set as -56m for this example. Please
41+
% note that the seabed depth is considered negative as we're measuring downwards
42+
% from the sea level.
43+
% * The |tolerance|, or the threshold, for determining when a node is deemed
44+
% to be in contact with the seabed. For this exercise, we'll use a tolerance of
45+
% 0.25m. The selection of a suitable tolerance value depends on various factors
46+
% including the resolution of your data and the specifics of your application.
47+
%%
48+
% We use the |lay_length| function for this calculation, which will yield an
49+
% array representing the lay length of the mooring line at each time step. Let's
50+
% execute the function:
51+
52+
depth = -56; % meters
53+
tolerance = 0.25; % meters
54+
laylength = lay_length(data, -56, 0.25)
55+
%%
56+
% Additionally we can use this information to get an average lay length for
57+
% the whole time period.
58+
59+
fprintf('The average lay length of the mooring line is: %.1f meters', mean(laylength))
60+
% Visualizing Mooring Line Dynamics with Graphics
61+
% After calculating the lay length, let's progress to the final step of our
62+
% journey: visualization. The mooring module within MHKiT provides tools to create
63+
% interactive, informative graphics that can help us visualize and better understand
64+
% the behavior of the mooring line.
65+
%
66+
% However, to keep things performance-friendly, we will first slice our initial
67+
% data down to a 10-second window. This reduces computational demand while still
68+
% providing a useful snapshot of our mooring line's dynamics.
69+
%
70+
% With our data subset ready, we can create a 3D animation of the mooring line
71+
% using the |plot_mooring_animate|.
72+
73+
plot_mooring_animate(data(data.Time<10, :), '3D', 0.05, ...
74+
'xlabel','X-axis','ylabel','Y-axis','zlabel','depth','title','3D example')
75+
%%
76+
% In this simplified example, the mooring line is constrained from moving along
77+
% the y-axis. Since there is no motion along the y-axis, it would actually be
78+
% easier to view the animation in 2D instead. This can be accomplished with the
79+
% |plot_mooring_animate| function specifying dimension=|'2D'|.
80+
81+
plot_mooring_animate(data(data.Time<10, :), '2D', 0.05, ...
82+
'xlabel','X-axis','ylabel','depth [m]','title','2D example')
83+
%%
84+
% Through these graphical representations, we can gain a more intuitive understanding
85+
% of how the mooring line interacts with the surrounding marine environment over
86+
% time.
87+
% Summary and Conclusion
88+
% In this notebook, we walked through the MHKiT Mooring module learning how
89+
% to utilize MHKiT in conjunction with MoorDyn output to analyze the dynamics
90+
% of a single mooring line.
91+
%
92+
% We used the |read_moordyn| function to bring this data into Matlab, preparing
93+
% it for further analysis. Next, we calculated the 'lay length' of our mooring
94+
% line using the |lay_length| function, obtaining an array representing the lay
95+
% length at each time step. Finally, we visualized 2D and 3D animations of the
96+
% mooring line's behavior over a 10-second period using the |plot_mooring_animate|
97+
% function.
98+
%
99+
% We hope that this example serves as a valuable guide to employing the MHKiT
100+
% Mooring module and MoorDyn analyses.
101+
%
102+
% Thank you for your interest in MHKiT! We encourage you to continue to open
103+
% an issue or pull request if you have any feedback or expansions which would
104+
% help you improve your mooring data analysis.

examples/mooring_example.mlx

119 KB
Binary file not shown.

mhkit/mooring/lay_length.m

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
function line_lay_length = lay_length(data, depth, tolerance)
2+
3+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4+
% Calculate the lay length of a mooring line over time.
5+
%
6+
% Lay length is the measure of how much of the mooring line is in contact
7+
% with the seabed. This function requires MoorDyn line output data containing
8+
% individual node positions NodeNpx, NodeNpy, NodeNpz.
9+
%
10+
% Parameters
11+
% ----------
12+
% data: table
13+
% MoorDyn line output data table containing Time column and node
14+
% position data (NodeNpx, NodeNpy, NodeNpz) where N is the node number.
15+
% Data should be obtained using mhkit.mooring.read_moordyn() with a
16+
% MoorDyn line output file (*.Line*.out).
17+
% depth: double
18+
% Depth of seabed (m). Should be negative for depths below sea level.
19+
% tolerance: double, optional
20+
% Tolerance to detect first lift point from seabed, by default 0.25
21+
% meters. Nodes with z-position > depth + abs(tolerance) are
22+
% considered lifted from seabed.
23+
%
24+
% Returns
25+
% -------
26+
% line_lay_length: double array
27+
% Array containing the lay length at each time step (m)
28+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
29+
30+
31+
arguments
32+
data table
33+
depth {mustBeNumeric}
34+
tolerance {mustBeNumeric} = 0.25
35+
end
36+
37+
%channel names
38+
chans = data.Properties.VariableNames;
39+
40+
% get node names
41+
idx = strfind(chans, 'x');
42+
idx = cell2mat(cellfun(@(x)any(~isempty(x)),idx,'UniformOutput',false));
43+
nodes_x = {chans{idx}};
44+
idy = strfind(chans, 'y');
45+
idy = cell2mat(cellfun(@(x)any(~isempty(x)),idy,'UniformOutput',false));
46+
nodes_y = {chans{idy}};
47+
idz = strfind(chans, 'z');
48+
idz = cell2mat(cellfun(@(x)any(~isempty(x)),idz,'UniformOutput',false));
49+
nodes_z = {chans{idz}};
50+
51+
% check if data contains the necessary nodes
52+
if isempty(nodes_x) || isempty(nodes_y) || isempty(nodes_z)
53+
error("The data must contain x, y, and z node data!")
54+
end
55+
if length(nodes_z) < 3
56+
error("This function requires at least 3 nodes to calculate lay length")
57+
end
58+
59+
% find name of first z point where tolerance is exceeded
60+
zdata = table2array(data(:,nodes_z)); % Convert table to array
61+
laypoint_mask = zdata > (depth + abs(tolerance));
62+
laypoint = nodes_z(any(laypoint_mask));
63+
64+
% get previous z-point
65+
lay_indx = find(cellfun(@(x) strcmp(x, laypoint), nodes_z)) - 1;
66+
lay_z = nodes_z(lay_indx);
67+
68+
% get corresponding x-point and y-point node names
69+
lay_x = strcat(lay_z{:}(1:end-1), "x");
70+
lay_y = strcat(lay_z{:}(1:end-1), "y");
71+
lay_0x = nodes_x{1};
72+
lay_0y = nodes_y{1};
73+
74+
% find distance between initial point and lay point
75+
laylength_x = data.(lay_x) - data.(lay_0x);
76+
laylength_y = data.(lay_y) - data.(lay_0y);
77+
line_lay_length = (laylength_x.^2 + laylength_y.^2) .^ 0.5;
78+
79+
end
80+
81+
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
function plot_mooring_animate(data, dimension, step, varargin)
2+
%Graphics function that creates a 2D or 3D animation of the node
3+
% positions of a mooring line over time.
4+
% Detailed explanation goes here
5+
6+
arguments (Input)
7+
data
8+
dimension {mustBeTextScalar} = '2D'
9+
step {mustBeNumeric} = 0.05
10+
end
11+
arguments (Repeating)
12+
varargin
13+
end
14+
15+
%channel names
16+
chans = data.Properties.VariableNames;
17+
18+
% get node names
19+
idx = strfind(chans, 'x');
20+
idx = cell2mat(cellfun(@(x)any(~isempty(x)),idx,'UniformOutput',false));
21+
nodes_x = {chans{idx}};
22+
idy = strfind(chans, 'y');
23+
idy = cell2mat(cellfun(@(x)any(~isempty(x)),idy,'UniformOutput',false));
24+
nodes_y = {chans{idy}};
25+
idz = strfind(chans, 'z');
26+
idz = cell2mat(cellfun(@(x)any(~isempty(x)),idz,'UniformOutput',false));
27+
nodes_z = {chans{idz}};
28+
29+
figure;
30+
% allow for axis labels
31+
for k = 1:2:length(varargin)
32+
labelType = varargin{k};
33+
labelText = varargin{k+1};
34+
35+
switch lower(labelType)
36+
case 'title'
37+
title(labelText);
38+
case 'xlabel'
39+
xlabel(labelText);
40+
case 'ylabel'
41+
ylabel(labelText);
42+
case 'zlabel'
43+
zlabel(labelText);
44+
otherwise
45+
warning('Unknown label type: %s', labelType);
46+
end
47+
end
48+
49+
% 2D animate
50+
if strcmp(dimension,'2D')
51+
h = animatedline('Marker','o');
52+
grid on
53+
clearpoints(h);
54+
for k=1:size(data,2)
55+
clearpoints(h);
56+
x = table2array(data(k, nodes_x));
57+
z = table2array(data(k, nodes_z));
58+
addpoints(h,x,z)
59+
drawnow
60+
pause(step)
61+
end
62+
% 3D animate
63+
elseif strcmp(dimension,'3D')
64+
view(3);
65+
h = animatedline('Marker','o');
66+
grid on
67+
clearpoints(h);
68+
for k=1:size(data,2)
69+
clearpoints(h);
70+
x = table2array(data(k, nodes_x));
71+
y = table2array(data(k, nodes_y));
72+
z = table2array(data(k, nodes_z));
73+
addpoints(h,x,y,z)
74+
drawnow
75+
pause(step)
76+
end
77+
else
78+
error('Please make sure to specify the correct dimension!')
79+
end
80+
81+
82+
83+
end
84+

0 commit comments

Comments
 (0)