diff --git a/docs/OtherSupporting/OutListParameters.xlsx b/docs/OtherSupporting/OutListParameters.xlsx index 4bdee3aa4..b99ef9de9 100644 Binary files a/docs/OtherSupporting/OutListParameters.xlsx and b/docs/OtherSupporting/OutListParameters.xlsx differ diff --git a/docs/source/user/hydrodyn/input_files.rst b/docs/source/user/hydrodyn/input_files.rst index aea6e67ff..e3e533663 100644 --- a/docs/source/user/hydrodyn/input_files.rst +++ b/docs/source/user/hydrodyn/input_files.rst @@ -898,9 +898,12 @@ specified in the HYDRODYN section of the driver input file when running HydroDyn standalone, or by the OpenFAST program when running a coupled simulation. See :numref:`hd-summary-file` for summary file details. -For this version, **OutAll** must be set to FALSE. In future versions, -setting **OutAll** = TRUE will cause HydroDyn to auto-generate outputs -for every joint and member in the input file. +If **OutAll** is set to TRUE, HydroDyn will output the total strip-theory +forces and moments on each user-defined member and joint, followed by the +forces and moments on each computational node of the strip-theory mesh. +These additional output channels are inserted as additional columns in the +output file independent of any user-requested outputs. See :ref:`hd-outall-option` +for more information. If **OutSwtch** is set to 1, outputs are sent to a file with the name ``OutRootname.HD.out``. If **OutSwtch** is set to 2, outputs are diff --git a/docs/source/user/hydrodyn/output_files.rst b/docs/source/user/hydrodyn/output_files.rst index c3212f62c..13791713a 100644 --- a/docs/source/user/hydrodyn/output_files.rst +++ b/docs/source/user/hydrodyn/output_files.rst @@ -166,6 +166,59 @@ data for a single 6\ **NBody**-by-6\ **NBody** matrix. If **NBodyMod** > 1 (no hydrodynamic coupling), the summary file will contain data for **NBody** 6-by-6 radiation kernal matrices. +.. _hd-outall-option: + +**OutAll** Option +~~~~~~~~~~~~~~~~~ + +If **OutAll** is set to TRUE, HydroDyn will output the total strip-theory +forces and moments on each user-defined member and joint. These are +included as additional columns in the output file independent of any +user-requested outputs. The forces and moments on the members (integrated loads across +all side walls) will be written first. For example, the 6 load components +on the first member in the **MEMBERS** table (the first row of the table) +are given by **M1TotFxi**, **M1TotFyi**, **M1TotFzi**, **M1TotMxi**, +**M1TotMyi**, and **M1TotMzi**. After the member loads, the total lumped +loads on each joint are printed next. For instance, the loads on the first +joint in the **MEMBER JOINTS** table are printed with the column names +**J1TotFxi**, **J1TotFyi**, **J1TotFzi**, **J1TotMxi**, **J1TotMyi**, and +**J1TotMzi**. Note that for these outputs, the members and joints are +simply numbered based on their order of appearance in the respective tables +in the input file, so, as an example, **J2** refers to the joint defined +on the second row of the **MEMBER JOINTS** table. The member and joint +numbering does not follow **MemberID** and **JointID**, nor does it follow +the numbering used with the user-requested member and joint outputs. + +The output forces and moments are the total strip-theory loads, including +hydrodynamic, hydrostatic, marine growth, and ballast contributions. If a +member has **PropPot** set to TRUE, the relevant load components will be +omitted for that member and its connecting joints as appropriate. All +force and moment components are resolved in the earth-fixed inertial frame +of reference, and the moments are computed about the instantaneous principal +reference point (PRP), same as the output channels **HydroFxi**, +**HydroFyi**, etc. As a reminder, the PRP is a body-fixed point located at +the earth-fixed origin when the HydroDyn structure is undisplaced. Summing +all member and joint loads gives the total strip-theory loads on the entire +structure. + +After the member and joint loads, HydroDyn also outputs the total forces +and moments on each computational node of the HydroDyn strip-theory (Morison) +mesh. This internal mesh is used to map the loads to other structural +modules, such as SubDyn, and contains joint nodes at the user-defined joint +locations followed by member internal nodes created from member discretization. +The force and moment components are again resolved in the earth-fixed inertial +frame of reference. However, the moment on each node is about the node itself, +not about the PRP as with the member and joint load outputs above. Additionally, +the joint mesh nodes can have load contributions from both member side walls +and from the joint/endplates. This is because part of the side-wall loads on +the first and last element of a member can be assignd to the joint nodes. As +a result, the load outputs at the joint nodes do not necessarily match the joint +load outputs above, which do not contain contributions from member side walls. +The nodal load output column names indicate the node number, e.g., **N1TotFxi**, +**N1TotFyi**, **N1TotFzi**, **N1TotMxi**, **N1TotMyi**, and **N1TotMzi** for +the first node. The node numbering follows the **Nodes** table in the HydroDyn +summary file. + Results File ~~~~~~~~~~~~ diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90 index 2fe891c0d..0420ca923 100644 --- a/modules/hydrodyn/src/HydroDyn.f90 +++ b/modules/hydrodyn/src/HydroDyn.f90 @@ -584,7 +584,9 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I ! Were visualization meshes requested? InputFileData%Morison%VisMeshes = p%VisMeshes - + ! Additional Morison inputs to be initialized just in case + u%Morison%PtfmRefY = 0.0_ReKi + u%Morison%PRP = [0.0_ReKi,0.0_ReKi,0.0_ReKi] ! Initialize the Morison Element Calculations CALL Morison_Init(InputFileData%Morison, u%Morison, p%Morison, x%Morison, xd%Morison, z%Morison, OtherState%Morison, & y%Morison, m%Morison, Interval, InitOut%Morison, ErrStat2, ErrMsg2 ) @@ -1204,14 +1206,11 @@ SUBROUTINE HydroDyn_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherSt DO i=1,nTime CALL Morison_CopyInput(Inputs(i)%Morison, Inputs_Morison(i), MESH_NEWCOPY, ErrStat2, ErrMsg2) call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - ! Inputs_Morison(i)%PtfmRefY = Inputs(i)%PtfmRefY Inputs_Morison(i)%PtfmRefY = xd%PtfmRefY(i) + Inputs_Morison(i)%PRP = Inputs(i)%PRPMesh%Position(:,1) + Inputs(i)%PRPMesh%TranslationDisp(:,1) END DO CALL Morison_CopyInput(Inputs(1)%Morison, u_Morison, MESH_NEWCOPY, ErrStat2, ErrMsg2) call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - ! u_Morison%PtfmRefY = Inputs(1)%PtfmRefY - u_Morison%PtfmRefY = xd%PtfmRefY(1) - CALL Morison_Input_ExtrapInterp(Inputs_Morison, InputTimes, u_Morison, t, ErrStat2, ErrMsg2) ! get inputs at time t call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) @@ -1762,6 +1761,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, IF ( u%Morison%Mesh%Committed ) THEN ! Make sure we are using Morison / there is a valid mesh u%Morison%PtfmRefY = PtfmRefY + u%Morison%PRP = u%PRPMesh%Position(:,1)+u%PRPMesh%TranslationDisp(:,1) CALL Morison_CalcOutput( Time, u%Morison, p%Morison, x%Morison, xd%Morison, & z%Morison, OtherState%Morison, y%Morison, m%Morison, & ErrStat2, ErrMsg2, calcMorisonHstLdsLocal ) @@ -1777,9 +1777,9 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat, if (Failed()) return ! Aggregate the sub-module outputs - IF (p%Morison%NumOuts > 0) THEN + IF (p%Morison%NumOuts > 0 .or. p%Morison%OutAll) THEN J = p%NumOuts + 1 - DO I=1, p%Morison%NumOuts + DO I=1, size(p%Morison%OutParam) y%WriteOutput(J) = y%Morison%WriteOutput(I) J = J + 1 END DO diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt index 647e5fa2f..76191e922 100644 --- a/modules/hydrodyn/src/HydroDyn.txt +++ b/modules/hydrodyn/src/HydroDyn.txt @@ -63,7 +63,6 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER NUserOutputs - - - "Number of Hydrodyn-level requested output channels" - typedef ^ ^ CHARACTER(ChanLen) UserOutputs {:} - - "This should really be dimensioned with MaxOutPts" - typedef ^ ^ INTEGER OutSwtch - - - "Output requested channels to: [1=Hydrodyn.out 2=GlueCode.out 3=both files]" - -typedef ^ ^ LOGICAL OutAll - - - "Output all user-specified member and joint loads (only at each member end, not interior locations) [T/F]" - typedef ^ ^ INTEGER NumOuts - - - "The number of outputs for this module as requested in the input file" - typedef ^ ^ CHARACTER(ChanLen) OutList {:} - - "The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts" - typedef ^ ^ LOGICAL HDSum - - - "Generate a HydroDyn summary file [T/F]" - diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index d46b2d3ef..f8bd455f8 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -1222,7 +1222,7 @@ SUBROUTINE HydroDyn_ParseInput( InputFileName, OutRootName, FileInfo_In, InputFi if (Failed()) return; ! OutAll - Whether or not to output information for every member and joint - call ParseVar( FileInfo_In, CurLine, 'OutAll', InputFileData%OutAll, ErrStat2, ErrMsg2, UnEc ) + call ParseVar( FileInfo_In, CurLine, 'OutAll', InputFileData%Morison%OutAll, ErrStat2, ErrMsg2, UnEc ) if (Failed()) return; ! OutSwtch - Specify how to write to an output file @@ -2804,15 +2804,6 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, Interval, InputFileData, ErrS ! Data section for OUTPUT !------------------------------------------------------------------------------------------------- - - ! OutAll - output all member and joint data - - IF ( InputFileData%OutAll ) THEN !TODO: Alter this check once OutAll is supported - CALL SetErrStat( ErrID_Fatal,'OutAll must be FALSE. Future versions of HydroDyn will once again support values of either TRUE or FALSE.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - - ! OutSwtch - output file switch IF ( InputFileData%OutSwtch /= 1 .AND. InputFileData%OutSwtch /= 2 .AND. InputFileData%OutSwtch /= 3 ) THEN diff --git a/modules/hydrodyn/src/HydroDyn_Output.f90 b/modules/hydrodyn/src/HydroDyn_Output.f90 index aab5dab29..53301598d 100644 --- a/modules/hydrodyn/src/HydroDyn_Output.f90 +++ b/modules/hydrodyn/src/HydroDyn_Output.f90 @@ -8887,9 +8887,9 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, OutRootName, InputFileData, y, p, m, p%OutDec = 1 !TODO: Remove this once the parameter has been added to the HD input file GJH 7/8/2014 - IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN + IF (ALLOCATED( p%Morison%OutParam ) .AND. (p%Morison%NumOuts > 0 .OR. p%Morison%OutAll)) THEN hasMorisonOuts = .TRUE. - p%NumTotalOuts = p%NumTotalOuts + p%Morison%NumOuts + p%NumTotalOuts = p%NumTotalOuts + size(p%Morison%OutParam) END IF ! Allocate the aggregate arrays @@ -8929,7 +8929,7 @@ SUBROUTINE HDOUT_Init( HydroDyn_ProgDesc, OutRootName, InputFileData, y, p, m, J = p%NumOuts + 1 IF ( hasMorisonOuts ) THEN - DO I=1, p%Morison%NumOuts + DO I=1, size(p%Morison%OutParam) InitOut%WriteOutputHdr(J) = InitOut%Morison%WriteOutputHdr(I) InitOut%WriteOutputUnt(J) = InitOut%Morison%WriteOutputUnt(I) J = J + 1 @@ -8982,7 +8982,7 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta !------------------------------------------------------------------------------------------------- p%UnOutFile = -1 IF ( (ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) .OR. & - (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0 ) ) THEN ! Output has been requested so let's open an output file + (ALLOCATED( p%Morison%OutParam ) .AND. (p%Morison%NumOuts > 0 .OR. p%Morison%OutAll) ) ) THEN ! Output has been requested so let's open an output file ! Open the file for output OutFileName = TRIM(OutRootName)//'.out' @@ -9013,9 +9013,9 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputHdr(I) ), I=1,p%NumOuts ) END IF - IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN - Frmt = '('//TRIM(Int2LStr(p%Morison%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Morison%WriteOutputHdr(I) ), I=1,p%Morison%NumOuts ) + IF (ALLOCATED( p%Morison%OutParam ) .AND. (p%Morison%NumOuts > 0 .OR. p%Morison%OutAll)) THEN + Frmt = '('//TRIM(Int2LStr(size(p%Morison%OutParam)))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Morison%WriteOutputHdr(I) ), I=1,size(p%Morison%OutParam) ) END IF @@ -9033,9 +9033,9 @@ SUBROUTINE HDOut_OpenOutput( HydroDyn_ProgDesc, OutRootName, p, InitOut, ErrSta WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%WriteOutputUnt(I) ), I=1,p%NumOuts ) END IF - IF (ALLOCATED( p%Morison%OutParam ) .AND. p%Morison%NumOuts > 0) THEN - Frmt = '('//TRIM(Int2LStr(p%Morison%NumOuts))//'(:,A,'//TRIM( p%OutSFmt )//'))' - WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Morison%WriteOutputUnt(I) ), I=1,p%Morison%NumOuts ) + IF (ALLOCATED( p%Morison%OutParam ) .AND. (p%Morison%NumOuts > 0 .OR. p%Morison%OutAll)) THEN + Frmt = '('//TRIM(Int2LStr(size(p%Morison%OutParam)))//'(:,A,'//TRIM( p%OutSFmt )//'))' + WRITE(p%UnOutFile,Frmt,ADVANCE='no') ( p%Delim, TRIM( InitOut%Morison%WriteOutputUnt(I) ), I=1,size(p%Morison%OutParam) ) END IF diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90 index c1b96adc1..73927c85a 100644 --- a/modules/hydrodyn/src/HydroDyn_Types.f90 +++ b/modules/hydrodyn/src/HydroDyn_Types.f90 @@ -76,7 +76,6 @@ MODULE HydroDyn_Types INTEGER(IntKi) :: NUserOutputs = 0_IntKi !< Number of Hydrodyn-level requested output channels [-] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: UserOutputs !< This should really be dimensioned with MaxOutPts [-] INTEGER(IntKi) :: OutSwtch = 0_IntKi !< Output requested channels to: [1=Hydrodyn.out 2=GlueCode.out 3=both files] [-] - LOGICAL :: OutAll = .false. !< Output all user-specified member and joint loads (only at each member end, not interior locations) [T/F] [-] INTEGER(IntKi) :: NumOuts = 0_IntKi !< The number of outputs for this module as requested in the input file [-] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< The user-requested output channel labels for this modules. This should really be dimensioned with MaxOutPts [-] LOGICAL :: HDSum = .false. !< Generate a HydroDyn summary file [T/F] [-] @@ -228,20 +227,21 @@ MODULE HydroDyn_Types integer(IntKi), public, parameter :: HydroDyn_x_Morison_DummyContState = 4 ! HydroDyn%Morison%DummyContState integer(IntKi), public, parameter :: HydroDyn_u_Morison_Mesh = 5 ! HydroDyn%Morison%Mesh integer(IntKi), public, parameter :: HydroDyn_u_Morison_PtfmRefY = 6 ! HydroDyn%Morison%PtfmRefY - integer(IntKi), public, parameter :: HydroDyn_u_WAMITMesh = 7 ! HydroDyn%WAMITMesh - integer(IntKi), public, parameter :: HydroDyn_u_PRPMesh = 8 ! HydroDyn%PRPMesh - integer(IntKi), public, parameter :: HydroDyn_u_qAddDOF = 9 ! HydroDyn%qAddDOF - integer(IntKi), public, parameter :: HydroDyn_u_qAddDOFDot = 10 ! HydroDyn%qAddDOFDot - integer(IntKi), public, parameter :: HydroDyn_u_qAddDOFDotDot = 11 ! HydroDyn%qAddDOFDotDot - integer(IntKi), public, parameter :: HydroDyn_y_WAMIT_Mesh = 12 ! HydroDyn%WAMIT(DL%i1)%Mesh - integer(IntKi), public, parameter :: HydroDyn_y_WAMIT_FAddDOF = 13 ! HydroDyn%WAMIT(DL%i1)%FAddDOF - integer(IntKi), public, parameter :: HydroDyn_y_WAMIT2_Mesh = 14 ! HydroDyn%WAMIT2(DL%i1)%Mesh - integer(IntKi), public, parameter :: HydroDyn_y_Morison_Mesh = 15 ! HydroDyn%Morison%Mesh - integer(IntKi), public, parameter :: HydroDyn_y_Morison_VisMesh = 16 ! HydroDyn%Morison%VisMesh - integer(IntKi), public, parameter :: HydroDyn_y_Morison_WriteOutput = 17 ! HydroDyn%Morison%WriteOutput - integer(IntKi), public, parameter :: HydroDyn_y_WAMITMesh = 18 ! HydroDyn%WAMITMesh - integer(IntKi), public, parameter :: HydroDyn_y_WriteOutput = 19 ! HydroDyn%WriteOutput - integer(IntKi), public, parameter :: HydroDyn_y_FAddDOF = 20 ! HydroDyn%FAddDOF + integer(IntKi), public, parameter :: HydroDyn_u_Morison_PRP = 7 ! HydroDyn%Morison%PRP + integer(IntKi), public, parameter :: HydroDyn_u_WAMITMesh = 8 ! HydroDyn%WAMITMesh + integer(IntKi), public, parameter :: HydroDyn_u_PRPMesh = 9 ! HydroDyn%PRPMesh + integer(IntKi), public, parameter :: HydroDyn_u_qAddDOF = 10 ! HydroDyn%qAddDOF + integer(IntKi), public, parameter :: HydroDyn_u_qAddDOFDot = 11 ! HydroDyn%qAddDOFDot + integer(IntKi), public, parameter :: HydroDyn_u_qAddDOFDotDot = 12 ! HydroDyn%qAddDOFDotDot + integer(IntKi), public, parameter :: HydroDyn_y_WAMIT_Mesh = 13 ! HydroDyn%WAMIT(DL%i1)%Mesh + integer(IntKi), public, parameter :: HydroDyn_y_WAMIT_FAddDOF = 14 ! HydroDyn%WAMIT(DL%i1)%FAddDOF + integer(IntKi), public, parameter :: HydroDyn_y_WAMIT2_Mesh = 15 ! HydroDyn%WAMIT2(DL%i1)%Mesh + integer(IntKi), public, parameter :: HydroDyn_y_Morison_Mesh = 16 ! HydroDyn%Morison%Mesh + integer(IntKi), public, parameter :: HydroDyn_y_Morison_VisMesh = 17 ! HydroDyn%Morison%VisMesh + integer(IntKi), public, parameter :: HydroDyn_y_Morison_WriteOutput = 18 ! HydroDyn%Morison%WriteOutput + integer(IntKi), public, parameter :: HydroDyn_y_WAMITMesh = 19 ! HydroDyn%WAMITMesh + integer(IntKi), public, parameter :: HydroDyn_y_WriteOutput = 20 ! HydroDyn%WriteOutput + integer(IntKi), public, parameter :: HydroDyn_y_FAddDOF = 21 ! HydroDyn%FAddDOF contains @@ -457,7 +457,6 @@ subroutine HydroDyn_CopyInputFile(SrcInputFileData, DstInputFileData, CtrlCode, DstInputFileData%UserOutputs = SrcInputFileData%UserOutputs end if DstInputFileData%OutSwtch = SrcInputFileData%OutSwtch - DstInputFileData%OutAll = SrcInputFileData%OutAll DstInputFileData%NumOuts = SrcInputFileData%NumOuts if (allocated(SrcInputFileData%OutList)) then LB(1:1) = lbound(SrcInputFileData%OutList) @@ -579,7 +578,6 @@ subroutine HydroDyn_PackInputFile(RF, Indata) call RegPack(RF, InData%NUserOutputs) call RegPackAlloc(RF, InData%UserOutputs) call RegPack(RF, InData%OutSwtch) - call RegPack(RF, InData%OutAll) call RegPack(RF, InData%NumOuts) call RegPackAlloc(RF, InData%OutList) call RegPack(RF, InData%HDSum) @@ -629,7 +627,6 @@ subroutine HydroDyn_UnPackInputFile(RF, OutData) call RegUnpack(RF, OutData%NUserOutputs); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%UserOutputs); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%OutSwtch); if (RegCheckErr(RF, RoutineName)) return - call RegUnpack(RF, OutData%OutAll); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NumOuts); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%OutList); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%HDSum); if (RegCheckErr(RF, RoutineName)) return @@ -2823,6 +2820,8 @@ subroutine HydroDyn_VarPackInput(V, u, ValAry) call MV_PackMesh(V, u%Morison%Mesh, ValAry) ! Mesh case (HydroDyn_u_Morison_PtfmRefY) VarVals(1) = u%Morison%PtfmRefY ! Scalar + case (HydroDyn_u_Morison_PRP) + VarVals = u%Morison%PRP(V%iLB:V%iUB) ! Rank 1 Array case (HydroDyn_u_WAMITMesh) call MV_PackMesh(V, u%WAMITMesh, ValAry) ! Mesh case (HydroDyn_u_PRPMesh) @@ -2859,6 +2858,8 @@ subroutine HydroDyn_VarUnpackInput(V, ValAry, u) call MV_UnpackMesh(V, ValAry, u%Morison%Mesh) ! Mesh case (HydroDyn_u_Morison_PtfmRefY) u%Morison%PtfmRefY = VarVals(1) ! Scalar + case (HydroDyn_u_Morison_PRP) + u%Morison%PRP(V%iLB:V%iUB) = VarVals ! Rank 1 Array case (HydroDyn_u_WAMITMesh) call MV_UnpackMesh(V, ValAry, u%WAMITMesh) ! Mesh case (HydroDyn_u_PRPMesh) @@ -2881,6 +2882,8 @@ function HydroDyn_InputFieldName(DL) result(Name) Name = "u%Morison%Mesh" case (HydroDyn_u_Morison_PtfmRefY) Name = "u%Morison%PtfmRefY" + case (HydroDyn_u_Morison_PRP) + Name = "u%Morison%PRP" case (HydroDyn_u_WAMITMesh) Name = "u%WAMITMesh" case (HydroDyn_u_PRPMesh) diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 0bd6288e6..4dfe7e438 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -1795,6 +1795,7 @@ subroutine AllocateMemberDataArrays( member, memberLoads, errStat, errMsg ) call AllocAry( memberLoads%F_If , 6, member%NElements+1, 'memberLoads%F_If' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( memberLoads%F_WMG , 6, member%NElements+1, 'memberLoads%F_WMG', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( memberLoads%F_IMG , 6, member%NElements+1, 'memberLoads%F_IMG', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_sum , 6, member%NElements+1, 'memberLoads%F_sum', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) ! Shape dependent variables if (member%MSecGeom == MSecGeom_Cyl) then @@ -1876,6 +1877,8 @@ subroutine AllocateMemberDataArrays( member, memberLoads, errStat, errMsg ) memberLoads%F_If = 0.0_ReKi memberLoads%F_WMG = 0.0_ReKi memberLoads%F_IMG = 0.0_ReKi + memberLoads%F_sum = 0.0_ReKi + memberLoads%F_tot = 0.0_ReKi if (member%MSecGeom == MSecGeom_Cyl) then member%dRdl_mg = 0.0_ReKi @@ -2804,6 +2807,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In p%NJoints = InitInp%NJoints p%NumOuts = InitInp%NumOuts p%NMOutputs = InitInp%NMOutputs ! Number of members to output [ >=0 and <10] + p%OutAll = InitInp%OutAll p%WaveDisp = InitInp%WaveDisp p%AMMod = InitInp%AMMod p%HstMod = InitInp%HstMod @@ -3419,6 +3423,7 @@ SUBROUTINE AllocateNodeLoadVariables(InitInp, p, m, NNodes, errStat, errMsg ) call AllocAry( m%F_D_End , 3, p%NJoints, 'm%F_D_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%F_B_End , 6, p%NJoints, 'm%F_B_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%F_IMG_End , 6, p%NJoints, 'm%F_IMG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%F_tot_End , 6, p%NJoints, 'm%F_tot_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( p%I_MG_End , 3, 3, p%NJoints, 'p%I_MG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( p%F_WMG_End , 3, p%NJoints, 'p%F_WMG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( p%Mass_MG_End , p%NJoints, 'p%Mass_MG_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) @@ -3448,6 +3453,7 @@ SUBROUTINE AllocateNodeLoadVariables(InitInp, p, m, NNodes, errStat, errMsg ) m%F_D_End = 0.0 m%F_B_End = 0.0 m%F_IMG_End = 0.0 + m%F_tot_End = 0.0 p%DP_Const_End = 0.0 p%I_MG_End = 0.0 p%Mass_MG_End = 0.0 @@ -4521,6 +4527,23 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! External Hydrodynamic Side Loads - End ! !-----------------------------------------------------------------------------------------------------! + ! Compute total member force and moment about PRP if OutAll + ! Cannot use mesh force and moment above because multiple members can share the same end joints + ! Todo: Restructure the code above to avoid having to sum the load components twice. + ! This is ok for now because we only do this if p%OutAll = true + if (p%OutAll) then + m%memberLoads(im)%F_tot = 0.0_ReKi + do i = 1,N+1 + m%memberLoads(im)%F_sum(:,i) = m%memberLoads(im)%F_D(:,i) + m%memberLoads(im)%F_I(:,i) + m%memberLoads(im)%F_A(:,i) + & + m%memberLoads(im)%F_B(:,i) + m%memberLoads(im)%F_BF(:,i) + m%memberLoads(im)%F_IF(:,i) + & + m%memberLoads(im)%F_WMG(:,i) + m%memberLoads(im)%F_IMG(:,i) + m%memberLoads(im)%F_tot = m%memberLoads(im)%F_tot + m%memberLoads(im)%F_sum(:,i) + m%memberLoads(im)%F_tot(4:6) = m%memberLoads(im)%F_tot(4:6) + & + cross_product( u%Mesh%Position(:,mem%NodeIndx(i))+u%Mesh%TranslationDisp(:,mem%NodeIndx(i))-u%PRP, & + m%memberLoads(im)%F_sum(1:3,i)) + end do + end if + !-----------------------------------------------------------------------------------------------------! ! Any end plate loads that are modeled on a per-member basis: F_B and F_BF ! !-----------------------------------------------------------------------------------------------------! @@ -4755,13 +4778,16 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, + p%DragLoFSc_End(j) * An_End(i) * p%DragConst_End(j) * abs(vmag) *max(vmag, 0.0_ReKi) m%F_D_End(i,j) = 2.0_ReKi * m%F_D_End(i,j) END IF - - y%Mesh%Force(i,j) = y%Mesh%Force(i,j) + m%F_D_End(i,j) + m%F_I_End(i,j) + p%F_WMG_End(i,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_A_End(i,j) + m%F_IMG_End(i,j) + m%F_tot_End(i,j) = m%F_D_End(i,j) + m%F_I_End(i,j) + p%F_WMG_End(i,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_A_End(i,j) + m%F_IMG_End(i,j) + y%Mesh%Force(i,j) = y%Mesh%Force(i,j) + m%F_tot_End(i,j) ELSE ! Three moment components - y%Mesh%Moment(i-3,j) = y%Mesh%Moment(i-3,j) + m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_IMG_End(i,j) + m%F_tot_End(i,j) = m%F_B_End(i,j) + m%F_BF_End(i,j) + m%F_IMG_End(i,j) + y%Mesh%Moment(i-3,j) = y%Mesh%Moment(i-3,j) + m%F_tot_End(i,j) END IF END DO ! I=1,6 - + ! Compute and save the joint total moment about PRP for output file + m%F_tot_End(4:6,j) = m%F_tot_End(4:6,j) + cross_product( u%Mesh%Position(:,j)+u%Mesh%TranslationDisp(:,j)-u%PRP, m%F_tot_End(1:3,j)) + END DO ! J = 1, p%NJoints !---------------------------------------------------------------------------------------------------------------! diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index e14c5a9af..f8da63bbe 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -248,6 +248,8 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi FV {:}{:} - - "Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi FA {:}{:} - - "Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi F_DP {:}{:} - - "Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times" - +typedef ^ ^ ReKi F_sum {:}{:} - - "Member-based (side-effects) Nodal combined loads at time t" - +typedef ^ ^ ReKi F_tot {6} - - "Member total force and moment" - # typedef ^ Morison_CoefMembersCyl INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - typedef ^ ^ ReKi MemberCd1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - @@ -405,6 +407,7 @@ typedef ^ ^ INTEGER typedef ^ ^ Morison_JOutput JOutLst {:} - - "" - typedef ^ ^ CHARACTER(ChanLen) OutList {:} - - "This list size needs to be the maximum # of possible outputs because of the use of ReadAry(). Use MaxMrsnOutputs" - typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ LOGICAL OutAll - .false. - "Output all user-specified member and joint loads (only total member loads, not interior locations) [T/F]" - typedef ^ ^ INTEGER UnSum - - - "" - typedef ^ ^ SeaSt_WaveFieldType *WaveField - - - "Pointer to SeaState wave field" - typedef ^ ^ logical VisMeshes - .false. - "Output visualization meshes" - @@ -458,7 +461,8 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi F_I_End {:}{:} - - "Lumped intertia loads at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi F_IMG_End {:}{:} - - "Joint marine growth intertia loads at time t, which may not correspond to the WaveTime array of times" - typedef ^ ^ ReKi F_A_End {:}{:} - - "Lumped added mass loads at time t, which may not correspond to the WaveTime array of times" - -typedef ^ ^ ReKi F_BF_End {:}{:} - - "" - +typedef ^ ^ ReKi F_BF_End {:}{:} - - "Joint internal ballast hydrostatic loads" - +typedef ^ ^ ReKi F_tot_End {:}{:} - - "Joint total loads" typedef ^ ^ ReKi V_rel_n {:} - - "Normal relative flow velocity at joints" m/s typedef ^ ^ ReKi V_rel_n_HiPass {:} - - "High-pass filtered normal relative flow velocity at joints" m/s typedef ^ ^ ReKi zFillGroup {:} - - "Instantaneous highest point of each filled group" m @@ -494,6 +498,7 @@ typedef ^ ^ INTEGER typedef ^ ^ Morison_JOutput JOutLst {:} - - "" - typedef ^ ^ OutParmType OutParam {:} - - "" - typedef ^ ^ INTEGER NumOuts - - - "" - +typedef ^ ^ LOGICAL OutAll - .false. - "Output all user-specified member and joint loads (only total member loads, not interior locations) [T/F]" - typedef ^ ^ SeaSt_WaveFieldType *WaveField - - - "SeaState wave field" - typedef ^ ^ logical VisMeshes - .false. - "Output visualization meshes" - typedef ^ ^ INTEGER PtfmYMod - - - "Large yaw model" - @@ -506,6 +511,7 @@ typedef ^ ^ Morison_Fil # typedef ^ InputType MeshType Mesh - - - "Kinematics of each node input mesh" - typedef ^ ^ ReKi PtfmRefY - - - "Reference platform yaw offset" (rad) +typedef ^ ^ ReKi PRP {3} - - "Coordinates of the principal reference point" (m) # # # ..... Outputs ................................................................................................................... diff --git a/modules/hydrodyn/src/Morison_Output.f90 b/modules/hydrodyn/src/Morison_Output.f90 index 642309b98..efa49bd58 100644 --- a/modules/hydrodyn/src/Morison_Output.f90 +++ b/modules/hydrodyn/src/Morison_Output.f90 @@ -7924,7 +7924,24 @@ SUBROUTINE MrsnOut_MapOutputs( y, p, u, m ) END DO END IF ! p%NumOuts > 0 - + + IF (.not.p%OutAll) RETURN + + I = p%NumOuts + DO im = 1,p%NMembers + y%WriteOutput(I+1:I+6) = m%MemberLoads(im)%F_tot + I = I + 6_IntKi + END DO + DO im = 1,p%NJoints + y%WriteOutput(I+1:I+6) = m%F_tot_End(:,im) + I = I + 6_IntKi + END DO + DO im = 1,p%NNodes + y%WriteOutput(I+1:I+3) = y%Mesh%Force(:,im) + y%WriteOutput(I+4:I+6) = y%Mesh%Moment(:,im) + I = I + 6_IntKi + END DO + END SUBROUTINE MrsnOut_MapOutputs @@ -8008,20 +8025,22 @@ SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) ! Check that the variables in OutList are valid !------------------------------------------------------------------------------------------------- -! MrsnOut_Data%NumOuts = HDO_InitData%NumOuts -if (p%NumOuts > 0 ) THEN - CALL SetOutParam( InitInp%OutList, p, ErrStat, ErrMsg ) - IF ( ErrStat >= AbortErrLev ) RETURN -END IF + ! MrsnOut_Data%NumOuts = HDO_InitData%NumOuts + IF ( (p%NumOuts > 0_IntKi) .or. p%OutAll ) THEN + CALL SetOutParam( InitInp%OutList, p, ErrStat, ErrMsg ) + IF ( ErrStat >= AbortErrLev ) RETURN + END IF !------------------------------------------------------------------------------------------------- ! Open the output file, if necessary, and write the header !------------------------------------------------------------------------------------------------- - IF ( ALLOCATED( p%OutParam ) .AND. p%NumOuts > 0 ) THEN ! Output has been requested so let's open an output file + IF ( .not. allocated(p%OutParam) ) return + + IF ( size(p%OutParam) > 0 ) THEN ! Output has been requested so let's open an output file - ALLOCATE( y%WriteOutput( p%NumOuts ), STAT = ErrStat ) + ALLOCATE( y%WriteOutput( size(p%OutParam) ), STAT = ErrStat ) IF ( ErrStat /= ErrID_None ) THEN ErrMsg = ' Error allocating space for WriteOutput array.' ErrStat = ErrID_Fatal @@ -8056,14 +8075,14 @@ SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) ! These variables are to help follow the framework template, but the data in them is simply a copy of data ! already available in the OutParam data structure - ALLOCATE ( InitOut%WriteOutputHdr(p%NumOuts), STAT = ErrStat ) + ALLOCATE ( InitOut%WriteOutputHdr(size(p%OutParam)), STAT = ErrStat ) IF ( ErrStat /= ErrID_None ) THEN ErrMsg = ' Error allocating space for WriteOutputHdr array.' ErrStat = ErrID_Fatal RETURN END IF - ALLOCATE ( InitOut%WriteOutputUnt(p%NumOuts), STAT = ErrStat ) + ALLOCATE ( InitOut%WriteOutputUnt(size(p%OutParam)), STAT = ErrStat ) IF ( ErrStat /= ErrID_None ) THEN ErrMsg = ' Error allocating space for WriteOutputHdr array.' ErrStat = ErrID_Fatal @@ -8072,7 +8091,7 @@ SUBROUTINE MrsnOut_Init( InitInp, y, p, InitOut, ErrStat, ErrMsg ) - DO I = 1,p%NumOuts + DO I = 1,size(p%OutParam) InitOut%WriteOutputHdr(I) = TRIM( p%OutParam(I)%Name ) InitOut%WriteOutputUnt(I) = TRIM( p%OutParam(I)%Units ) @@ -8942,8 +8961,11 @@ SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) ! Allocate and set index, name, and units for the output channels ! If a selected output channel is not available in this module, set error flag. !------------------------------------------------------------------------------------------------- - - ALLOCATE ( p%OutParam(1:p%NumOuts) , STAT=ErrStat2 ) + if (p%OutAll) then + ALLOCATE ( p%OutParam(1:(p%NumOuts + 6_IntKi*p%NMembers + 6_IntKi*p%NJoints + 6_IntKi*p%NNodes)) , STAT=ErrStat2 ) + else + ALLOCATE ( p%OutParam(1:p%NumOuts) , STAT=ErrStat2 ) + endif IF ( ErrStat2 /= 0_IntKi ) THEN CALL SetErrStat( ErrID_Fatal,"Error allocating memory for the Morison OutParam array.", ErrStat, ErrMsg, RoutineName ) RETURN @@ -8985,6 +9007,67 @@ SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) END DO + if (p%OutAll) then + k = p%NumOuts + do i = 1,p%NMembers + p%OutParam(k+1)%Name = "M"//trim(num2lstr(i))//"TotFxi" + p%OutParam(k+1)%Units = "(N)" + p%OutParam(k+2)%Name = "M"//trim(num2lstr(i))//"TotFyi" + p%OutParam(k+2)%Units = "(N)" + p%OutParam(k+3)%Name = "M"//trim(num2lstr(i))//"TotFzi" + p%OutParam(k+3)%Units = "(N)" + p%OutParam(k+4)%Name = "M"//trim(num2lstr(i))//"TotMxi" + p%OutParam(k+4)%Units = "(N-m)" + p%OutParam(k+5)%Name = "M"//trim(num2lstr(i))//"TotMyi" + p%OutParam(k+5)%Units = "(N-m)" + p%OutParam(k+6)%Name = "M"//trim(num2lstr(i))//"TotMzi" + p%OutParam(k+6)%Units = "(N-m)" + do j = 1,6 + k = k + 1_IntKi + p%OutParam(k)%Indx = -1_IntKi + p%OutParam(k)%SignM = 1_IntKi + end do + end do + do i = 1,p%NJoints + p%OutParam(k+1)%Name = "J"//trim(num2lstr(i))//"TotFxi" + p%OutParam(k+1)%Units = "(N)" + p%OutParam(k+2)%Name = "J"//trim(num2lstr(i))//"TotFyi" + p%OutParam(k+2)%Units = "(N)" + p%OutParam(k+3)%Name = "J"//trim(num2lstr(i))//"TotFzi" + p%OutParam(k+3)%Units = "(N)" + p%OutParam(k+4)%Name = "J"//trim(num2lstr(i))//"TotMxi" + p%OutParam(k+4)%Units = "(N-m)" + p%OutParam(k+5)%Name = "J"//trim(num2lstr(i))//"TotMyi" + p%OutParam(k+5)%Units = "(N-m)" + p%OutParam(k+6)%Name = "J"//trim(num2lstr(i))//"TotMzi" + p%OutParam(k+6)%Units = "(N-m)" + do j = 1,6 + k = k + 1_IntKi + p%OutParam(k)%Indx = -1_IntKi + p%OutParam(k)%SignM = 1_IntKi + end do + end do + do i = 1,p%NNodes + p%OutParam(k+1)%Name = "N"//trim(num2lstr(i))//"TotFxi" + p%OutParam(k+1)%Units = "(N)" + p%OutParam(k+2)%Name = "N"//trim(num2lstr(i))//"TotFyi" + p%OutParam(k+2)%Units = "(N)" + p%OutParam(k+3)%Name = "N"//trim(num2lstr(i))//"TotFzi" + p%OutParam(k+3)%Units = "(N)" + p%OutParam(k+4)%Name = "N"//trim(num2lstr(i))//"TotMxi" + p%OutParam(k+4)%Units = "(N-m)" + p%OutParam(k+5)%Name = "N"//trim(num2lstr(i))//"TotMyi" + p%OutParam(k+5)%Units = "(N-m)" + p%OutParam(k+6)%Name = "N"//trim(num2lstr(i))//"TotMzi" + p%OutParam(k+6)%Units = "(N-m)" + do j = 1,6 + k = k + 1_IntKi + p%OutParam(k)%Indx = -1_IntKi + p%OutParam(k)%SignM = 1_IntKi + end do + end do + end if + RETURN END SUBROUTINE SetOutParam !---------------------------------------------------------------------------------------------------------------------------------- diff --git a/modules/hydrodyn/src/Morison_Types.f90 b/modules/hydrodyn/src/Morison_Types.f90 index 23f4f011c..3ab02c291 100644 --- a/modules/hydrodyn/src/Morison_Types.f90 +++ b/modules/hydrodyn/src/Morison_Types.f90 @@ -297,6 +297,8 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FV !< Fluid velocity at line element node at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: FA !< Fluid acceleration at line element node at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_DP !< Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_sum !< Member-based (side-effects) Nodal combined loads at time t [-] + REAL(ReKi) , DIMENSION(1:6) :: F_tot = 0.0_ReKi !< Member total force and moment [-] END TYPE Morison_MemberLoads ! ======================= ! ========= Morison_CoefMembersCyl ======= @@ -473,6 +475,7 @@ MODULE Morison_Types TYPE(Morison_JOutput) , DIMENSION(:), ALLOCATABLE :: JOutLst !< [-] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< This list size needs to be the maximum # of possible outputs because of the use of ReadAry(). Use MaxMrsnOutputs [-] INTEGER(IntKi) :: NumOuts = 0_IntKi !< [-] + LOGICAL :: OutAll = .false. !< Output all user-specified member and joint loads (only total member loads, not interior locations) [T/F] [-] INTEGER(IntKi) :: UnSum = 0_IntKi !< [-] TYPE(SeaSt_WaveFieldType) , POINTER :: WaveField => NULL() !< Pointer to SeaState wave field [-] LOGICAL :: VisMeshes = .false. !< Output visualization meshes [-] @@ -526,7 +529,8 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_I_End !< Lumped intertia loads at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_IMG_End !< Joint marine growth intertia loads at time t, which may not correspond to the WaveTime array of times [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_A_End !< Lumped added mass loads at time t, which may not correspond to the WaveTime array of times [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_BF_End !< [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_BF_End !< Joint internal ballast hydrostatic loads [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_tot_End !< Joint total loads [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: V_rel_n !< Normal relative flow velocity at joints [m/s] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: V_rel_n_HiPass !< High-pass filtered normal relative flow velocity at joints [m/s] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: zFillGroup !< Instantaneous highest point of each filled group [m] @@ -561,6 +565,7 @@ MODULE Morison_Types TYPE(Morison_JOutput) , DIMENSION(:), ALLOCATABLE :: JOutLst !< [-] TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< [-] INTEGER(IntKi) :: NumOuts = 0_IntKi !< [-] + LOGICAL :: OutAll = .false. !< Output all user-specified member and joint loads (only total member loads, not interior locations) [T/F] [-] TYPE(SeaSt_WaveFieldType) , POINTER :: WaveField => NULL() !< SeaState wave field [-] LOGICAL :: VisMeshes = .false. !< Output visualization meshes [-] INTEGER(IntKi) :: PtfmYMod = 0_IntKi !< Large yaw model [-] @@ -572,6 +577,7 @@ MODULE Morison_Types TYPE, PUBLIC :: Morison_InputType TYPE(MeshType) :: Mesh !< Kinematics of each node input mesh [-] REAL(ReKi) :: PtfmRefY = 0.0_ReKi !< Reference platform yaw offset [(rad)] + REAL(ReKi) , DIMENSION(1:3) :: PRP = 0.0_ReKi !< Coordinates of the principal reference point [(m)] END TYPE Morison_InputType ! ======================= ! ========= Morison_OutputType ======= @@ -584,9 +590,10 @@ MODULE Morison_Types integer(IntKi), public, parameter :: Morison_x_DummyContState = 1 ! Morison%DummyContState integer(IntKi), public, parameter :: Morison_u_Mesh = 2 ! Morison%Mesh integer(IntKi), public, parameter :: Morison_u_PtfmRefY = 3 ! Morison%PtfmRefY - integer(IntKi), public, parameter :: Morison_y_Mesh = 4 ! Morison%Mesh - integer(IntKi), public, parameter :: Morison_y_VisMesh = 5 ! Morison%VisMesh - integer(IntKi), public, parameter :: Morison_y_WriteOutput = 6 ! Morison%WriteOutput + integer(IntKi), public, parameter :: Morison_u_PRP = 4 ! Morison%PRP + integer(IntKi), public, parameter :: Morison_y_Mesh = 5 ! Morison%Mesh + integer(IntKi), public, parameter :: Morison_y_VisMesh = 6 ! Morison%VisMesh + integer(IntKi), public, parameter :: Morison_y_WriteOutput = 7 ! Morison%WriteOutput contains @@ -2632,6 +2639,19 @@ subroutine Morison_CopyMemberLoads(SrcMemberLoadsData, DstMemberLoadsData, CtrlC end if DstMemberLoadsData%F_DP = SrcMemberLoadsData%F_DP end if + if (allocated(SrcMemberLoadsData%F_sum)) then + LB(1:2) = lbound(SrcMemberLoadsData%F_sum) + UB(1:2) = ubound(SrcMemberLoadsData%F_sum) + if (.not. allocated(DstMemberLoadsData%F_sum)) then + allocate(DstMemberLoadsData%F_sum(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberLoadsData%F_sum.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberLoadsData%F_sum = SrcMemberLoadsData%F_sum + end if + DstMemberLoadsData%F_tot = SrcMemberLoadsData%F_tot end subroutine subroutine Morison_DestroyMemberLoads(MemberLoadsData, ErrStat, ErrMsg) @@ -2674,6 +2694,9 @@ subroutine Morison_DestroyMemberLoads(MemberLoadsData, ErrStat, ErrMsg) if (allocated(MemberLoadsData%F_DP)) then deallocate(MemberLoadsData%F_DP) end if + if (allocated(MemberLoadsData%F_sum)) then + deallocate(MemberLoadsData%F_sum) + end if end subroutine subroutine Morison_PackMemberLoads(RF, Indata) @@ -2692,6 +2715,8 @@ subroutine Morison_PackMemberLoads(RF, Indata) call RegPackAlloc(RF, InData%FV) call RegPackAlloc(RF, InData%FA) call RegPackAlloc(RF, InData%F_DP) + call RegPackAlloc(RF, InData%F_sum) + call RegPack(RF, InData%F_tot) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -2714,6 +2739,8 @@ subroutine Morison_UnPackMemberLoads(RF, OutData) call RegUnpackAlloc(RF, OutData%FV); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%FA); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%F_DP); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%F_sum); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%F_tot); if (RegCheckErr(RF, RoutineName)) return end subroutine subroutine Morison_CopyCoefMembersCyl(SrcCoefMembersCylData, DstCoefMembersCylData, CtrlCode, ErrStat, ErrMsg) @@ -3530,6 +3557,7 @@ subroutine Morison_CopyInitInput(SrcInitInputData, DstInitInputData, CtrlCode, E DstInitInputData%OutList = SrcInitInputData%OutList end if DstInitInputData%NumOuts = SrcInitInputData%NumOuts + DstInitInputData%OutAll = SrcInitInputData%OutAll DstInitInputData%UnSum = SrcInitInputData%UnSum DstInitInputData%WaveField => SrcInitInputData%WaveField DstInitInputData%VisMeshes = SrcInitInputData%VisMeshes @@ -3869,6 +3897,7 @@ subroutine Morison_PackInitInput(RF, Indata) end if call RegPackAlloc(RF, InData%OutList) call RegPack(RF, InData%NumOuts) + call RegPack(RF, InData%OutAll) call RegPack(RF, InData%UnSum) call RegPack(RF, associated(InData%WaveField)) if (associated(InData%WaveField)) then @@ -4131,6 +4160,7 @@ subroutine Morison_UnPackInitInput(RF, OutData) end if call RegUnpackAlloc(RF, OutData%OutList); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NumOuts); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%OutAll); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%UnSum); if (RegCheckErr(RF, RoutineName)) return if (associated(OutData%WaveField)) deallocate(OutData%WaveField) call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return @@ -4666,6 +4696,18 @@ subroutine Morison_CopyMisc(SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg) end if DstMiscData%F_BF_End = SrcMiscData%F_BF_End end if + if (allocated(SrcMiscData%F_tot_End)) then + LB(1:2) = lbound(SrcMiscData%F_tot_End) + UB(1:2) = ubound(SrcMiscData%F_tot_End) + if (.not. allocated(DstMiscData%F_tot_End)) then + allocate(DstMiscData%F_tot_End(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%F_tot_End.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMiscData%F_tot_End = SrcMiscData%F_tot_End + end if if (allocated(SrcMiscData%V_rel_n)) then LB(1:1) = lbound(SrcMiscData%V_rel_n) UB(1:1) = ubound(SrcMiscData%V_rel_n) @@ -4781,6 +4823,9 @@ subroutine Morison_DestroyMisc(MiscData, ErrStat, ErrMsg) if (allocated(MiscData%F_BF_End)) then deallocate(MiscData%F_BF_End) end if + if (allocated(MiscData%F_tot_End)) then + deallocate(MiscData%F_tot_End) + end if if (allocated(MiscData%V_rel_n)) then deallocate(MiscData%V_rel_n) end if @@ -4829,6 +4874,7 @@ subroutine Morison_PackMisc(RF, Indata) call RegPackAlloc(RF, InData%F_IMG_End) call RegPackAlloc(RF, InData%F_A_End) call RegPackAlloc(RF, InData%F_BF_End) + call RegPackAlloc(RF, InData%F_tot_End) call RegPackAlloc(RF, InData%V_rel_n) call RegPackAlloc(RF, InData%V_rel_n_HiPass) call RegPackAlloc(RF, InData%zFillGroup) @@ -4876,6 +4922,7 @@ subroutine Morison_UnPackMisc(RF, OutData) call RegUnpackAlloc(RF, OutData%F_IMG_End); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%F_A_End); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%F_BF_End); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%F_tot_End); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%V_rel_n); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%V_rel_n_HiPass); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%zFillGroup); if (RegCheckErr(RF, RoutineName)) return @@ -5091,6 +5138,7 @@ subroutine Morison_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrM end do end if DstParamData%NumOuts = SrcParamData%NumOuts + DstParamData%OutAll = SrcParamData%OutAll DstParamData%WaveField => SrcParamData%WaveField DstParamData%VisMeshes = SrcParamData%VisMeshes DstParamData%PtfmYMod = SrcParamData%PtfmYMod @@ -5267,6 +5315,7 @@ subroutine Morison_PackParam(RF, Indata) end do end if call RegPack(RF, InData%NumOuts) + call RegPack(RF, InData%OutAll) call RegPack(RF, associated(InData%WaveField)) if (associated(InData%WaveField)) then call RegPackPointer(RF, c_loc(InData%WaveField), PtrInIndex) @@ -5373,6 +5422,7 @@ subroutine Morison_UnPackParam(RF, OutData) end do end if call RegUnpack(RF, OutData%NumOuts); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%OutAll); if (RegCheckErr(RF, RoutineName)) return if (associated(OutData%WaveField)) deallocate(OutData%WaveField) call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return if (IsAllocAssoc) then @@ -5424,6 +5474,7 @@ subroutine Morison_CopyInput(SrcInputData, DstInputData, CtrlCode, ErrStat, ErrM call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return DstInputData%PtfmRefY = SrcInputData%PtfmRefY + DstInputData%PRP = SrcInputData%PRP end subroutine subroutine Morison_DestroyInput(InputData, ErrStat, ErrMsg) @@ -5446,6 +5497,7 @@ subroutine Morison_PackInput(RF, Indata) if (RF%ErrStat >= AbortErrLev) return call MeshPack(RF, InData%Mesh) call RegPack(RF, InData%PtfmRefY) + call RegPack(RF, InData%PRP) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -5456,6 +5508,7 @@ subroutine Morison_UnPackInput(RF, OutData) if (RF%ErrStat /= ErrID_None) return call MeshUnpack(RF, OutData%Mesh) ! Mesh call RegUnpack(RF, OutData%PtfmRefY); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%PRP); if (RegCheckErr(RF, RoutineName)) return end subroutine subroutine Morison_CopyOutput(SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg) @@ -5610,6 +5663,8 @@ SUBROUTINE Morison_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, Err REAL(DbKi) :: a1, a2 ! temporary for extrapolation/interpolation INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = '' @@ -5630,6 +5685,7 @@ SUBROUTINE Morison_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, Err CALL MeshExtrapInterp1(u1%Mesh, u2%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) u_out%PtfmRefY = a1*u1%PtfmRefY + a2*u2%PtfmRefY + u_out%PRP = a1*u1%PRP + a2*u2%PRP END SUBROUTINE SUBROUTINE Morison_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) @@ -5662,6 +5718,8 @@ SUBROUTINE Morison_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, INTEGER(IntKi) :: ErrStat2 ! local errors CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors CHARACTER(*), PARAMETER :: RoutineName = 'Morison_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays ! Initialize ErrStat ErrStat = ErrID_None ErrMsg = '' @@ -5688,6 +5746,7 @@ SUBROUTINE Morison_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, CALL MeshExtrapInterp2(u1%Mesh, u2%Mesh, u3%Mesh, tin, u_out%Mesh, tin_out, ErrStat2, ErrMsg2) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) u_out%PtfmRefY = a1*u1%PtfmRefY + a2*u2%PtfmRefY + a3*u3%PtfmRefY + u_out%PRP = a1*u1%PRP + a2*u2%PRP + a3*u3%PRP END SUBROUTINE subroutine Morison_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg) @@ -5985,6 +6044,8 @@ subroutine Morison_VarPackInput(V, u, ValAry) call MV_PackMesh(V, u%Mesh, ValAry) ! Mesh case (Morison_u_PtfmRefY) VarVals(1) = u%PtfmRefY ! Scalar + case (Morison_u_PRP) + VarVals = u%PRP(V%iLB:V%iUB) ! Rank 1 Array case default VarVals = 0.0_R8Ki end select @@ -6011,6 +6072,8 @@ subroutine Morison_VarUnpackInput(V, ValAry, u) call MV_UnpackMesh(V, ValAry, u%Mesh) ! Mesh case (Morison_u_PtfmRefY) u%PtfmRefY = VarVals(1) ! Scalar + case (Morison_u_PRP) + u%PRP(V%iLB:V%iUB) = VarVals ! Rank 1 Array end select end associate end subroutine @@ -6023,6 +6086,8 @@ function Morison_InputFieldName(DL) result(Name) Name = "u%Mesh" case (Morison_u_PtfmRefY) Name = "u%PtfmRefY" + case (Morison_u_PRP) + Name = "u%PRP" case default Name = "Unknown Field" end select