Mooring Module Example

In this example, we’ll explore the functionalities of the Mooring module of the Marine and Hydrokinetic Toolkit (MHKiT). As of now, this module primarily supports output from MoorDyn, an innovative tool for simulating the complex dynamics of mooring lines used in marine applications.

The objective will be to analyze the MoorDyn output data of a single mooring line. The steps are: 1. Import Data - Import the MoorDyn output 2. Lay Length - Calculate the lay length parameter 3. Visualize - Create graphical animations

[1]:
import mhkit.mooring as mooring

Importing Data with the IO Module

The first step is to import the MoorDyn output file. This file contains the key data that we’ll be analyzing throughout this notebook. If support for other types of output is desired, please raise an issue or reach out to the MHKiT team!

The code below provides paths to two files: * fpath = MoorDyn output file of a single mooring line containing node positions and segment tensions * inputfile = Path to MoorDyn input file that corresponds to the output. This is an optional argument which parses the input parameters and writes them to the xarray object as attributes for reference. Note: the input file provided here does not match the output and is only meant for demonstration purposes.

We use the mooring.io.read_moordyn function to import the data from these files into an xarray Dataset:

[2]:
fpath = ".\data\mooring\line1_test.out"
inputfile = ".\data\mooring\TestInput.MD.dat"

ds = mooring.io.read_moordyn(fpath, input_file=inputfile)
ds
[2]:
<xarray.Dataset>
Dimensions:   (Time: 3581)
Coordinates:
  * Time      (Time) float64 0.0 0.025 0.05 0.075 0.1 ... 89.42 89.45 89.47 89.5
Data variables: (12/43)
    Node0px   (Time) float64 -300.0 -300.0 -300.0 ... -300.0 -300.0 -300.0
    Node0py   (Time) float64 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0
    Node0pz   (Time) float64 -56.0 -56.0 -56.0 -56.0 ... -56.0 -56.0 -56.0 -56.0
    Node1px   (Time) float64 -295.0 -295.0 -295.0 ... -295.0 -295.0 -295.0
    Node1py   (Time) float64 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0
    Node1pz   (Time) float64 -56.02 -56.02 -56.02 ... -56.02 -56.02 -56.02
    ...        ...
    Seg5Ten   (Time) float64 5.266e+04 5.237e+04 ... 3.502e+04 3.502e+04
    Seg6Ten   (Time) float64 5.266e+04 5.238e+04 ... 3.502e+04 3.502e+04
    Seg7Ten   (Time) float64 5.267e+04 5.24e+04 ... 3.502e+04 3.502e+04
    Seg8Ten   (Time) float64 5.268e+04 5.242e+04 ... 3.502e+04 3.502e+04
    Seg9Ten   (Time) float64 5.27e+04 5.244e+04 ... 3.502e+04 3.502e+04
    Seg10Ten  (Time) float64 5.6e+04 5.573e+04 5.555e+04 ... 3.714e+04 3.713e+04
