Skip to content

Commit

Permalink
Merge pull request #1727 from RyanDavies19/main
Browse files Browse the repository at this point in the history
MoorDyn updates and bug fixes
  • Loading branch information
andrew-platt authored Oct 2, 2023
2 parents efead48 + c9567fe commit 7d09eb9
Show file tree
Hide file tree
Showing 14 changed files with 1,103 additions and 915 deletions.
9 changes: 5 additions & 4 deletions docs/source/user/moordyn/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
MoorDyn Users Guide
====================

A standalone C++ version of MoorDyn is also available outside the OpenFAST
repository. The documentation for the C++ version covers the input file format
(`MoorDyn usage <https://moordyn.readthedocs.io/en/latest/usage.html>`_, specifically the section for V2)
The documentation for MoorDyn is avaible `here <https://moordyn.readthedocs.io>`_. It features instructions
for the use of MoorDynF, the module in OpenFAST, and MoorDynC, the standalone C++ code. Input file formats
are described in the `inputs section <>`_.
(`MoorDyn usage <https://moordyn.readthedocs.io/en/latest/inputs.html>`_, specifically the section for V2)
usage of MoorDyn at the FAST.Farm level
(`MoorDyn with FAST.Farm <https://moordyn.readthedocs.io/en/latest/usage.html#moordyn-with-fast-farm>`_),
(`MoorDyn with FAST.Farm <https://moordyn.readthedocs.io/en/latest/inputs.html#moordyn-with-fast-farm-inputs>`_),
and links to publications with the relevant theory.

2 changes: 1 addition & 1 deletion glue-codes/fast-farm/src/FAST_Farm_Subs.f90
Original file line number Diff line number Diff line change
Expand Up @@ -2006,7 +2006,7 @@ subroutine FARM_MD_Increment(t, n, farm, ErrStat, ErrMsg)
! ----- map MD load outputs to each turbine's substructure ----- (taken from U FullOpt1...)
do nt = 1,farm%p%NumTurbines

if (farm%MD%p%nCpldCons(nt) > 0 ) then ! only map loads if MoorDyn has connections to this turbine (currently considering only Point connections <<< )
if (farm%MD%p%nCpldPoints(nt) > 0 ) then ! only map loads if MoorDyn has connections to this turbine (currently considering only Point connections <<< )

! copy the MD output mesh for this turbine into a copy mesh within the FAST instance
!CALL MeshCopy ( farm%MD%y%CoupledLoads(nt), farm%FWrap(nt)%m%Turbine%MeshMapData%u_FarmMD_CoupledLoads, MESH_NEWCOPY, ErrStat2, ErrMsg2 )
Expand Down
8 changes: 3 additions & 5 deletions modules/moordyn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ The Fortran implementation of MoorDyn, which has been developed
following the FAST Modularization Framework, is included as a module in
OpenFAST.

For the C++ implementation of MoorDyn, see http://www.matt-hall.ca/moordyn.
"MoorDyn C" can be compiled as a dynamically-linked library and features
simpler functions for easy coupling with models or scripts coded in C/C++,
Fortran, Matlab/Simulink, etc. It has recently been integrated into WEC-Sim.
For the C++ implementation of MoorDyn, see https://github.com/FloatingArrayDesign/MoorDyn.
"MoorDynC" is more adaptable to unique use cases and couplings. It can be compiled as a dynamically-linked library or wrapped for use in Python (as a module), Fortran, and Matlab. It features simpler functions for easy coupling with models or scripts coded in C/C++, Fortran, Matlab/Simulink, etc. An example of this coupling is it’s integration into WEC-Sim.

Both forms of MoorDyn feature the same underlying mooring model, use similar
Both forms of MoorDyn feature the same underlying mooring model, use the same
input and output conventions, and are being updated and improved in parallel.
They follow the same version numbering, with a "C" or "F" suffix for
differentiation.
369 changes: 188 additions & 181 deletions modules/moordyn/src/MoorDyn.f90

Large diffs are not rendered by default.

