Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable WEC-Sim to use MoorDyn v2 capabilities #1212

Merged
merged 16 commits into from
May 29, 2024
56 changes: 40 additions & 16 deletions docs/_include/mooring.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ information about the mooring class code structure, refer to

Floating WEC systems are often connected to mooring lines to keep the device in
position. WEC-Sim allows the user to model the mooring dynamics in the
simulation by specifying the mooring matrix or coupling with MoorDyn. To
simulation by specifying the mooring matrix, a mooring lookup table, or coupling with MoorDyn. To
include mooring connections, the user can use the mooring block (i.e., Mooring
Matrix block or MoorDyn block) given in the WEC-Sim library under Moorings lib
and connect it between the body and the Global reference frame. Refer to the
:ref:`rm3_moordyn`, and the :ref:`webinar4` for more information.
Matrix block, Mooring Lookup Table block, or MoorDyn Connection block)
given in the WEC-Sim library under Moorings lib
and connect it between the body and the Global reference frame. The Moordyn Connection
block can also be placed between two dynamic bodies or frames. Refer to the
:ref:`rm3_moordyn`, and the :ref:`webinar8` for more information.

MoorDyn is hosted on a separate `MoorDyn repository <https://github.com/WEC-Sim/moorDyn>`_.
It must be download separately, and all files and folders should be placed in
Expand Down Expand Up @@ -92,17 +94,34 @@ The lookup table dataset should contain one structure that contains fields for e
MoorDyn
^^^^^^^

When the MoorDyn block is used, the user needs to initiate the mooring class by
When a MoorDyn block is used, the user first needs to initiate the mooring class by
setting :code:`mooring = mooringClass('mooring name')` in the WEC-Sim input
file (wecSimInputFile.m), followed by the number of mooring lines that are
defined in MoorDyn (``mooring(1).moorDynLines = <Number of mooring lines>``)

A mooring folder that includes a moorDyn input file (``lines.txt``) is required
in the simulation folder.
file (``wecSimInputFile.m``), followed by setting :code:`mooring(i).moorDyn = 1` to
initialize a MoorDyn connection. Each MoorDyn connection can consist of multiple
lines and each line may have multiple nodes. The number of MoorDyn lines and nodes in
each line should be defined as (``mooring(i).moorDynLines = <Number of mooring lines>``)
and (``mooring(i).moorDynNodes(iLine) = <Number of mooring nodes in line>`` - only used
for ParaView visualization), respectively and should match the number of lines and nodes
specified in the MoorDyn input file.

A mooring folder that includes a MoorDyn input file (``lines.txt``) is required
in the simulation folder. The body and corresponding mooring attachment points are
defined in the MoorDyn input file. The body location in the MoorDyn input file
should match that of the initial location of the body's center of gravity (usually
derived from BEM results). MoorDyn handles the kinematic transform to
convert the mooring forces from the attachment points to the 6 degree of freedom
force acting on the current location of the body's center of gravity. The initial
displacement of the mooring line in WEC-Sim (``mooring(i).initial.displacement``)
should match the location of the connected body in the MoorDyn input file or the
difference in location between two connected bodies. In the MoorDyn input file,
the location of points/nodes are specified relative to the body location if of
attachment type 'body#' and relative to the global frame for any other
attachement type.

.. Note::
WEC-Sim/MoorDyn coupling only allows one mooring configuration in the
simulation.
WEC-Sim/MoorDyn coupling now allows more than one mooring connnection (i.e.,
multiple MoorDyn Connection blocks) in the simulation, but there can only be
one call to MoorDyn (i.e., one MoorDyn Caller block).

.. _rm3_moordyn:

Expand All @@ -117,7 +136,8 @@ Applications <https://github.com/WEC-Sim/WEC-Sim_Applications>`_ repository.

* **WEC-Sim Simulink Model**: Start out by following the instructions on how to
model the :ref:`user-tutorials-rm3`. To couple WEC-Sim with MoorDyn, the
MoorDyn Block is added in parallel to the constraint block
MoorDyn Connection block is added in parallel to the constraint block and the
MoorDyn Caller block is added to the model (no connecting lines).