Attributes:
    LINE_TYPES:  {'main': {'Diam': '0.0766', 'MassDen': '113.35', 'EA': '7.53...
    POINTS:      {'1': {'Attachment': 'Fixed', 'X': '418.8', 'Y': '725.383', ...
    LINES:       {'1': {'LineType': 'main', 'AttachA': '1', 'AttachB': '4', '...
    OPTIONS:     {'dtM': '0.001', 'kbot': '3.0e6', 'cbot': '3.0e5', 'dtIC': '...

Calculating the Lay Length with MoorDyn Data

Next, we turn our focus to calculating the ‘lay length’. Lay length is the measure of how much of the mooring line is in contact with the seabed.

To calculate the lay length, we’ll use the MoorDyn output data we imported in the previous step. We also need to define two key parameters: * The depth of the seabed, which we’ve set as -56m for this example. Please note that the seabed depth is considered negative as we’re measuring downwards from the sea level. * The tolerance, or the threshold, for determining when a node is deemed to be in contact with the seabed. For this exercise, we’ll use a tolerance of 0.25m. The selection of a suitable tolerance value depends on various factors including the resolution of your data and the specifics of your application.

We use the mooring.lay_length function for this calculation, which will yield a DataArray representing the lay length of the mooring line at each time step. Let’s execute the function:

[3]:
laylength = mooring.lay_length(ds, depth=-56, tolerance=0.25)
laylength
[3]:
<xarray.DataArray (Time: 3581)>
array([45.001, 45.001, 45.001, ..., 45.001, 45.001, 45.001])
Coordinates:
  * Time     (Time) float64 0.0 0.025 0.05 0.075 0.1 ... 89.42 89.45 89.47 89.5

Additionally, we can use this information to get an average lay length for the whole time period.

[4]:
print(
    "The average lay length of the mooring line is: "
    + str(laylength.mean().values.round())
    + " meters"
)
The average lay length of the mooring line is: 45.0 meters

Visualizing Mooring Line Dynamics with Graphics

After calculating the lay length, let’s progress to the final step of our journey: visualization. The mooring module within MHKiT provides tools to create interactive, informative graphics that can help us visualize and better understand the behavior of the mooring line.

However, to keep things performance-friendly, we will first slice our initial data down to a 10-second window. This reduces computational demand while still providing a useful snapshot of our mooring line’s dynamics.

With our data subset ready, we can create a 3D animation of the mooring line using the mooring.graphics.animate function. We then import a few additional modules to enable the display of animations within this notebook.

[5]:
%matplotlib agg
from IPython.display import HTML

dsani = ds.sel(Time=slice(0, 10))

ani = mooring.graphics.animate(
    dsani,
    dimension="3d",
    interval=10,
    repeat=True,
    xlabel="X-axis",
    ylabel="Y-axis",
    zlabel="Depth [m]",
    title="Mooring Line Example",
)
HTML(ani.to_jshtml())
c:\users\sterl\codes\mhkit-python\mhkit\mooring\graphics.py:129: UserWarning: Attempting to set identical low and high zlims makes transformation singular; automatically expanding.
  ax.set(xlim3d=xlim, ylim3d=ylim, zlim3d=zlim)
Animation size has reached 20989322 bytes, exceeding the limit of 20971520.0. If you're sure you want a larger animation embedded, set the animation.embed_limit rc parameter to a larger value (in MB). This and further frames will be dropped.
[5]:

In this simplified example, the mooring line is constrained from moving along the y-axis. Therefore, it would actually be easier to view the animation in 2D instead. This can be accomplished with the animate function specifying dimension='2d' .

[6]:
%matplotlib agg
ani2d = mooring.graphics.animate(
    dsani,
    dimension="2d",
    xaxis="x",
    yaxis="z",
    repeat=True,
    xlabel="X-axis",
    ylabel="Depth [m]",
    title="Mooring Line Example",
)

HTML(ani2d.to_jshtml())
[6]:

Through these graphical representations, we can gain a more intuitive understanding of how the mooring line interacts with the surrounding marine environment over time.

Summary and Conclusion

In this notebook, we walked through the MHKiT Mooring module learning how to utilize MHKiT in conjunction with MoorDyn output to analyze the dynamics of a single mooring line.

We used the mooring.io.read_moordyn function to bring this data into an xarray Dataset, preparing it for further analysis. Next, we calculated the ‘lay length’ of our mooring line using the mooring.lay_length function, obtaining a DataArray representing the lay length at each time step. Finally, we visualized 2D and 3D animations of the mooring line’s behavior over a 10-second period using the mooring.graphics.animate function.

We hope that this example serves as a valuable guide to employing the MHKiT Mooring module and MoorDyn analyses.

Thank you for your interest in MHKiT! We encourage you to continue to open an issue or pull request if you have any feedback or expansions which would help you improve your mooring data analysis.