65 changes: 33 additions & 32 deletions modules/moordyn/src/MoorDyn_Body.f90
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ MODULE MoorDyn_Body
USE NWTC_Library
USE MoorDyn_Misc
!USE MoorDyn_Line, only : Line_SetEndKinematics, Line_GetEndStuff
USE MoorDyn_Point, only : Connect_SetKinematics, Connect_GetNetForceAndMass
USE MoorDyn_Point, only : Point_SetKinematics, Point_GetNetForceAndMass
USE MoorDyn_Rod, only : Rod_Initialize, Rod_SetKinematics, Rod_GetNetForceAndMass

IMPLICIT NONE
Expand All @@ -43,7 +43,7 @@ MODULE MoorDyn_Body
PUBLIC :: Body_GetStateDeriv
PUBLIC :: Body_DoRHS
PUBLIC :: Body_GetCoupledForce
PUBLIC :: Body_AddConnect
PUBLIC :: Body_AddPoint
PUBLIC :: Body_AddRod


Expand Down Expand Up @@ -81,12 +81,13 @@ SUBROUTINE Body_Setup( Body, tempArray, p, ErrStat, ErrMsg)
CALL TranslateMass6to6DOF(Body%rCG, Mtemp, Body%M0) ! account for potential CG offset <<< is the direction right? <<<

DO J=1,3
Body%M0(J,J) = Body%M0(J,J) + Body%BodyV*Body%BodyCa(J) ! add added mass in each direction about ref point (so only diagonals) <<< eventually expand to multi D
Body%M0(J,J) = Body%M0(J,J) + Body%BodyV*Body%BodyCa(J)* p%rhow ! add added mass in each direction about ref point (so only diagonals) <<< eventually expand to multi D
END DO

! --------------- if this is an independent body (not coupled) ----------
! set initial position and orientation of body from input file
Body%r6 = tempArray
Body%r6(1:3) = tempArray(1:3)
Body%r6(4:6) = tempArray(4:6) * (pi/180)

! calculate orientation matrix based on latest angles
!RotMat(r6[3], r6[4], r6[5], OrMat);
Expand Down Expand Up @@ -134,7 +135,7 @@ END SUBROUTINE Body_Setup
! if (m%RodList(Body%attachedR(l))%typeNum == 2) CALL Rod_Initialize(m%RodList(Body%attachedR(l)), dummyStates, m%LineList)
! END DO
!
! ! Note: Connections don't need any initialization
! ! Note: Points don't need any initialization
!
! END SUBROUTINE Body_InitializeUnfree
! !--------------------------------------------------------------
Expand All @@ -157,15 +158,15 @@ SUBROUTINE Body_Initialize(Body, states, m)
states(1:6 ) = Body%v6


! set positions of any dependent connections and rods now (before they are initialized)
! set positions of any dependent points and rods now (before they are initialized)
CALL Body_SetDependentKin(Body, 0.0_DbKi, m)

! If any Rod is fixed to the body (not pinned), initialize it now because otherwise it won't be initialized
DO l=1, Body%nAttachedR
if (m%RodList(Body%attachedR(l))%typeNum == 2) CALL Rod_Initialize(m%RodList(Body%attachedR(l)), dummyStates, m)
END DO

! Note: Connections don't need any initialization
! Note: Points don't need any initialization

END SUBROUTINE Body_Initialize
!--------------------------------------------------------------
Expand All @@ -181,15 +182,15 @@ SUBROUTINE Body_InitializeUnfree(Body, m)
REAL(DbKi) :: dummyStates(12) ! dummy vector to mimic states when initializing a rigidly attached rod


! set positions of any dependent connections and rods now (before they are initialized)
! set positions of any dependent points and rods now (before they are initialized)
CALL Body_SetDependentKin(Body, 0.0_DbKi, m)

! If any Rod is fixed to the body (not pinned), initialize it now because otherwise it won't be initialized
DO l=1, Body%nAttachedR
if (m%RodList(Body%attachedR(l))%typeNum == 2) CALL Rod_Initialize(m%RodList(Body%attachedR(l)), dummyStates, m)
END DO

! Note: Connections don't need any initialization
! Note: Points don't need any initialization