.. _WECSimmoorDyn:

Expand All @@ -126,7 +146,7 @@ Applications <https://github.com/WEC-Sim/WEC-Sim_Applications>`_ repository.
:align: center

* **WEC-Sim Input File**: In the ``wecSimInputFile.m`` file, the user needs to
initiate the mooring class and define the number of mooring lines.
initiate the mooring class and MoorDyn and define the number of mooring lines.

.. _WECSimInputMoorDyn:

Expand All @@ -135,8 +155,12 @@ Applications <https://github.com/WEC-Sim/WEC-Sim_Applications>`_ repository.

* **MoorDyn Input File**: A mooring folder that includes a moorDyn input file
(``lines.txt``) is created. The moorDyn input file (``lines.txt``) is shown
in the figure below. More details on how to setup the MooDyn input file are
described in the MoorDyn User Guide :cite:`Hall2015MoorDynGuide`.
in the figure below. More details on how to set up the MooDyn input file are
jtgrasb marked this conversation as resolved.
Show resolved Hide resolved
described in the `MoorDyn Documentation <https://moordyn.readthedocs.io/en/latest/>`_.
One specific requirement when using WEC-Sim with MoorDyn is that the Body(s) in which
the mooring lines are attached to should be labeled as "Coupled" in the MoorDyn input
file, which allows for WEC-Sim to control the body dynamics.
Note: WEC-Sim now uses MoorDyn v2.

.. _moorDynInput:

Expand Down
Binary file modified docs/_static/images/WEC-Sim_Lib_mooring.PNG
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/images/WECSimMoorDyn.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/images/moorDynInput.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 8 additions & 6 deletions docs/refs/WEC-Sim_Theory.bib
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,14 @@ @article{Hall2015ValidationData
publisher = {Elsevier},
}