END SUBROUTINE Body_InitializeUnfree
!--------------------------------------------------------------
Expand All @@ -206,7 +207,7 @@ SUBROUTINE Body_SetKinematics(Body, r_in, v_in, a_in, t, m)
Real(DbKi), INTENT(IN ) :: v_in(6) ! 6-DOF velocity
Real(DbKi), INTENT(IN ) :: a_in(6) ! 6-DOF acceleration (only used for coupled rods)
Real(DbKi), INTENT(IN ) :: t ! instantaneous time
TYPE(MD_MiscVarType), INTENT(INOUT) :: m ! passing along all mooring objects (for simplicity, since Bodies deal with Rods and Connections)
TYPE(MD_MiscVarType), INTENT(INOUT) :: m ! passing along all mooring objects (for simplicity, since Bodies deal with Rods and Points)


INTEGER(IntKi) :: l
Expand Down Expand Up @@ -259,26 +260,26 @@ SUBROUTINE Body_SetState(Body, X, t, m)
Body%v6 = X(1:6) ! get velocities


! set positions of any dependent connections and rods
! set positions of any dependent points and rods
CALL Body_SetDependentKin(Body, t, m)

END SUBROUTINE Body_SetState
!--------------------------------------------------------------


! set the states (positions and velocities) of any connects or rods that are part of this body
! set the states (positions and velocities) of any points or rods that are part of this body
! also computes the orientation matrix (never skip this sub!)
!--------------------------------------------------------------
SUBROUTINE Body_SetDependentKin(Body, t, m)

Type(MD_Body), INTENT(INOUT) :: Body ! the Bodyion object
REAL(DbKi), INTENT(IN ) :: t
TYPE(MD_MiscVarType), INTENT(INOUT) :: m ! passing along all mooring objects (for simplicity, since Bodies deal with Rods and Connections)
TYPE(MD_MiscVarType), INTENT(INOUT) :: m ! passing along all mooring objects (for simplicity, since Bodies deal with Rods and Points)

INTEGER(IntKi) :: l ! index of attached objects

Real(DbKi) :: rConnect(3)
Real(DbKi) :: rdConnect(3)
Real(DbKi) :: rPoint(3)
Real(DbKi) :: rdPoint(3)
Real(DbKi) :: rRod(6)
Real(DbKi) :: vRod(6)
Real(DbKi) :: aRod(6)
Expand All @@ -289,15 +290,15 @@ SUBROUTINE Body_SetDependentKin(Body, t, m)
!CALL SmllRotTrans('', Body%r6(4), Body%r6(5), Body%r6(6), Body%TransMat, '', ErrStat2, ErrMsg2)
Body%OrMat = TRANSPOSE( EulerConstruct( Body%r6(4:6) ) ) ! full Euler angle approach <<<< need to check order

! set kinematics of any dependent connections
! set kinematics of any dependent points
do l = 1,Body%nAttachedC

CALL transformKinematics(Body%rConnectRel(:,l), Body%r6, Body%OrMat, Body%v6, rConnect, rdConnect) !<<< should double check this function
CALL transformKinematics(Body%rPointRel(:,l), Body%r6, Body%OrMat, Body%v6, rPoint, rdPoint) !<<< should double check this function

! >>> need to add acceleration terms here too? <<<

! pass above to the connection and get it to calculate the forces
CALL Connect_SetKinematics( m%ConnectList(Body%attachedC(l)), rConnect, rdConnect, m%zeros6(1:3), t, m)
! pass above to the point and get it to calculate the forces
CALL Point_SetKinematics( m%PointList(Body%attachedC(l)), rPoint, rdPoint, m%zeros6(1:3), t, m)
end do

! set kinematics of any dependent Rods
Expand Down Expand Up @@ -424,11 +425,11 @@ SUBROUTINE Body_DoRHS(Body, m, p)



! Get contributions from any dependent connections
! Get contributions from any dependent points
do l = 1,Body%nAttachedC

! get net force and mass from Connection on body ref point (global orientation)
CALL Connect_GetNetForceAndMass( m%ConnectList(Body%attachedC(l)), Body%r6(1:3), F6_i, M6_i, m, p)
! get net force and mass from Point on body ref point (global orientation)
CALL Point_GetNetForceAndMass( m%PointList(Body%attachedC(l)), Body%r6(1:3), F6_i, M6_i, m, p)

if (ABS(F6_i(5)) > 1.0E12) then
print *, "Warning: extreme pitch moment from body-attached Point ", l
Expand Down Expand Up @@ -488,33 +489,33 @@ END SUBROUTINE Body_GetCoupledForce



! this function handles assigning a connection to a body
! this function handles assigning a point to a body
!--------------------------------------------------------------
SUBROUTINE Body_AddConnect(Body, connectID, coords)
SUBROUTINE Body_AddPoint(Body, pointID, coords)

Type(MD_Body), INTENT(INOUT) :: Body ! the Connection object
Integer(IntKi), INTENT(IN ) :: connectID
Type(MD_Body), INTENT(INOUT) :: Body ! the Point object
Integer(IntKi), INTENT(IN ) :: pointID
REAL(DbKi), INTENT(IN ) :: coords(3)


IF (wordy > 0) Print*, "C", connectID, "->B", Body%IdNum
IF (wordy > 0) Print*, "P", pointID, "->B", Body%IdNum

IF(Body%nAttachedC < 30) THEN ! this is currently just a maximum imposed by a fixed array size. could be improved.
Body%nAttachedC = Body%nAttachedC + 1 ! increment the number connected
Body%AttachedC(Body%nAttachedC) = connectID
Body%rConnectRel(:,Body%nAttachedC) = coords ! store relative position of connect on body
Body%nAttachedC = Body%nAttachedC + 1 ! increment the number pointed
Body%AttachedC(Body%nAttachedC) = pointID
Body%rPointRel(:,Body%nAttachedC) = coords ! store relative position of point on body
ELSE
Print*, "too many Points attached to Body ", Body%IdNum, " in MoorDyn!"
END IF

END SUBROUTINE Body_AddConnect
END SUBROUTINE Body_AddPoint


! this function handles assigning a rod to a body
!--------------------------------------------------------------
SUBROUTINE Body_AddRod(Body, rodID, coords)

Type(MD_Body), INTENT(INOUT) :: Body ! the Connection object
Type(MD_Body), INTENT(INOUT) :: Body ! the Point object
Integer(IntKi), INTENT(IN ) :: rodID
REAL(DbKi), INTENT(IN ) :: coords(6) ! positions of rod ends A and B relative to body

Expand Down
6 changes: 3 additions & 3 deletions modules/moordyn/src/MoorDyn_Driver.f90
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ PROGRAM MoorDyn_Driver
endif

do iTurb = 1, MD_p%nTurbines
ncIn = ncIn + MD_p%nCpldBodies(iTurb)*6 + MD_p%nCpldRods(iTurb)*6 + MD_p%nCpldCons(iTurb)*3
ncIn = ncIn + MD_p%nCpldBodies(iTurb)*6 + MD_p%nCpldRods(iTurb)*6 + MD_p%nCpldPoints(iTurb)*3
end do

call WrScr('MoorDyn has '//trim(num2lstr(ncIn))//' coupled DOFs and/or active-tensioned inputs.')
Expand Down Expand Up @@ -519,7 +519,7 @@ PROGRAM MoorDyn_Driver
END DO

! any coupled points (type -1)
DO l = 1, MD_p%nCpldCons(iTurb)
DO l = 1, MD_p%nCpldPoints(iTurb)

MD_u(1)%CoupledKinematics(iTurb)%TranslationDisp(:,K) = r_in(i, J:J+2) - MD_u(1)%CoupledKinematics(iTurb)%Position(:,K) - MD_p%TurbineRefPos(:,iTurb)
MD_u(1)%CoupledKinematics(iTurb)%TranslationVel( :,K) = rd_in(i, J:J+2)
Expand Down Expand Up @@ -608,7 +608,7 @@ PROGRAM MoorDyn_Driver
END DO

! any coupled points (type -1)
DO l = 1, MD_p%nCpldCons(iTurb)
DO l = 1, MD_p%nCpldPoints(iTurb)

MD_u(1)%CoupledKinematics(iTurb)%TranslationDisp(:,K) = r_in(i, J:J+2) - MD_u(1)%CoupledKinematics(iTurb)%Position(:,K) - MD_p%TurbineRefPos(:,iTurb)
MD_u(1)%CoupledKinematics(iTurb)%TranslationVel( :,K) = rd_in(i, J:J+2)
Expand Down
Loading

0 comments on commit 7d09eb9

Please sign in to comment.