@misc{Hall2015MoorDynGuide,
title = {MoorDyn User’s Guide},
year = {2015},
booktitle = {University of Maine},
author = {Hall, Matthew},
publisher = {University of Maine}
@inproceedings{hall2020moordyn,
title={Moordyn v2: New capabilities in mooring system components and load cases},
author={Hall, Matthew},
booktitle={International Conference on Offshore Mechanics and Arctic Engineering},
volume={84416},
pages={V009T09A078},
year={2020},
organization={American Society of Mechanical Engineers}
}

@article{Morison1950,
Expand Down
18 changes: 9 additions & 9 deletions docs/theory/theory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ Mooring

The mooring load is represented using a linear quasi-static mooring stiffness
or by using the mooring forces calculated from `MoorDyn
<http://www.matt-hall.ca/moordyn>`_ :cite:`Hall2015MoorDynGuide`, which is an
<http://www.matt-hall.ca/moordyn>`_, which is an
open-source lumped-mass mooring dynamics model.

Mooring Matrix
Expand Down Expand Up @@ -782,14 +782,14 @@ MoorDyn discretizes each mooring line in a mooring system into evenly-sized
line segments connected by node points (see :ref:`MoorDyn figure
<MoorDynFig>`). The line mass is lumped at these node points along with
gravitational and buoyancy forces, hydrodynamic loads, and reactions from
contact with the seabed. Hydrodynamic drag and added mass are calculated based
on Morison's equation. A mooring line's axial stiffness is modeled by applying
a linear stiffness to each line segment in tension only. A damping term is also
applied in each segment to dampen non-physical resonance caused by the
lumped-mass discretization. Bending and torsional stiffnesses are neglected.
Bottom contact is represented by vertical stiffness and damping forces applied
at the nodes when a node is located below the seabed.
:cite:`Hall2015ValidationData`.
contact with the seabed. Hydrodynamic drag and added mass
are calculated based on Morison's equation. A mooring line's axial stiffness
is modeled by applying a linear stiffness to each line segment in tension only.
A damping term is also applied in each segment to dampen non-physical resonance
caused by the lumped-mass discretization. Bending and torsional stiffnesses are
neglected. Bottom contact is represented by vertical stiffness and damping
forces applied at the nodes when a node is located below the seabed.
:cite:`Hall2015ValidationData,hall2020moordyn`.

.. _MoorDynFig:

Expand Down
28 changes: 21 additions & 7 deletions docs/user/code_structure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ Mooring Class

The mooring class (``mooringClass``) allows for different fidelity simulations
of mooring systems. Three possibilities are available, a lumped mooring matrix,
a mooring lookup table, or MoorDyn. These differences are determined by the Simulink block chosen, and are
a mooring lookup table, or MoorDyn. These differences are determined by the Simulink block(s) chosen, and are
described below. At a high level, the Mooring class interacts with the rest of
WEC-Sim as shown in the diagram below. The interaction is similar to a
constraint or PTO, where some resistive forcing is calculated and passed to a
Expand Down Expand Up @@ -733,18 +733,32 @@ Mooring Blocks
""""""""""""""""""""

The Mooring Class is tied to the Moorings library.
Three types of blocks may be used\: a 'Mooring Matrix', a 'MoorDyn' system, or a 'Mooring Lookup Table'.
Four types of blocks may be used\: a 'Mooring Matrix', a 'Mooring Lookup Table',
a 'MoorDyn Connection' block, or a 'MoorDyn Caller' block.
The ``MooringMatrix`` block applies linear damping and stiffness based on
the motion of the follower relative to the base.
Damping and stiffness can be specified between all DOFs in a 6x6 matrix.
The ``MooringLookupTable`` block searches a user-supplied 6DOF force lookup table.
The lookup table should contain six parameters: the resultant mooring force in each degree of freedom.
Each force is indexed by position in all six degrees of freedom.
The mooring force is interpolated between indexed positions based on the instantaneous position of the mooring system.
The ``MoorDyn`` block uses the compiled MoorDyn
executables and a MoorDyn input file to simulate a realistic mooring system.
There can only be one MoorDyn block per Simulink model. There are no
restrictions on the number of MooringMatrix or MooringLookupTable blocks.
There are no restrictions on the number of MooringMatrix or MooringLookupTable blocks.

The ``MoorDynConnection`` block is used to detect the relative motion between
two connection points (i.e., a body and the global reference frame or between
two bodies). The block uses Simulink's 'Goto' and 'From' blocks to feed the
relative response to the ``MoorDynCaller`` block, which then calls MoorDyn to
calculate the 6 degree of freedom mooring forces based on the instantaneous displacement,
velocity, a MoorDyn input file, and the compiled MoorDyn libraries to simulate a realistic
mooring system. The mooring forces are then sent back to the MoorDyn Connection
block to be applied at the body's center of gravity. Multiple MoorDyn Connection
blocks can be used to specify mooring lines between different bodies/frames,
but there can only be one MoorDyn Caller block per Simulink model. Each
MoorDyn Connection block should be initialized as a ``mooring`` object in
the ``wecSimInputFile.m`` with ``mooring(i).moorDyn`` set equal to 1. The
``MoorDynCaller`` block should not have an accompanying ``mooring`` object.
If set up correctly in the ``wecSimInputFile.m``, the signals will be
automatically sent between the MoorDyn Connection and MoorDyn Caller blocks.

.. figure:: /_static/images/WEC-Sim_Lib_mooring.PNG
:width: 400 pt
Expand Down Expand Up @@ -862,7 +876,7 @@ While the bulk of the WEC-Sim code consists of the WEC-Sim classes and the
WEC-Sim library, the source code also includes supporting functions and
external codes. These include third party Matlab functions to read ``*.h5`` and
``*.stl`` files, WEC-Sim Matlab functions to write ``*.h5`` files and run
WEC-Sim in batch mode, MoorDyn compiled executables, python macros for ParaView
WEC-Sim in batch mode, MoorDyn compiled libraries, python macros for ParaView
visualization, and the PTO-Sim class and library. Additionally, BEMIO can be
used to create the hydrodynamic ``*.h5`` file required by WEC-Sim. MoorDyn is
an open source code that must be downloaded separately. Users may also obtain,
Expand Down
5 changes: 5 additions & 0 deletions docs/user/webinars.rst
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ available below.

<iframe width="560" height="315" src="https://www.youtube.com/embed/rqUVK9dCsU0?si=pEKY0jXbKIU7bngl" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

.. Note::
The above MoorDyn webinar is based on MoorDyn v1 and is in the process of being updated
for MoorDyn v2. Please refer to :ref:`user-advanced-features-mooring` for instruction on
using WEC-Sim with MoorDyn v2.


.. _webinar9:

Expand Down
7 changes: 7 additions & 0 deletions source/functions/initializeWecSim.m
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,14 @@
if mooring(ii).lookupTableFlag == 1
mooring(ii).loadLookupTable();
end
if mooring(ii).moorDyn == 1
simu.numMoorDyn = simu.numMoorDyn+1;
end
end; clear ii
% Initialize MoorDyn
if simu.numMoorDyn > 0
mooring.callMoorDynLib();
end
end


Expand Down
6 changes: 0 additions & 6 deletions source/functions/postProcessWecSim.m
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,6 @@
% MoorDyn
for iMoor = 1:simu.numMoorings
if mooring(iMoor).moorDyn==1
% Ensure that Lines library is closed before reading MoorDyn output
if libisloaded('libmoordyn')
calllib('libmoordyn','MoorDynClose');
unloadlibrary libmoordyn;
end

output.loadMoorDyn(mooring(iMoor).moorDynLines);
end
end; clear iMoor
Expand Down
2 changes: 1 addition & 1 deletion source/functions/simulink/model/MoorDyn_matlab_FCN.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function FLines = MoorDyn_matlab_FCN(X,XD,Time,CoupTime)

FLines = zeros(1,6);
FLines = zeros(1,length(X));
coder.extrinsic('MoorDyn_caller');

FLines = MoorDyn_caller(X,XD,Time-CoupTime,CoupTime);
Expand Down
6 changes: 6 additions & 0 deletions source/functions/stopWecSim.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
cd (['..' filesep pctDir filesep '..' filesep]);
end

% Close MoorDyn if used
if simu.numMoorDyn > 0
% Close MoorDyn
mooring.closeMoorDynLib();
end

% Clear intermediate variables and variant subsystem flags
clear nonlinearHydro sv_linearHydro sv_nonlinearHydro stateSpace radiation_option sv_convolution sv_stateSpace sv_constantCoeff typeNum B2B sv_B2B sv_noB2B;
clear nhbod* sv_b* sv_noWave sv_regularWaves* sv_irregularWaves* sv_udfWaves sv_instFS sv_meanFS sv_MEOn sv_MEOff morisonElement flexHydrobody_* sv_irregularWavesYaw_* sv_regularWavesYaw_* yaw numBody;
Expand Down
Binary file modified source/lib/WEC-Sim/WECSim_Lib_Moorings.slx
Binary file not shown.
43 changes: 40 additions & 3 deletions source/objects/mooringClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
'damping', zeros(6,6), ... %
'stiffness', zeros(6,6), ... %
'preTension', [0 0 0 0 0 0]) % (`structure`) Defines the mooring parameters. ``damping`` (`6x6 float matrix`) Matrix of damping coefficients, Default = ``zeros(6)``. ``stiffness`` (`6x6 float matrix`) Matrix of stiffness coefficients, Default = ``zeros(6)``. ``preTension`` (`1x6 float vector`) Array of pretension force in each dof, Default = ``[0 0 0 0 0 0]``.
moorDyn (1,1) {mustBeInteger} = 0 % (`integer`) Flag to indicate a MoorDyn block, 0 or 1. Default = ``0``
moorDyn (1,1) {mustBeInteger} = 0 % (`integer`) Flag to indicate and initialize a MoorDyn connection, 0 or 1. Default = ``0``
moorDynLines (1,1) {mustBeInteger, mustBeNonnegative} = 0 % (`integer`) Number of lines in MoorDyn. Default = ``0``
moorDynNodes (1,:) {mustBeInteger, mustBeNonnegative} = [] % (`integer`) number of nodes for each line. Default = ``'NOT DEFINED'``
name (1,:) {mustBeText} = 'NOT DEFINED' % (`string`) Name of the mooring. Default = ``'NOT DEFINED'``
Expand All @@ -58,7 +58,7 @@
if exist('name','var')
obj.name = name;
else
error('The mooring class number(s) in the wecSimInputFile must be specified in ascending order starting from 1. The mooringClass() function should be called first to initialize each mooring line with a name.')
error('The mooring class number(s) in the wecSimInputFile must be specified in ascending order starting from 1. The mooringClass() function should be called first to initialize each mooring connection with a name.')
end
end

Expand Down Expand Up @@ -161,13 +161,50 @@ function listInfo(obj)
end

function obj = setLoc(obj)
% This method sets mooring location
% This method sets MoorDyn initial orientation
obj.orientation = [obj.location + obj.initial.displacement 0 0 0];
end

function setNumber(obj,number)
% Method to set the private number property
obj.number = number;
end

function callMoorDynLib(obj)
% Initialize MoorDyn Lib (Windows:dll or OSX:dylib)
disp('---------------Starting MoorDyn-----------')

if libisloaded('libmoordyn')
calllib('libmoordyn', 'MoorDynClose');
unloadlibrary libmoordyn;
end

if ismac
loadlibrary('libmoordyn.dylib','MoorDyn.h');
elseif ispc
loadlibrary('libmoordyn.dll','MoorDyn.h');
elseif isunix
loadlibrary('libmoordyn.so','MoorDyn.h');
else
disp('Cannot run MoorDyn in this platform');
end

orientationTotal = [];
for ii=1:length(obj)
if obj(ii).moorDyn == 1
orientationTotal = [orientationTotal, obj(ii).orientation];
end
end

calllib('libmoordyn', 'MoorDynInit', orientationTotal, zeros(1,length(orientationTotal)), obj(1).moorDynInputFile);
disp('MoorDyn Initialized. Now time stepping...')
end

function closeMoorDynLib(obj)
% Close MoorDyn Lib
calllib('libmoordyn', 'MoorDynClose');
unloadlibrary libmoordyn;
end

end
end
3 changes: 3 additions & 0 deletions source/objects/responseClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@
if isstruct(mooringOutput)
signals = {'position','velocity','forceMooring'};
for ii = 1:length(mooringOutput)
if length(size(mooringOutput(ii).signals.values)) == 3 % reformat mooring output if necessary
mooringOutput(ii).signals.values = squeeze(mooringOutput(ii).signals.values)';
end
obj.mooring(ii).name = mooringOutput(ii).name;
obj.mooring(ii).time = mooringOutput(ii).time;
for jj = 1:length(signals)
Expand Down
1 change: 1 addition & 0 deletions source/objects/simulationClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
numConstraints = 0 % (`integer`) Number of contraints in the wec model. Default = ``0``
numDragBodies = 0 % (`integer`) Number of drag bodies that comprise the WEC device (excluding hydrodynamic bodies). Default = ``0``
numHydroBodies = 0 % (`integer`) Number of hydrodynamic bodies that comprise the WEC device. Default = ``0``
numMoorDyn = 0 % (`integer`) Number of moordyn blocks systems in the wec model. Default = ``0``
numMoorings = 0 % (`integer`) Number of moorings in the wec model. Default = ``0``
numPtos = 0 % (`integer`) Number of power take-off elements in the model. Default = ``0``
numPtoSim = 0 % (`integer`) Number of PTO-Sim elements in the model. Default = ``0``
Expand Down