diff --git a/docs/source/user/subdyn/theory.rst b/docs/source/user/subdyn/theory.rst index 4df87b53cf..06bdea0790 100755 --- a/docs/source/user/subdyn/theory.rst +++ b/docs/source/user/subdyn/theory.rst @@ -389,17 +389,17 @@ element stiffness and consistent mass matrices can be written as follows {\scriptstyle [k_e]= \begin{bmatrix} - \frac{12 E J_y} {L_e^3 \left( 1+ K_{sy} \right)} & 0 & 0 & 0 & \frac{6 E J_y}{L_e^2 \left( 1+ K_{sy} \right)} & 0 & -\frac{12 E J_y}{L_e^3 \left( 1+ K_{sy} \right)} & 0 & 0 & 0 & \frac{6 E J_y}{L_e^2 \left( 1+ K_{sy} \right)} & 0 \\ - & \frac{12 E J_x}{L_e^3 \left( 1+ K_{sx} \right)} & 0 & -\frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 & 0 & -\frac{12 E J_x}{L_e^3 \left ( 1+ K_{sx} \right )} & 0 & -\frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 \\ + \frac{12 E J_y} {L_e^3 \left( 1+ K_{sx} \right)} & 0 & 0 & 0 & \frac{6 E J_y}{L_e^2 \left( 1+ K_{sx} \right)} & 0 & -\frac{12 E J_y}{L_e^3 \left( 1+ K_{sx} \right)} & 0 & 0 & 0 & \frac{6 E J_y}{L_e^2 \left( 1+ K_{sx} \right)} & 0 \\ + & \frac{12 E J_x}{L_e^3 \left( 1+ K_{sy} \right)} & 0 & -\frac{6 E J_x}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 & 0 & 0 & -\frac{12 E J_x}{L_e^3 \left ( 1+ K_{sy} \right )} & 0 & -\frac{6 E J_x}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 & 0 \\ & & \frac{E A_z}{L_e} & 0 & 0 & 0 & 0 & 0 & -\frac{E A_z}{L_e} & 0 & 0 & 0 \\ - & & & \frac{\left(4 + K_{sx} \right) E J_x}{L_e \left ( 1+ K_{sx} \right )} & 0 & 0 & 0 & \frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & \frac{\left( 2-K_{sx} \right) E J_x}{L_e \left ( 1+ K_{sx} \right )} & 0 & 0 \\ - & & & & \frac{\left(4 + K_{sy} \right) E J_y}{L_e \left ( 1+ K_{sy} \right )} & 0 & -\frac{6 E J_y}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 & 0 & 0 & \frac{\left( 2-K_{sy} \right) E J_y}{L_e \left ( 1+ K_{sy} \right )} & 0 \\ + & & & \frac{\left(4 + K_{sy} \right) E J_x}{L_e \left ( 1+ K_{sy} \right )} & 0 & 0 & 0 & \frac{6 E J_x}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 & \frac{\left( 2-K_{sy} \right) E J_x}{L_e \left ( 1+ K_{sy} \right )} & 0 & 0 \\ + & & & & \frac{\left(4 + K_{sx} \right) E J_y}{L_e \left ( 1+ K_{sx} \right )} & 0 & -\frac{6 E J_y}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 & 0 & \frac{\left( 2-K_{sx} \right) E J_y}{L_e \left ( 1+ K_{sx} \right )} & 0 \\ & & & & & \frac{G J_z}{L_e} & 0 & 0 & 0 & 0 & 0 & -\frac{G J_z}{L_e} \\ - & & & & & & \frac{12 E J_y} {L_e^3 \left( 1+ K_{sy} \right)} & 0 & 0 & 0 & -\frac{6 E J_y}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 \\ - & & & & & & & \frac{12 E J_x}{L_e^3 \left( 1+ K_{sx} \right)} & 0 & \frac{6 E J_x}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 & 0 \\ + & & & & & & \frac{12 E J_y} {L_e^3 \left( 1+ K_{sx} \right)} & 0 & 0 & 0 & -\frac{6 E J_y}{L_e^2 \left ( 1+ K_{sx} \right )} & 0 \\ + & & & & & & & \frac{12 E J_x}{L_e^3 \left( 1+ K_{sy} \right)} & 0 & \frac{6 E J_x}{L_e^2 \left ( 1+ K_{sy} \right )} & 0 & 0 \\ & & & & & & & & \frac{E A_z}{L_e} & 0 & 0 & 0 \\ - & & & & & & & & & \frac{\left(4 + K_{sx} \right) E J_x}{L_e \left ( 1+ K_{sx} \right )} & 0 & 0 \\ - & & & & & & & & & & \frac{\left(4 + K_{sy} \right) E J_y}{L_e \left ( 1+ K_{sy} \right )} & 0 \\ + & & & & & & & & & \frac{\left(4 + K_{sy} \right) E J_x}{L_e \left ( 1+ K_{sy} \right )} & 0 & 0 \\ + & & & & & & & & & & \frac{\left(4 + K_{sx} \right) E J_y}{L_e \left ( 1+ K_{sx} \right )} & 0 \\ & & & & & & & & & & & \frac{G J_z}{L_e} \\ \end{bmatrix} } diff --git a/modules/hydrodyn/src/HydroDyn_Input.f90 b/modules/hydrodyn/src/HydroDyn_Input.f90 index 98d97dea82..d9960ed40b 100644 --- a/modules/hydrodyn/src/HydroDyn_Input.f90 +++ b/modules/hydrodyn/src/HydroDyn_Input.f90 @@ -453,64 +453,104 @@ SUBROUTINE HydroDyn_ParseInput( InputFileName, OutRootName, FileInfo_In, InputFi !------------------------------------------------------------------------------------------------- - ! Member Cross-section Properties Section + ! Cylindrical Member Cross-section Properties Section !------------------------------------------------------------------------------------------------- if ( InputFileData%Echo ) WRITE(UnEc, '(A)') trim(FileInfo_In%Lines(CurLine)) ! Write section break to echo CurLine = CurLine + 1 - ! NPropSets - Number of member cross-section property sets - call ParseVar( FileInfo_In, CurLine, 'NPropSets', InputFileData%Morison%NPropSets, ErrStat2, ErrMsg2, UnEc ) + ! NPropSetsCyl - Number of cylindrical member cross-section property sets + call ParseVar( FileInfo_In, CurLine, 'NPropSetsCyl', InputFileData%Morison%NPropSetsCyl, ErrStat2, ErrMsg2, UnEc ) if (Failed()) return; ! Table header - if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'MPropSets table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'MPropSetsCyl table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) CurLine = CurLine + 1 - if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'MPropSets table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'MPropSetsCyl table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) CurLine = CurLine + 1 - IF ( InputFileData%Morison%NPropSets > 0 ) THEN + IF ( InputFileData%Morison%NPropSetsCyl > 0 ) THEN - CALL AllocAry( tmpReArray, 3, 'temporary array for MPropSets', ErrStat2, ErrMsg2 ) + CALL AllocAry( tmpReArray, 3, 'temporary array for MPropSetsCyl', ErrStat2, ErrMsg2 ) if (Failed()) return; ! Allocate memory for Member cross-section property set-related arrays - ALLOCATE ( InputFileData%Morison%MPropSets(InputFileData%Morison%NPropSets), STAT = ErrStat2 ) + ALLOCATE ( InputFileData%Morison%MPropSetsCyl(InputFileData%Morison%NPropSetsCyl), STAT = ErrStat2 ) IF ( ErrStat2 /= 0 ) THEN ErrStat2 = ErrID_Fatal - ErrMsg2 = 'Error allocating space for MPropSets array.' + ErrMsg2 = 'Error allocating space for MPropSetsCyl array.' if (Failed()) return; END IF - DO I = 1,InputFileData%Morison%NPropSets - call ParseAry( FileInfo_In, CurLine, ' MPropSets line '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), ErrStat2, ErrMsg2, UnEc ) + DO I = 1,InputFileData%Morison%NPropSetsCyl + call ParseAry( FileInfo_In, CurLine, ' MPropSetsCyl line '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), ErrStat2, ErrMsg2, UnEc ) if (Failed()) return; - InputFileData%Morison%MPropSets(I)%PropSetID = NINT(tmpReArray(1)) - InputFileData%Morison%MPropSets(I)%PropD = tmpReArray(2) - InputFileData%Morison%MPropSets(I)%PropThck = tmpReArray(3) + InputFileData%Morison%MPropSetsCyl(I)%PropSetID = NINT(tmpReArray(1)) + InputFileData%Morison%MPropSetsCyl(I)%PropD = tmpReArray(2) + InputFileData%Morison%MPropSetsCyl(I)%PropThck = tmpReArray(3) END DO if (allocated(tmpReArray)) deallocate(tmpReArray) END IF + !------------------------------------------------------------------------------------------------- + ! Rectangular Member Cross-section Properties Section + !------------------------------------------------------------------------------------------------- + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') trim(FileInfo_In%Lines(CurLine)) ! Write section break to echo + CurLine = CurLine + 1 + + ! NPropSetsRec - Number of rectangular member cross-section property sets + call ParseVar( FileInfo_In, CurLine, 'NPropSetsRec', InputFileData%Morison%NPropSetsRec, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return; + + ! Table header + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'MPropSetsRec table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + CurLine = CurLine + 1 + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'MPropSetsRec table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + CurLine = CurLine + 1 + + IF ( InputFileData%Morison%NPropSetsRec > 0 ) THEN + + CALL AllocAry( tmpReArray, 4, 'temporary array for MPropSetsRec', ErrStat2, ErrMsg2 ) + if (Failed()) return; + + ! Allocate memory for Member cross-section property set-related arrays + ALLOCATE ( InputFileData%Morison%MPropSetsRec(InputFileData%Morison%NPropSetsRec), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + ErrStat2 = ErrID_Fatal + ErrMsg2 = 'Error allocating space for MPropSetsRec array.' + if (Failed()) return; + END IF + + DO I = 1,InputFileData%Morison%NPropSetsRec + call ParseAry( FileInfo_In, CurLine, ' MPropSetsRec line '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return; + InputFileData%Morison%MPropSetsRec(I)%PropSetID = NINT(tmpReArray(1)) + InputFileData%Morison%MPropSetsRec(I)%PropA = tmpReArray(2) + InputFileData%Morison%MPropSetsRec(I)%PropB = tmpReArray(3) + InputFileData%Morison%MPropSetsRec(I)%PropThck = tmpReArray(4) + END DO + + if (allocated(tmpReArray)) deallocate(tmpReArray) + END IF !------------------------------------------------------------------------------------------------- - ! Simple hydrodynamic coefficients Section + ! Simple cylindrical member hydrodynamic coefficients Section !------------------------------------------------------------------------------------------------- if ( InputFileData%Echo ) WRITE(UnEc, '(A)') trim(FileInfo_In%Lines(CurLine)) ! Write section break to echo CurLine = CurLine + 1 ! Table header - if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Simple hydrodynamic coefficients table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Simple cylindrical member hydrodynamic coefficients table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) CurLine = CurLine + 1 - if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Simple hydrodynamic coefficients table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Simple cylindrical member hydrodynamic coefficients table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) CurLine = CurLine + 1 - CALL AllocAry( tmpReArray, 14, 'temporary array for Simple hydrodynamic coefficients', ErrStat2, ErrMsg2 ) + CALL AllocAry( tmpReArray, 14, 'temporary array for Simple cylindrical member hydrodynamic coefficients', ErrStat2, ErrMsg2 ) if (Failed()) return - ! call ParseAry( FileInfo_In, CurLine, 'Simple hydrodynamic coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), ErrStat2, ErrMsg2, UnEc ) + ! call ParseAry( FileInfo_In, CurLine, 'Simple cylindrical member hydrodynamic coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), ErrStat2, ErrMsg2, UnEc ) ! if (Failed()) return; - CALL ParseRAryWKywrd( FileInfo_In, CurLine, 'Simple hydrodynamic coefficients table row '//trim( Int2LStr(1_IntKi)), tmpReArray, size(tmpReArray), & + CALL ParseRAryWKywrd( FileInfo_In, CurLine, 'Simple cylindrical member hydrodynamic coefficients table row '//trim( Int2LStr(1_IntKi)), tmpReArray, size(tmpReArray), & 'MCF', 1.0_ReKi, (/5,6/), InputFileData%Morison%SimplMCF, ErrStat2, ErrMsg2, UnEc ) if (Failed()) return @@ -532,63 +572,100 @@ SUBROUTINE HydroDyn_ParseInput( InputFileName, OutRootName, FileInfo_In, InputFi if (allocated(tmpReArray)) deallocate(tmpReArray) !------------------------------------------------------------------------------------------------- - ! Depth-based Hydrodynamic Coefficients Section + ! Simple rectangular member hydrodynamic coefficients Section !------------------------------------------------------------------------------------------------- if ( InputFileData%Echo ) WRITE(UnEc, '(A)') trim(FileInfo_In%Lines(CurLine)) ! Write section break to echo CurLine = CurLine + 1 - ! NCoefDpth - Number of depth-based hydrodynamic coefficient property sets - call ParseVar( FileInfo_In, CurLine, 'NCoefDpth', InputFileData%Morison%NCoefDpth, ErrStat2, ErrMsg2, UnEc ) + ! Table header + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Simple rectangular member hydrodynamic coefficients table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + CurLine = CurLine + 1 + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Simple rectangular member hydrodynamic coefficients table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + CurLine = CurLine + 1 + + + CALL AllocAry( tmpReArray, 18, 'temporary array for Simple rectangular member hydrodynamic coefficients', ErrStat2, ErrMsg2 ) + if (Failed()) return + CALL ParseRAryWKywrd( FileInfo_In, CurLine, 'Simple rectangular member hydrodynamic coefficients table row '//trim( Int2LStr(1_IntKi)), tmpReArray, size(tmpReArray), & + 'MCF', 1.0_ReKi, (/9,10/), InputFileData%Morison%SimplRecMCF, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + InputFileData%Morison%SimplRecCdA = tmpReArray( 1) + InputFileData%Morison%SimplRecCdAMG = tmpReArray( 2) + InputFileData%Morison%SimplRecCdB = tmpReArray( 3) + InputFileData%Morison%SimplRecCdBMG = tmpReArray( 4) + InputFileData%Morison%SimplRecCaA = tmpReArray( 5) + InputFileData%Morison%SimplRecCaAMG = tmpReArray( 6) + InputFileData%Morison%SimplRecCaB = tmpReArray( 7) + InputFileData%Morison%SimplRecCaBMG = tmpReArray( 8) + InputFileData%Morison%SimplRecCp = tmpReArray( 9) + InputFileData%Morison%SimplRecCpMG = tmpReArray(10) + InputFileData%Morison%SimplRecAxCd = tmpReArray(11) + InputFileData%Morison%SimplRecAxCdMG = tmpReArray(12) + InputFileData%Morison%SimplRecAxCa = tmpReArray(13) + InputFileData%Morison%SimplRecAxCaMG = tmpReArray(14) + InputFileData%Morison%SimplRecAxCp = tmpReArray(15) + InputFileData%Morison%SimplRecAxCpMG = tmpReArray(16) + InputFileData%Morison%SimplRecCb = tmpReArray(17) + InputFileData%Morison%SimplRecCbMG = tmpReArray(18) + + if (allocated(tmpReArray)) deallocate(tmpReArray) + + !------------------------------------------------------------------------------------------------- + ! Depth-based Cylindrical Member Hydrodynamic Coefficients Section + !------------------------------------------------------------------------------------------------- + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') trim(FileInfo_In%Lines(CurLine)) ! Write section break to echo + CurLine = CurLine + 1 + + ! NCoefDpthCyl - Number of depth-based cylindrical member hydrodynamic coefficient property sets + call ParseVar( FileInfo_In, CurLine, 'NCoefDpthCyl', InputFileData%Morison%NCoefDpthCyl, ErrStat2, ErrMsg2, UnEc ) if (Failed()) return; ! Table header - if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Depth-based hydrodynamic coefficients table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Depth-based cylindrical member hydrodynamic coefficients table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) CurLine = CurLine + 1 - if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Depth-based hydrodynamic coefficients table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Depth-based cylindrical member hydrodynamic coefficients table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) CurLine = CurLine + 1 - IF ( InputFileData%Morison%NCoefDpth > 0 ) THEN + IF ( InputFileData%Morison%NCoefDpthCyl > 0 ) THEN - CALL AllocAry( tmpReArray, 15, 'temporary array for CoefDpths', ErrStat2, ErrMsg2 ) + CALL AllocAry( tmpReArray, 15, 'temporary array for CoefDpthsCyl', ErrStat2, ErrMsg2 ) if (Failed()) return; ! Allocate memory for depth-based coefficient arrays - ALLOCATE ( InputFileData%Morison%CoefDpths(InputFileData%Morison%NCoefDpth), STAT = ErrStat2 ) + ALLOCATE ( InputFileData%Morison%CoefDpthsCyl(InputFileData%Morison%NCoefDpthCyl), STAT = ErrStat2 ) IF ( ErrStat2 /= 0 ) THEN ErrStat2 = ErrID_Fatal - ErrMsg2 = 'Error allocating space for CoefDpths array.' + ErrMsg2 = 'Error allocating space for CoefDpthsCyl array.' if (Failed()) return; END IF - DO I = 1,InputFileData%Morison%NCoefDpth - ! call ParseAry( FileInfo_In, CurLine, ' CoefDpths coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), ErrStat2, ErrMsg2, UnEc ) - ! if (Failed()) return; - CALL ParseRAryWKywrd( FileInfo_In, CurLine, ' CoefDpths coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), & - 'MCF', 1.0_ReKi, (/6,7/), InputFileData%Morison%CoefDpths(I)%DpthMCF, ErrStat2, ErrMsg2, UnEc ) + DO I = 1,InputFileData%Morison%NCoefDpthCyl + CALL ParseRAryWKywrd( FileInfo_In, CurLine, ' CoefDpthsCyl coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), & + 'MCF', 1.0_ReKi, (/6,7/), InputFileData%Morison%CoefDpthsCyl(I)%DpthMCF, ErrStat2, ErrMsg2, UnEc ) if (Failed()) return - - InputFileData%Morison%CoefDpths(I)%Dpth = tmpReArray( 1) - InputFileData%Morison%CoefDpths(I)%DpthCd = tmpReArray( 2) - InputFileData%Morison%CoefDpths(I)%DpthCdMG = tmpReArray( 3) - InputFileData%Morison%CoefDpths(I)%DpthCa = tmpReArray( 4) - InputFileData%Morison%CoefDpths(I)%DpthCaMG = tmpReArray( 5) - InputFileData%Morison%CoefDpths(I)%DpthCp = tmpReArray( 6) - InputFileData%Morison%CoefDpths(I)%DpthCpMG = tmpReArray( 7) - InputFileData%Morison%CoefDpths(I)%DpthAxCd = tmpReArray( 8) - InputFileData%Morison%CoefDpths(I)%DpthAxCdMG = tmpReArray( 9) - InputFileData%Morison%CoefDpths(I)%DpthAxCa = tmpReArray(10) - InputFileData%Morison%CoefDpths(I)%DpthAxCaMG = tmpReArray(11) - InputFileData%Morison%CoefDpths(I)%DpthAxCp = tmpReArray(12) - InputFileData%Morison%CoefDpths(I)%DpthAxCpMG = tmpReArray(13) - InputFileData%Morison%CoefDpths(I)%DpthCb = tmpReArray(14) - InputFileData%Morison%CoefDpths(I)%DpthCbMG = tmpReArray(15) + InputFileData%Morison%CoefDpthsCyl(I)%Dpth = tmpReArray( 1) + InputFileData%Morison%CoefDpthsCyl(I)%DpthCd = tmpReArray( 2) + InputFileData%Morison%CoefDpthsCyl(I)%DpthCdMG = tmpReArray( 3) + InputFileData%Morison%CoefDpthsCyl(I)%DpthCa = tmpReArray( 4) + InputFileData%Morison%CoefDpthsCyl(I)%DpthCaMG = tmpReArray( 5) + InputFileData%Morison%CoefDpthsCyl(I)%DpthCp = tmpReArray( 6) + InputFileData%Morison%CoefDpthsCyl(I)%DpthCpMG = tmpReArray( 7) + InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCd = tmpReArray( 8) + InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCdMG = tmpReArray( 9) + InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCa = tmpReArray(10) + InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCaMG = tmpReArray(11) + InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCp = tmpReArray(12) + InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCpMG = tmpReArray(13) + InputFileData%Morison%CoefDpthsCyl(I)%DpthCb = tmpReArray(14) + InputFileData%Morison%CoefDpthsCyl(I)%DpthCbMG = tmpReArray(15) END DO - DO I = 2,InputFileData%Morison%NCoefDpth - IF (InputFileData%Morison%CoefDpths(I)%DpthMCF .NEQV. InputFileData%Morison%CoefDpths(1)%DpthMCF) THEN + DO I = 2,InputFileData%Morison%NCoefDpthCyl + IF (InputFileData%Morison%CoefDpthsCyl(I)%DpthMCF .NEQV. InputFileData%Morison%CoefDpthsCyl(1)%DpthMCF) THEN ErrStat2 = ErrID_Fatal - ErrMsg2 = 'In the depth-based hydrodynamic coefficients, MCF is specified for some depth but not others.' + ErrMsg2 = 'In the depth-based cylindrical member hydrodynamic coefficients, MCF is specified for some depth but not others.' if (Failed()) RETURN END IF END DO @@ -596,78 +673,218 @@ SUBROUTINE HydroDyn_ParseInput( InputFileName, OutRootName, FileInfo_In, InputFi if (allocated(tmpReArray)) deallocate(tmpReArray) END IF + !------------------------------------------------------------------------------------------------- + ! Depth-based Rectangular Member Hydrodynamic Coefficients Section + !------------------------------------------------------------------------------------------------- + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') trim(FileInfo_In%Lines(CurLine)) ! Write section break to echo + CurLine = CurLine + 1 + + ! NCoefDpthRec - Number of depth-based rectangular member hydrodynamic coefficient property sets + call ParseVar( FileInfo_In, CurLine, 'NCoefDpthRec', InputFileData%Morison%NCoefDpthRec, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return; + + ! Table header + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Depth-based rectangular member hydrodynamic coefficients table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + CurLine = CurLine + 1 + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Depth-based rectangular member hydrodynamic coefficients table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + CurLine = CurLine + 1 + + IF ( InputFileData%Morison%NCoefDpthRec > 0 ) THEN + + CALL AllocAry( tmpReArray, 19, 'temporary array for CoefDpthsRec', ErrStat2, ErrMsg2 ) + if (Failed()) return; + + ! Allocate memory for depth-based coefficient arrays + ALLOCATE ( InputFileData%Morison%CoefDpthsRec(InputFileData%Morison%NCoefDpthRec), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + ErrStat2 = ErrID_Fatal + ErrMsg2 = 'Error allocating space for CoefDpthsRec array.' + if (Failed()) return; + END IF + + DO I = 1,InputFileData%Morison%NCoefDpthRec + CALL ParseRAryWKywrd( FileInfo_In, CurLine, ' CoefDpthsRec coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), & + 'MCF', 1.0_ReKi, (/10,11/), InputFileData%Morison%CoefDpthsRec(I)%DpthMCF, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + + InputFileData%Morison%CoefDpthsRec(I)%Dpth = tmpReArray( 1) + InputFileData%Morison%CoefDpthsRec(I)%DpthCdA = tmpReArray( 2) + InputFileData%Morison%CoefDpthsRec(I)%DpthCdAMG = tmpReArray( 3) + InputFileData%Morison%CoefDpthsRec(I)%DpthCdB = tmpReArray( 4) + InputFileData%Morison%CoefDpthsRec(I)%DpthCdBMG = tmpReArray( 5) + InputFileData%Morison%CoefDpthsRec(I)%DpthCaA = tmpReArray( 6) + InputFileData%Morison%CoefDpthsRec(I)%DpthCaAMG = tmpReArray( 7) + InputFileData%Morison%CoefDpthsRec(I)%DpthCaB = tmpReArray( 8) + InputFileData%Morison%CoefDpthsRec(I)%DpthCaBMG = tmpReArray( 9) + InputFileData%Morison%CoefDpthsRec(I)%DpthCp = tmpReArray(10) + InputFileData%Morison%CoefDpthsRec(I)%DpthCpMG = tmpReArray(11) + InputFileData%Morison%CoefDpthsRec(I)%DpthAxCd = tmpReArray(12) + InputFileData%Morison%CoefDpthsRec(I)%DpthAxCdMG = tmpReArray(13) + InputFileData%Morison%CoefDpthsRec(I)%DpthAxCa = tmpReArray(14) + InputFileData%Morison%CoefDpthsRec(I)%DpthAxCaMG = tmpReArray(15) + InputFileData%Morison%CoefDpthsRec(I)%DpthAxCp = tmpReArray(16) + InputFileData%Morison%CoefDpthsRec(I)%DpthAxCpMG = tmpReArray(17) + InputFileData%Morison%CoefDpthsRec(I)%DpthCb = tmpReArray(18) + InputFileData%Morison%CoefDpthsRec(I)%DpthCbMG = tmpReArray(19) + END DO + + DO I = 2,InputFileData%Morison%NCoefDpthRec + IF (InputFileData%Morison%CoefDpthsRec(I)%DpthMCF .NEQV. InputFileData%Morison%CoefDpthsRec(1)%DpthMCF) THEN + ErrStat2 = ErrID_Fatal + ErrMsg2 = 'In the depth-based rectangular member hydrodynamic coefficients, MCF is specified for some depth but not others.' + if (Failed()) RETURN + END IF + END DO + + if (allocated(tmpReArray)) deallocate(tmpReArray) + END IF !------------------------------------------------------------------------------------------------- - ! Member-based Hydrodynamic Coefficients Section + ! Member-based Cylindrical Member Hydrodynamic Coefficients Section !------------------------------------------------------------------------------------------------- if ( InputFileData%Echo ) WRITE(UnEc, '(A)') trim(FileInfo_In%Lines(CurLine)) ! Write section break to echo CurLine = CurLine + 1 - ! NCoefMembers - Number of member-based hydrodynamic coefficient property sets - call ParseVar( FileInfo_In, CurLine, 'NCoefMembers', InputFileData%Morison%NCoefMembers, ErrStat2, ErrMsg2, UnEc ) + ! NCoefMembersCyl - Number of member-based cylindrical member hydrodynamic coefficient property sets + call ParseVar( FileInfo_In, CurLine, 'NCoefMembersCyl', InputFileData%Morison%NCoefMembersCyl, ErrStat2, ErrMsg2, UnEc ) if (Failed()) return; ! Table header - if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Member-based hydrodynamic coefficients table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Member-based cylindrical member hydrodynamic coefficients table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) CurLine = CurLine + 1 - if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Member-based hydrodynamic coefficients table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Member-based cylindrical member hydrodynamic coefficients table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) CurLine = CurLine + 1 - IF ( InputFileData%Morison%NCoefMembers > 0 ) THEN + IF ( InputFileData%Morison%NCoefMembersCyl > 0 ) THEN - CALL AllocAry( tmpReArray, 29, 'temporary array for CoefMembers', ErrStat2, ErrMsg2 ) + CALL AllocAry( tmpReArray, 29, 'temporary array for CoefMembersCyl', ErrStat2, ErrMsg2 ) if (Failed()) return; ! Allocate memory for Member-based coefficient arrays - ALLOCATE ( InputFileData%Morison%CoefMembers(InputFileData%Morison%NCoefMembers), STAT = ErrStat2 ) + ALLOCATE ( InputFileData%Morison%CoefMembersCyl(InputFileData%Morison%NCoefMembersCyl), STAT = ErrStat2 ) IF ( ErrStat2 /= 0 ) THEN ErrStat2 = ErrID_Fatal - ErrMsg2 = 'Error allocating space for CoefMembers array.' + ErrMsg2 = 'Error allocating space for CoefMembersCyl array.' if (Failed()) return; END IF - DO I = 1,InputFileData%Morison%NCoefMembers - !call ParseAry( FileInfo_In, CurLine, 'Member-based hydrodynamic coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), ErrStat2, ErrMsg2, UnEc ) - ! if (Failed()) return; + DO I = 1,InputFileData%Morison%NCoefMembersCyl - CALL ParseRAryWKywrd( FileInfo_In, CurLine, 'Member-based hydrodynamic coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), & - 'MCF', 1.0_ReKi, (/10,11,12,13/), InputFileData%Morison%CoefMembers(I)%MemberMCF, ErrStat2, ErrMsg2, UnEc ) + CALL ParseRAryWKywrd( FileInfo_In, CurLine, 'Member-based cylindrical member hydrodynamic coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), & + 'MCF', 1.0_ReKi, (/10,11,12,13/), InputFileData%Morison%CoefMembersCyl(I)%MemberMCF, ErrStat2, ErrMsg2, UnEc ) if (Failed()) return - InputFileData%Morison%CoefMembers(I)%MemberID = NINT(tmpReArray( 1)) - InputFileData%Morison%CoefMembers(I)%MemberCd1 = tmpReArray( 2) - InputFileData%Morison%CoefMembers(I)%MemberCd2 = tmpReArray( 3) - InputFileData%Morison%CoefMembers(I)%MemberCdMG1 = tmpReArray( 4) - InputFileData%Morison%CoefMembers(I)%MemberCdMG2 = tmpReArray( 5) - InputFileData%Morison%CoefMembers(I)%MemberCa1 = tmpReArray( 6) - InputFileData%Morison%CoefMembers(I)%MemberCa2 = tmpReArray( 7) - InputFileData%Morison%CoefMembers(I)%MemberCaMG1 = tmpReArray( 8) - InputFileData%Morison%CoefMembers(I)%MemberCaMG2 = tmpReArray( 9) - InputFileData%Morison%CoefMembers(I)%MemberCp1 = tmpReArray(10) - InputFileData%Morison%CoefMembers(I)%MemberCp2 = tmpReArray(11) - InputFileData%Morison%CoefMembers(I)%MemberCpMG1 = tmpReArray(12) - InputFileData%Morison%CoefMembers(I)%MemberCpMG2 = tmpReArray(13) - InputFileData%Morison%CoefMembers(I)%MemberAxCd1 = tmpReArray(14) - InputFileData%Morison%CoefMembers(I)%MemberAxCd2 = tmpReArray(15) - InputFileData%Morison%CoefMembers(I)%MemberAxCdMG1 = tmpReArray(16) - InputFileData%Morison%CoefMembers(I)%MemberAxCdMG2 = tmpReArray(17) - InputFileData%Morison%CoefMembers(I)%MemberAxCa1 = tmpReArray(18) - InputFileData%Morison%CoefMembers(I)%MemberAxCa2 = tmpReArray(19) - InputFileData%Morison%CoefMembers(I)%MemberAxCaMG1 = tmpReArray(20) - InputFileData%Morison%CoefMembers(I)%MemberAxCaMG2 = tmpReArray(21) - InputFileData%Morison%CoefMembers(I)%MemberAxCp1 = tmpReArray(22) - InputFileData%Morison%CoefMembers(I)%MemberAxCp2 = tmpReArray(23) - InputFileData%Morison%CoefMembers(I)%MemberAxCpMG1 = tmpReArray(24) - InputFileData%Morison%CoefMembers(I)%MemberAxCpMG2 = tmpReArray(25) - InputFileData%Morison%CoefMembers(I)%MemberCb1 = tmpReArray(26) - InputFileData%Morison%CoefMembers(I)%MemberCb2 = tmpReArray(27) - InputFileData%Morison%CoefMembers(I)%MemberCbMG1 = tmpReArray(28) - InputFileData%Morison%CoefMembers(I)%MemberCbMG2 = tmpReArray(29) + InputFileData%Morison%CoefMembersCyl(I)%MemberID = NINT(tmpReArray( 1)) + InputFileData%Morison%CoefMembersCyl(I)%MemberCd1 = tmpReArray( 2) + InputFileData%Morison%CoefMembersCyl(I)%MemberCd2 = tmpReArray( 3) + InputFileData%Morison%CoefMembersCyl(I)%MemberCdMG1 = tmpReArray( 4) + InputFileData%Morison%CoefMembersCyl(I)%MemberCdMG2 = tmpReArray( 5) + InputFileData%Morison%CoefMembersCyl(I)%MemberCa1 = tmpReArray( 6) + InputFileData%Morison%CoefMembersCyl(I)%MemberCa2 = tmpReArray( 7) + InputFileData%Morison%CoefMembersCyl(I)%MemberCaMG1 = tmpReArray( 8) + InputFileData%Morison%CoefMembersCyl(I)%MemberCaMG2 = tmpReArray( 9) + InputFileData%Morison%CoefMembersCyl(I)%MemberCp1 = tmpReArray(10) + InputFileData%Morison%CoefMembersCyl(I)%MemberCp2 = tmpReArray(11) + InputFileData%Morison%CoefMembersCyl(I)%MemberCpMG1 = tmpReArray(12) + InputFileData%Morison%CoefMembersCyl(I)%MemberCpMG2 = tmpReArray(13) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCd1 = tmpReArray(14) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCd2 = tmpReArray(15) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCdMG1 = tmpReArray(16) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCdMG2 = tmpReArray(17) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCa1 = tmpReArray(18) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCa2 = tmpReArray(19) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCaMG1 = tmpReArray(20) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCaMG2 = tmpReArray(21) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCp1 = tmpReArray(22) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCp2 = tmpReArray(23) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCpMG1 = tmpReArray(24) + InputFileData%Morison%CoefMembersCyl(I)%MemberAxCpMG2 = tmpReArray(25) + InputFileData%Morison%CoefMembersCyl(I)%MemberCb1 = tmpReArray(26) + InputFileData%Morison%CoefMembersCyl(I)%MemberCb2 = tmpReArray(27) + InputFileData%Morison%CoefMembersCyl(I)%MemberCbMG1 = tmpReArray(28) + InputFileData%Morison%CoefMembersCyl(I)%MemberCbMG2 = tmpReArray(29) END DO if (allocated(tmpReArray)) deallocate(tmpReArray) END IF + !------------------------------------------------------------------------------------------------- + ! Member-based Rectangular Member Hydrodynamic Coefficients Section + !------------------------------------------------------------------------------------------------- + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') trim(FileInfo_In%Lines(CurLine)) ! Write section break to echo + CurLine = CurLine + 1 + + ! NCoefMembersRec - Number of member-based rectangular member hydrodynamic coefficient property sets + call ParseVar( FileInfo_In, CurLine, 'NCoefMembersRec', InputFileData%Morison%NCoefMembersRec, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return; + + ! Table header + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Member-based rectangular member hydrodynamic coefficients table header line 1: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + CurLine = CurLine + 1 + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Member-based rectangular member hydrodynamic coefficients table header line 2: '//NewLine//trim(FileInfo_In%Lines(CurLine)) + CurLine = CurLine + 1 + + IF ( InputFileData%Morison%NCoefMembersRec > 0 ) THEN + + CALL AllocAry( tmpReArray, 37, 'temporary array for CoefMembersRec', ErrStat2, ErrMsg2 ) + if (Failed()) return; + + ! Allocate memory for Member-based coefficient arrays + ALLOCATE ( InputFileData%Morison%CoefMembersRec(InputFileData%Morison%NCoefMembersRec), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + ErrStat2 = ErrID_Fatal + ErrMsg2 = 'Error allocating space for CoefMembersRec array.' + if (Failed()) return; + END IF + + DO I = 1,InputFileData%Morison%NCoefMembersRec + + CALL ParseRAryWKywrd( FileInfo_In, CurLine, 'Member-based rectangular member hydrodynamic coefficients table row '//trim( Int2LStr(I)), tmpReArray, size(tmpReArray), & + 'MCF', 1.0_ReKi, (/18,19,20,21/), InputFileData%Morison%CoefMembersRec(I)%MemberMCF, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + InputFileData%Morison%CoefMembersRec(I)%MemberID = NINT(tmpReArray( 1)) + InputFileData%Morison%CoefMembersRec(I)%MemberCdA1 = tmpReArray( 2) + InputFileData%Morison%CoefMembersRec(I)%MemberCdA2 = tmpReArray( 3) + InputFileData%Morison%CoefMembersRec(I)%MemberCdAMG1 = tmpReArray( 4) + InputFileData%Morison%CoefMembersRec(I)%MemberCdAMG2 = tmpReArray( 5) + InputFileData%Morison%CoefMembersRec(I)%MemberCdB1 = tmpReArray( 6) + InputFileData%Morison%CoefMembersRec(I)%MemberCdB2 = tmpReArray( 7) + InputFileData%Morison%CoefMembersRec(I)%MemberCdBMG1 = tmpReArray( 8) + InputFileData%Morison%CoefMembersRec(I)%MemberCdBMG2 = tmpReArray( 9) + InputFileData%Morison%CoefMembersRec(I)%MemberCaA1 = tmpReArray(10) + InputFileData%Morison%CoefMembersRec(I)%MemberCaA2 = tmpReArray(11) + InputFileData%Morison%CoefMembersRec(I)%MemberCaAMG1 = tmpReArray(12) + InputFileData%Morison%CoefMembersRec(I)%MemberCaAMG2 = tmpReArray(13) + InputFileData%Morison%CoefMembersRec(I)%MemberCaB1 = tmpReArray(14) + InputFileData%Morison%CoefMembersRec(I)%MemberCaB2 = tmpReArray(15) + InputFileData%Morison%CoefMembersRec(I)%MemberCaBMG1 = tmpReArray(16) + InputFileData%Morison%CoefMembersRec(I)%MemberCaBMG2 = tmpReArray(17) + InputFileData%Morison%CoefMembersRec(I)%MemberCp1 = tmpReArray(18) + InputFileData%Morison%CoefMembersRec(I)%MemberCp2 = tmpReArray(19) + InputFileData%Morison%CoefMembersRec(I)%MemberCpMG1 = tmpReArray(20) + InputFileData%Morison%CoefMembersRec(I)%MemberCpMG2 = tmpReArray(21) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCd1 = tmpReArray(22) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCd2 = tmpReArray(23) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCdMG1 = tmpReArray(24) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCdMG2 = tmpReArray(25) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCa1 = tmpReArray(26) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCa2 = tmpReArray(27) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCaMG1 = tmpReArray(28) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCaMG2 = tmpReArray(29) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCp1 = tmpReArray(30) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCp2 = tmpReArray(31) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCpMG1 = tmpReArray(32) + InputFileData%Morison%CoefMembersRec(I)%MemberAxCpMG2 = tmpReArray(33) + InputFileData%Morison%CoefMembersRec(I)%MemberCb1 = tmpReArray(34) + InputFileData%Morison%CoefMembersRec(I)%MemberCb2 = tmpReArray(35) + InputFileData%Morison%CoefMembersRec(I)%MemberCbMG1 = tmpReArray(36) + InputFileData%Morison%CoefMembersRec(I)%MemberCbMG2 = tmpReArray(37) + END DO + + if (allocated(tmpReArray)) deallocate(tmpReArray) + END IF !------------------------------------------------------------------------------------------------- ! Members Section @@ -698,17 +915,19 @@ SUBROUTINE HydroDyn_ParseInput( InputFileName, OutRootName, FileInfo_In, InputFi DO I = 1,InputFileData%Morison%NMembers ! We can't use the ParseAry here since PropPot is a logical Line = FileInfo_In%Lines(CurLine) - READ(Line,*,IOSTAT=ErrStat2) InputFileData%Morison%InpMembers(I)%MemberID, InputFileData%Morison%InpMembers(I)%MJointID1, & - InputFileData%Morison%InpMembers(I)%MJointID2, InputFileData%Morison%InpMembers(I)%MPropSetID1, & - InputFileData%Morison%InpMembers(I)%MPropSetID2, InputFileData%Morison%InpMembers(I)%MDivSize, & - InputFileData%Morison%InpMembers(I)%MCoefMod, InputFileData%Morison%InpMembers(I)%MHstLMod, & - InputFileData%Morison%InpMembers(I)%PropPot + READ(Line,*,IOSTAT=ErrStat2) InputFileData%Morison%InpMembers(I)%MemberID, InputFileData%Morison%InpMembers(I)%MJointID1, & + InputFileData%Morison%InpMembers(I)%MJointID2, InputFileData%Morison%InpMembers(I)%MPropSetID1, & + InputFileData%Morison%InpMembers(I)%MPropSetID2, InputFileData%Morison%InpMembers(I)%MSecGeom, & + InputFileData%Morison%InpMembers(I)%MSpinOrient, InputFileData%Morison%InpMembers(I)%MDivSize, & + InputFileData%Morison%InpMembers(I)%MCoefMod, InputFileData%Morison%InpMembers(I)%MHstLMod, & + InputFileData%Morison%InpMembers(I)%PropPot IF ( ErrStat2 /= 0 ) THEN ErrStat2 = ErrID_Fatal ErrMsg2 = 'Error reading members table row '//trim( Int2LStr(I))//', line ' & //trim( Int2LStr(FileInfo_In%FileLine(CurLine)))//' of file '//trim(FileInfo_In%FileList(FileInfo_In%FileIndx(CurLine))) if (Failed()) return; END IF + InputFileData%Morison%InpMembers(I)%MSpinOrient = InputFileData%Morison%InpMembers(I)%MSpinOrient * D2R if ( InputFileData%Echo ) WRITE(UnEc, '(A)') trim(FileInfo_In%Lines(CurLine)) ! Echo this line CurLine = CurLine+1 @@ -1117,8 +1336,10 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, Interval, InputFileData, ErrS INTEGER :: K ! Generic loop counter index CHARACTER(1024) :: TmpPath ! Temporary storage for relative path name LOGICAL :: FoundID ! Boolean flag indicating whether an ID from one tables is found in one of the other input table - REAL(ReKi) :: MinDepth ! The minimum depth entry in the Depth-based Hydrodynamic coefficents table - REAL(ReKi) :: MaxDepth ! The maximum depth entry in the Depth-based Hydrodynamic coefficents table + REAL(ReKi) :: MinCylDepth ! The minimum depth entry in the Depth-based cylindrical-member Hydrodynamic coefficents table + REAL(ReKi) :: MaxCylDepth ! The maximum depth entry in the Depth-based cylindrical-member Hydrodynamic coefficents table + REAL(ReKi) :: MinRecDepth ! The minimum depth entry in the Depth-based rectangular-member Hydrodynamic coefficents table + REAL(ReKi) :: MaxRecDepth ! The maximum depth entry in the Depth-based rectangular-member Hydrodynamic coefficents table REAL(ReKi) :: z1 REAL(ReKi) :: z2 REAL(ReKi) :: MinMembrDpth @@ -1693,260 +1914,384 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, Interval, InputFileData, ErrS ! Member Cross-section Properties Section !------------------------------------------------------------------------------------------------- - IF ( InputFileData%Morison%NPropSets < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'Number of member cross-section property sets must be greater than zero.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%Morison%NPropSetsCyl < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Number of cylindrical member cross-section property sets must be greater than zero.',ErrStat,ErrMsg,RoutineName) RETURN END IF - IF ( InputFileData%Morison%NPropSets > 0 ) THEN + IF ( InputFileData%Morison%NPropSetsCyl > 0 ) THEN - DO I = 1,InputFileData%Morison%NPropSets + DO I = 1,InputFileData%Morison%NPropSetsCyl ! Make sure that the current JointID is not used elsewhere in the table. - DO J = I+1,InputFileData%Morison%NPropSets - IF ( InputFileData%Morison%MPropSets(I)%PropSetID == InputFileData%Morison%MPropSets(J)%PropSetID ) THEN - CALL SetErrStat( ErrID_Fatal,'Duplicate PropSetIDs were found in the Member Cross-section Properties table.',ErrStat,ErrMsg,RoutineName) + DO J = I+1,InputFileData%Morison%NPropSetsCyl + IF ( InputFileData%Morison%MPropSetsCyl(I)%PropSetID == InputFileData%Morison%MPropSetsCyl(J)%PropSetID ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate PropSetIDs were found in the Cylindrical Member Cross-section Properties table.',ErrStat,ErrMsg,RoutineName) RETURN END IF END DO - IF ( ( InputFileData%Morison%MPropSets(I)%PropD < 0 ) .OR. ( InputFileData%Morison%MPropSets(I)%PropThck < 0 ) .OR. ( ( InputFileData%Morison%MPropSets(I)%PropD - InputFileData%Morison%MPropSets(I)%PropThck / 2.0 ) < 0) ) THEN - CALL SetErrStat( ErrID_Fatal,'PropD and PropThck must be greater than zero and (PropD - propThck/2 ) must be greater than zero.',ErrStat,ErrMsg,RoutineName) + IF ( ( InputFileData%Morison%MPropSetsCyl(I)%PropD < 0 ) .OR. ( InputFileData%Morison%MPropSetsCyl(I)%PropThck < 0 ) .OR. ( ( InputFileData%Morison%MPropSetsCyl(I)%PropD - 2.0 * InputFileData%Morison%MPropSetsCyl(I)%PropThck ) < 0) ) THEN + CALL SetErrStat( ErrID_Fatal,'For cylindrical members, PropD and PropThck must be greater than zero and (PropD - 2*PropThck) must be greater than zero.',ErrStat,ErrMsg,RoutineName) RETURN END IF END DO END IF + IF ( InputFileData%Morison%NPropSetsRec < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'Number of rectangular member cross-section property sets must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InputFileData%Morison%NPropSetsRec > 0 ) THEN + + DO I = 1,InputFileData%Morison%NPropSetsRec + + ! Make sure that the current JointID is not used elsewhere in the table. + DO J = I+1,InputFileData%Morison%NPropSetsRec + IF ( InputFileData%Morison%MPropSetsRec(I)%PropSetID == InputFileData%Morison%MPropSetsRec(J)%PropSetID ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate PropSetIDs were found in the Rectangular Member Cross-section Properties table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + IF ( ( InputFileData%Morison%MPropSetsRec(I)%PropA < 0 ) .OR. ( InputFileData%Morison%MPropSetsRec(I)%PropB < 0 ) .OR. ( InputFileData%Morison%MPropSetsRec(I)%PropThck < 0 ) .OR. ( ( InputFileData%Morison%MPropSetsRec(I)%PropA - 2.0 * InputFileData%Morison%MPropSetsRec(I)%PropThck ) < 0) .OR. ( ( InputFileData%Morison%MPropSetsRec(I)%PropB - 2.0 * InputFileData%Morison%MPropSetsRec(I)%PropThck ) < 0) ) THEN + CALL SetErrStat( ErrID_Fatal,'For rectangular members, PropA, PropB, and PropThck must be greater than zero and (PropA - 2*PropThck) and (PropB - 2*PropThck) must be greater than zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + END IF !------------------------------------------------------------------------------------------------- ! Simple hydrodynamic coefficients Section !------------------------------------------------------------------------------------------------- IF ( InputFileData%Morison%SimplCd < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%SimplCdMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%SimplCa < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%SimplCaMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%SimplAxCd < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplAxCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%SimplAxCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCd must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCdMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCa must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplCaMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCaMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplAxCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplAxCd must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplAxCdMG < 0 ) THEN CALL SetErrStat( ErrID_Fatal,'SimplAxCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%SimplAxCa < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplAxCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%SimplAxCaMG < 0 ) THEN + ELSE IF ( InputFileData%Morison%SimplAxCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplAxCa must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplAxCaMG < 0 ) THEN CALL SetErrStat( ErrID_Fatal,'SimplAxCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%SimplCb < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplCb must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN + ELSE IF ( InputFileData%Morison%SimplCb < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCb must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplCbMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplCbMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) END IF - IF ( InputFileData%Morison%SimplCbMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'SimplCbMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN + IF (ErrStat >= AbortErrLev) RETURN + + IF ( InputFileData%Morison%SimplRecCdA < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCdA must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecCdAMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCdAMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecCdB < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCdB must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecCdBMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCdBMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecCaA < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCaA must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecCaAMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCaAMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecCaB < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCaB must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecCaBMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCaBMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecAxCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecAxCd must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecAxCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecAxCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecAxCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecAxCa must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecAxCaMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecAxCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecCb < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCb must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%SimplRecCbMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'SimplRecCbMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) END IF + IF (ErrStat >= AbortErrLev) RETURN + !TODO: Do we need a test for AxCp !------------------------------------------------------------------------------------------------- ! Depth-based Hydrodynamic Coefficients Section !------------------------------------------------------------------------------------------------- - IF ( InputFileData%Morison%NCoefDpth < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'NCoefDpth must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%Morison%NCoefDpthCyl < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefDpthCyl must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) RETURN END IF - - IF ( InputFileData%Morison%NCoefDpth > 0 ) THEN - MinDepth = 99999999.0 - MaxDepth = -99999999.0 - DO I = 1,InputFileData%Morison%NCoefDpth + IF ( InputFileData%Morison%NCoefDpthCyl > 0 ) THEN + MinCylDepth = 99999999.0 + MaxCylDepth = -99999999.0 + DO I = 1,InputFileData%Morison%NCoefDpthCyl ! Record the minimum and maximum depths covered by this table. This will be used as part of a consistency check ! in the members table, below. - IF ( InputFileData%Morison%CoefDpths(I)%Dpth < MinDepth ) THEN - MinDepth = InputFileData%Morison%CoefDpths(I)%Dpth + IF ( InputFileData%Morison%CoefDpthsCyl(I)%Dpth < MinCylDepth ) THEN + MinCylDepth = InputFileData%Morison%CoefDpthsCyl(I)%Dpth ELSE CALL SetErrStat( ErrID_Fatal,'The rows of the Depth-based Hydrodynamic Coefficients table must be ordered with increasing depth (decreasing Z).',ErrStat,ErrMsg,RoutineName) RETURN END IF - IF ( InputFileData%Morison%CoefDpths(I)%Dpth > MaxDepth ) THEN - MaxDepth = InputFileData%Morison%CoefDpths(I)%Dpth + IF ( InputFileData%Morison%CoefDpthsCyl(I)%Dpth > MaxCylDepth ) THEN + MaxCylDepth = InputFileData%Morison%CoefDpthsCyl(I)%Dpth END IF ! Make sure that the current Dpth is not used elsewhere in the table. - DO J = I+1,InputFileData%Morison%NCoefDpth - IF ( EqualRealNos( InputFileData%Morison%CoefDpths(I)%Dpth, InputFileData%Morison%CoefDpths(J)%Dpth ) ) THEN - CALL SetErrStat( ErrID_Fatal,'Duplicate Dpths were found in the Depth-based Hydrodynamic Coefficients table.',ErrStat,ErrMsg,RoutineName) + DO J = I+1,InputFileData%Morison%NCoefDpthCyl + IF ( EqualRealNos( InputFileData%Morison%CoefDpthsCyl(I)%Dpth, InputFileData%Morison%CoefDpthsCyl(J)%Dpth ) ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate Dpths were found in the Depth-based Hydrodynamic Coefficients table for cylindrical members.',ErrStat,ErrMsg,RoutineName) RETURN END IF END DO - IF ( InputFileData%Morison%CoefDpths(I)%DpthCd < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthCdMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthCa < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthCaMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthAxCd < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCd must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthAxCdMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthAxCa < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCa must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthAxCaMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthAxCp < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCp must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthAxCpMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthAxCpMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthCb < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCb must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthCd must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthCdMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthCa must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthCaMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthCaMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthAxCd must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthAxCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthAxCa must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCaMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthAxCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCp < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthAxCp must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthAxCpMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthAxCpMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthCb < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthCb must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsCyl(I)%DpthCbMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for cylindrical members, DpthCbMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + END IF + IF (ErrStat >= AbortErrLev) RETURN + + END DO + + ! TODO: Sort the table based on depth so that a linear interpolation can be easily performed between entries. + + END IF + + IF ( InputFileData%Morison%NCoefDpthRec < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefDpthRec must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InputFileData%Morison%NCoefDpthRec > 0 ) THEN + MinRecDepth = 99999999.0 + MaxRecDepth = -99999999.0 + DO I = 1,InputFileData%Morison%NCoefDpthRec + + ! Record the minimum and maximum depths covered by this table. This will be used as part of a consistency check + ! in the members table, below. + IF ( InputFileData%Morison%CoefDpthsRec(I)%Dpth < MinRecDepth ) THEN + MinRecDepth = InputFileData%Morison%CoefDpthsRec(I)%Dpth + ELSE + CALL SetErrStat( ErrID_Fatal,'The rows of the Depth-based Hydrodynamic Coefficients table must be ordered with increasing depth (decreasing Z).',ErrStat,ErrMsg,RoutineName) RETURN END IF - IF ( InputFileData%Morison%CoefDpths(I)%DpthCbMG < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table, DpthCbMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN + IF ( InputFileData%Morison%CoefDpthsRec(I)%Dpth > MaxRecDepth ) THEN + MaxRecDepth = InputFileData%Morison%CoefDpthsRec(I)%Dpth END IF + + ! Make sure that the current Dpth is not used elsewhere in the table. + DO J = I+1,InputFileData%Morison%NCoefDpthRec + IF ( EqualRealNos( InputFileData%Morison%CoefDpthsRec(I)%Dpth, InputFileData%Morison%CoefDpthsRec(J)%Dpth ) ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate Dpths were found in the Depth-based Hydrodynamic Coefficients table for rectangular members.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCdA < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCdA must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCdAMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCdAMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCdB < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCdB must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCdBMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCdBMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCaA < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCa must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCaAMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCaMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCaB < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCa must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCaBMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCaMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthAxCd < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthAxCd must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthAxCdMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthAxCdMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthAxCa < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthAxCa must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthAxCaMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthAxCaMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthAxCp < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthAxCp must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthAxCpMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthAxCpMG must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCb < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCb must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefDpthsRec(I)%DpthCbMG < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the Depth-based hydrodynamic coefficients table for rectangular members, DpthCbMG must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + END IF + IF (ErrStat >= AbortErrLev) RETURN + END DO ! TODO: Sort the table based on depth so that a linear interpolation can be easily performed between entries. END IF - !------------------------------------------------------------------------------------------------- ! Member-based Hydrodynamic Coefficients Section !------------------------------------------------------------------------------------------------- - IF ( InputFileData%Morison%NCoefMembers < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'NCoefMembers must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%Morison%NCoefMembersCyl < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefMembersCyl must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) RETURN END IF - IF ( InputFileData%Morison%NCoefMembers > 0 ) THEN + IF ( InputFileData%Morison%NCoefMembersCyl > 0 ) THEN - DO I = 1,InputFileData%Morison%NCoefMembers + DO I = 1,InputFileData%Morison%NCoefMembersCyl ! Make sure that the current MemberID is not used elsewhere in the table. - DO J = I+1,InputFileData%Morison%NCoefMembers - IF ( InputFileData%Morison%CoefMembers(I)%MemberID == InputFileData%Morison%CoefMembers(J)%MemberID ) THEN - CALL SetErrStat( ErrID_Fatal,'Duplicate MemberIDs were found in the Member-based Hydrodynamic coefficients table.',ErrStat,ErrMsg,RoutineName) + DO J = I+1,InputFileData%Morison%NCoefMembersCyl + IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberID == InputFileData%Morison%CoefMembersCyl(J)%MemberID ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate MemberIDs were found in the Member-based Hydrodynamic coefficients table for cylindrical members.',ErrStat,ErrMsg,RoutineName) RETURN END IF END DO + IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCd1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCd1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCd2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCd2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCdMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCdMG1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCdMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCdMG2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCa1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCa1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCa2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCa2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCaMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCaMG1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCaMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCaMG2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberAxCa1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberAxCa1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberAxCa2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberAxCa2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberAxCaMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberAxCaMG1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberAxCaMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberAxCaMG2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCb1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCb1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCb2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCb2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCbMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCbMG1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersCyl(I)%MemberCbMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for cylindrical members, MemberCbMG2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + END IF + IF (ErrStat >= AbortErrLev) RETURN + END DO + END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCd1 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCd1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCd2 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCd2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCdMG1 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCdMG1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCdMG2 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCdMG2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCa1 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCa1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCa2 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCa2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCaMG1 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCaMG1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCaMG2 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCaMG2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberAxCa1 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberAxCa1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberAxCa2 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberAxCa2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberAxCaMG1 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberAxCaMG1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberAxCaMG2 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberAxCaMG2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCb1 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCb1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCb2 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCb2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCbMG1 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCbMG1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - IF ( InputFileData%Morison%CoefMembers(I)%MemberCbMG2 < 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table, MemberCbMG2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF + IF ( InputFileData%Morison%NCoefMembersRec < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefMembersRec must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + IF ( InputFileData%Morison%NCoefMembersRec > 0 ) THEN + + DO I = 1,InputFileData%Morison%NCoefMembersRec + + ! Make sure that the current MemberID is not used elsewhere in the table. + DO J = I+1,InputFileData%Morison%NCoefMembersRec + IF ( InputFileData%Morison%CoefMembersRec(I)%MemberID == InputFileData%Morison%CoefMembersRec(J)%MemberID ) THEN + CALL SetErrStat( ErrID_Fatal,'Duplicate MemberIDs were found in the Member-based Hydrodynamic coefficients table for rectangular members.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + END DO + + IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCdA1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCdA1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCdA2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCdA2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCdAMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCdAMG1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCdAMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCdAMG2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCdB1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCdB1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCdB2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCdB2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCdBMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCdBMG1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCdBMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCdBMG2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCaA1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCaA1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCaA2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCaA2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCaAMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCaAMG1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCaAMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCaAMG2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCaB1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCaB1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCaB2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCaB2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCaBMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCaBMG1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCaBMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCaBMG2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberAxCa1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberAxCa1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberAxCa2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberAxCa2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberAxCaMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberAxCaMG1 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberAxCaMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberAxCaMG2 must be greater or equal to zero.',ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCb1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCb1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCb2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCb2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCbMG1 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCbMG1 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + ELSE IF ( InputFileData%Morison%CoefMembersRec(I)%MemberCbMG2 < 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'In the member-based hydrodynamic coefficients table for rectangular members, MemberCbMG2 must be greater or equal to zero.' ,ErrStat,ErrMsg,RoutineName) + END IF + IF (ErrStat >= AbortErrLev) RETURN END DO END IF - !------------------------------------------------------------------------------------------------- ! Members Section !------------------------------------------------------------------------------------------------- @@ -2011,17 +2356,25 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, Interval, InputFileData, ErrS END IF ! Find MPropSetID1 and MPropSetID2 in the Member cross-section properties table and then record their index locations - DO J = 1,InputFileData%Morison%NPropSets - - - - IF ( InputFileData%Morison%InpMembers(I)%MPropSetID1 == InputFileData%Morison%MPropSets(J)%PropSetID ) THEN - InputFileData%Morison%InpMembers(I)%MPropSetID1Indx = J - END IF - IF ( InputFileData%Morison%InpMembers(I)%MPropSetID2 == InputFileData%Morison%MPropSets(J)%PropSetID ) THEN - InputFileData%Morison%InpMembers(I)%MPropSetID2Indx = J - END IF - END DO + IF ( InputFileData%Morison%InpMembers(I)%MSecGeom == MSecGeom_Cyl ) THEN + DO J = 1,InputFileData%Morison%NPropSetsCyl + IF ( InputFileData%Morison%InpMembers(I)%MPropSetID1 == InputFileData%Morison%MPropSetsCyl(J)%PropSetID ) THEN + InputFileData%Morison%InpMembers(I)%MPropSetID1Indx = J + END IF + IF ( InputFileData%Morison%InpMembers(I)%MPropSetID2 == InputFileData%Morison%MPropSetsCyl(J)%PropSetID ) THEN + InputFileData%Morison%InpMembers(I)%MPropSetID2Indx = J + END IF + END DO + ELSE IF ( InputFileData%Morison%InpMembers(I)%MSecGeom == MSecGeom_Rec ) THEN + DO J = 1,InputFileData%Morison%NPropSetsRec + IF ( InputFileData%Morison%InpMembers(I)%MPropSetID1 == InputFileData%Morison%MPropSetsRec(J)%PropSetID ) THEN + InputFileData%Morison%InpMembers(I)%MPropSetID1Indx = J + END IF + IF ( InputFileData%Morison%InpMembers(I)%MPropSetID2 == InputFileData%Morison%MPropSetsRec(J)%PropSetID ) THEN + InputFileData%Morison%InpMembers(I)%MPropSetID2Indx = J + END IF + END DO + END IF ! Make sure that a PropSetID entry in the Member cross-section properties table was found IF ( InputFileData%Morison%InpMembers(I)%MPropSetID1Indx == -1 ) THEN @@ -2048,42 +2401,80 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, Interval, InputFileData, ErrS END IF IF ( InputFileData%Morison%InpMembers(I)%MCoefMod == 2 ) THEN - IF ( InputFileData%Morison%NCoefDpth == 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'NCoefDpth must be greater than zero when a member is using a depth-based coefficient model.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF - ! We will not extrapolate depth-based coefficient values, so make sure that the depth-based table has values that are outside the depth range of this member - ! NOTE: This is actually potentially overly conservative because the final member may be shorter due to joint overlap handling. + ! We will not extrapolate depth-based coefficient values, so make sure that the depth-based table has values that are outside the depth range of this member + ! NOTE: This is actually potentially overly conservative because the final member may be shorter due to joint overlap handling. z1 = InputFileData%Morison%InpJoints( InputFileData%Morison%InpMembers(I)%MJointID1Indx )%Position(3) z2 = InputFileData%Morison%InpJoints( InputFileData%Morison%InpMembers(I)%MJointID2Indx )%Position(3) MinMembrDpth = min( z1, z2 ) MaxMembrDpth = max( z1, z2 ) - IF ( ( MinMembrDpth < MinDepth ) .OR. ( MaxMembrDpth > MaxDepth ) ) THEN - CALL SetErrStat( ErrID_Fatal,'This member uses a depth-based coefficient model, but the member depth is outside the range of values provided in the depth-based hydrodynamic coefficients table.',ErrStat,ErrMsg,RoutineName) - RETURN + IF ( InputFileData%Morison%InpMembers(I)%MSecGeom == MSecGeom_Cyl ) THEN + IF ( InputFileData%Morison%NCoefDpthCyl == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefDpthCyl for cylindrical members must be greater than zero when a member is using a depth-based coefficient model.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( ( MinMembrDpth < MinCylDepth ) .OR. ( MaxMembrDpth > MaxCylDepth ) ) THEN + CALL SetErrStat( ErrID_Fatal,'This cylindrical member uses a depth-based coefficient model, but the member depth is outside the range of values provided in the depth-based hydrodynamic coefficients table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ELSE IF ( InputFileData%Morison%InpMembers(I)%MSecGeom == MSecGeom_Rec ) THEN + IF ( InputFileData%Morison%NCoefDpthRec == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefDpthRec for rectangular members must be greater than zero when a member is using a depth-based coefficient model.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( ( MinMembrDpth < MinRecDepth ) .OR. ( MaxMembrDpth > MaxRecDepth ) ) THEN + CALL SetErrStat( ErrID_Fatal,'This rectangular member uses a depth-based coefficient model, but the member depth is outside the range of values provided in the depth-based hydrodynamic coefficients table.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF END IF - END IF - IF ( InputFileData%Morison%InpMembers(I)%MCoefMod == 3 ) THEN - IF ( InputFileData%Morison%NCoefMembers == 0 ) THEN - CALL SetErrStat( ErrID_Fatal,'NCoefMembers must be greater than zero when a member is using a member-based coefficient model.',ErrStat,ErrMsg,RoutineName) - RETURN - END IF + + IF (InputFileData%Morison%InpMembers(I)%MSecGeom == MSecGeom_Cyl) THEN + + IF ( InputFileData%Morison%NCoefMembersCyl == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefMembersCyl must be greater than zero when a member is using a member-based coefficient model.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF ! Make sure this id appears in the Members table and mark it's location for future use - FoundID = .FALSE. - DO J = 1,InputFileData%Morison%NCoefMembers - IF ( InputFileData%Morison%CoefMembers(J)%MemberID == InputFileData%Morison%InpMembers(I)%MemberID ) THEN - FoundID = .TRUE. - InputFileData%Morison%InpMembers(I)%MmbrCoefIDIndx = J + FoundID = .FALSE. + DO J = 1,InputFileData%Morison%NCoefMembersCyl + IF ( InputFileData%Morison%CoefMembersCyl(J)%MemberID == InputFileData%Morison%InpMembers(I)%MemberID ) THEN + FoundID = .TRUE. + InputFileData%Morison%InpMembers(I)%MmbrCoefIDIndx = J + END IF + END DO + IF ( .NOT. FoundID ) THEN + CALL SetErrStat( ErrID_Fatal,'Could not locate the MemberID referenced in the Members table in the associated Member-based Hydrodynamic coefficients table for cylindrical members.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + + ELSE IF (InputFileData%Morison%InpMembers(I)%MSecGeom == MSecGeom_Rec) THEN + + IF ( InputFileData%Morison%NCoefMembersRec == 0 ) THEN + CALL SetErrStat( ErrID_Fatal,'NCoefMembersRec must be greater than zero when a member is using a member-based coefficient model.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + ! Make sure this id appears in the Members table and mark it's location for future use + FoundID = .FALSE. + DO J = 1,InputFileData%Morison%NCoefMembersRec + IF ( InputFileData%Morison%CoefMembersRec(J)%MemberID == InputFileData%Morison%InpMembers(I)%MemberID ) THEN + FoundID = .TRUE. + InputFileData%Morison%InpMembers(I)%MmbrCoefIDIndx = J + END IF + END DO + IF ( .NOT. FoundID ) THEN + CALL SetErrStat( ErrID_Fatal,'Could not locate the MemberID referenced in the Members table in the associated Member-based Hydrodynamic coefficients table for rectangular members.',ErrStat,ErrMsg,RoutineName) + RETURN END IF - END DO - IF ( .NOT. FoundID ) THEN - CALL SetErrStat( ErrID_Fatal,'Could not locate the MemberID referenced in the Members table in the associated Member-based Hydrodynamic coefficients table.',ErrStat,ErrMsg,RoutineName) - RETURN END IF + + END IF + + IF ( InputFileData%Morison%InpMembers(I)%MSecGeom /= MSecGeom_Cyl .AND. InputFileData%Morison%InpMembers(I)%MSecGeom /= MSecGeom_Rec ) THEN + CALL SetErrStat( ErrID_Fatal,'MSecGeom must be 1 for cylindrical members or 2 for rectangular members.',ErrStat,ErrMsg,RoutineName) + RETURN END IF IF ( InputFileData%Morison%InpMembers(I)%MHstLMod /= 0 .AND. InputFileData%Morison%InpMembers(I)%MHstLMod /= 1 .AND. InputFileData%Morison%InpMembers(I)%MHstLMod /= 2 ) THEN @@ -2091,12 +2482,16 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, Interval, InputFileData, ErrS RETURN END IF + IF ( InputFileData%Morison%InpMembers(I)%MSecGeom == MSecGeom_Rec .AND. InputFileData%Morison%InpMembers(I)%MHstLMod /= 2 ) THEN + CALL SetErrStat( ErrID_Fatal,'MHstLMod must be 2 for rectangular members.',ErrStat,ErrMsg,RoutineName) + RETURN + END IF + IF ( InputFileData%Morison%InpMembers(I)%PropPot .AND. InputFileData%PotMod == 0 ) THEN CALL SetErrStat( ErrID_Fatal,'A member cannot have PropPot set to TRUE if PotMod = 0 in the FLOATING PLATFORM section.',ErrStat,ErrMsg,RoutineName) RETURN END IF - END DO END IF @@ -2132,6 +2527,9 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, Interval, InputFileData, ErrS InputFileData%Morison%InpMembers(k)%MmbrFilledIDIndx = I + ! Set entries of member list of the filled group to the member index instead of ID for quick lookup later + InputFileData%Morison%FilledGroups(I)%FillMList(J) = K + END IF END DO @@ -2150,6 +2548,7 @@ SUBROUTINE HydroDynInput_ProcessInitData( InitInp, Interval, InputFileData, ErrS ! Deal with DEFAULT or create a REAL from the string + CALL Conv2UC( InputFileData%Morison%FilledGroups(I)%FillDensChr ) IF ( TRIM(InputFileData%Morison%FilledGroups(I)%FillDensChr) /= 'DEFAULT' ) THEN READ (InputFileData%Morison%FilledGroups(I)%FillDensChr,*,IOSTAT=IOS) InputFileData%Morison%FilledGroups(I)%FillDens diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90 index 2926f82e6b..32ccbe48ae 100644 --- a/modules/hydrodyn/src/Morison.f90 +++ b/modules/hydrodyn/src/Morison.f90 @@ -35,7 +35,11 @@ MODULE Morison TYPE(ProgDesc), PARAMETER :: Morison_ProgDesc = ProgDesc( 'Morison', '', '' ) - + INTERFACE Morison_DirCosMtrx + MODULE PROCEDURE Morison_DirCosMtrx_Spin + MODULE PROCEDURE Morison_DirCosMtrx_noSpin + END INTERFACE + ! ..... Public Subroutines ................................................................................................... PUBLIC:: Morison_GenerateSimulationNodes @@ -45,69 +49,109 @@ MODULE Morison CONTAINS !---------------------------------------------------------------------------------------------------------------------------------- -SUBROUTINE Morison_DirCosMtrx( pos0, pos1, DirCos ) +SUBROUTINE Morison_DirCosMtrx_Spin( pos0, pos1, spin, DirCos ) +! Compute the direction cosine matrix given two end points and a spin angle for rectangular members +! Left multiplying DirCos with a vector in element local sys returns vector in global sys +! Updated to match the convention in SubDyn for consistency + + REAL(ReKi), INTENT( IN ) :: pos0(3), pos1(3), spin + Real(ReKi), INTENT( OUT ) :: DirCos(3,3) + Real(DbKi) :: Le, Lexy + Real(DbKi) :: dx, dy, dz + Real(DbKi) :: Rspin(3,3) + + DirCos = 0.0 + Rspin = 0.0 + + dx = pos1(1) - pos0(1) + dy = pos1(2) - pos0(2) + dz = pos1(3) - pos0(3) + + Lexy = sqrt( dx*dx + dy*dy ) + + IF ( EqualRealNos(Lexy, 0.0_DbKi) ) THEN + IF (dz > 0) THEN + DirCos(1,1) = 1.0 + DirCos(2,2) = 1.0 + DirCos(3,3) = 1.0 + ELSE + DirCos(1,1) = 1.0 + DirCos(2,2) = -1.0 + DirCos(3,3) = -1.0 + END IF + ELSE + Le = sqrt( dx*dx + dy*dy + dz*dz ) + + DirCos(1, 1) = dy/Lexy + DirCos(1, 2) = dx*dz/(Lexy*Le) + DirCos(1, 3) = dx/Le + + DirCos(2, 1) = -dx/Lexy + DirCos(2, 2) = dy*dz/(Lexy*Le) + DirCos(2, 3) = dy/Le + + DirCos(3, 1) = 0.0 + DirCos(3, 2) = -Lexy/Le + DirCos(3, 3) = dz/Le + END IF + + IF ( .not. EqualRealNos(spin, 0.0) ) THEN + ! Spin the member about its axis first + Rspin(1,1) = cos(spin) + Rspin(2,2) = Rspin(1,1) + Rspin(1,2) = -sin(spin) + Rspin(2,1) = -Rspin(1,2) + Rspin(3,3) = 1.0 + DirCos = matmul(DirCos,Rspin) + END IF + +END SUBROUTINE Morison_DirCosMtrx_Spin -! Compute the direction cosine matrix given two points along the axis of a cylinder +SUBROUTINE Morison_DirCosMtrx_noSpin( pos0, pos1, DirCos ) +! Compute the direction cosine matrix given two end points without spin for cylindrical members +! Left multiplying DirCos with a vector in element local sys returns vector in global sys +! Updated to match the convention in SubDyn for consistency REAL(ReKi), INTENT( IN ) :: pos0(3), pos1(3) Real(ReKi), INTENT( OUT ) :: DirCos(3,3) - Real(DbKi) :: xz, xyz - Real(DbKi) :: x0, y0, z0 - Real(DbKi) :: x1, y1, z1 -! Real(DbKi) :: temp - - x0 = pos0(1) - y0 = pos0(2) - z0 = pos0(3) - x1 = pos1(1) - y1 = pos1(2) - z1 = pos1(3) - - ! Need to verify that z0 <= z1, but this was already handled in the element construction process!!! GJH 9/24/13 - !IF ( z0 > z1 ) THEN - ! temp = x0 - ! x0 = x1 - ! x1 = temp - ! temp = y0 - ! y0 = y1 - ! y1 = temp - ! temp = z0 - ! z0 = z1 - ! z1 = temp - !END IF - - xz = sqrt((x0-x1)*(x0-x1)+(z0-z1)*(z0-z1)) - xyz = sqrt((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1)+(z0-z1)*(z0-z1)) - - IF ( xz==0 ) THEN - - IF (y1 0) THEN + DirCos(1,1) = 1.0 + DirCos(2,2) = 1.0 + DirCos(3,3) = 1.0 ELSE - - DirCos = transpose(reshape((/ 1, 0, 0, 0, 0, 1, 0, -1, 0 /), shape(DirCos))) - + DirCos(1,1) = 1.0 + DirCos(2,2) = -1.0 + DirCos(3,3) = -1.0 END IF - ELSE - - DirCos(1, 1) = (z1-z0)/xz - DirCos(1, 2) = -(x1-x0)*(y1-y0)/(xz*xyz) - DirCos(1, 3) = (x1-x0)/xyz - - DirCos(2, 1) = 0.0 - DirCos(2, 2) = xz/xyz - DirCos(2, 3) = (y1-y0)/xyz - - DirCos(3, 1) = -(x1-x0)/xz - DirCos(3, 2) = -(y1-y0)*(z1-z0)/(xz*xyz) - DirCos(3, 3) = (z1-z0)/xyz + Le = sqrt( dx*dx + dy*dy + dz*dz ) - END IF - -END SUBROUTINE Morison_DirCosMtrx + DirCos(1, 1) = dy/Lexy + DirCos(1, 2) = dx*dz/(Lexy*Le) + DirCos(1, 3) = dx/Le + + DirCos(2, 1) = -dx/Lexy + DirCos(2, 2) = dy*dz/(Lexy*Le) + DirCos(2, 3) = dy/Le + + DirCos(3, 1) = 0.0 + DirCos(3, 2) = -Lexy/Le + DirCos(3, 3) = dz/Le + END IF + +END SUBROUTINE Morison_DirCosMtrx_noSpin !==================================================================================================== SUBROUTINE GetDistance ( a, b, l ) @@ -379,7 +423,7 @@ subroutine GetOrientationAngles(p1, p2, phi, sinPhi, cosPhi, tanPhi, sinBeta, co end subroutine GetOrientationAngles !---------------------------------------------------------------------------------------------------------------------------------- !function to return conical taper geometry calculations (volume and center of volume) -SUBROUTINE TaperCalc(R1, R2, H, taperV, h_c) +SUBROUTINE CylTaperCalc(R1, R2, H, taperV, h_c) REAL(ReKi), INTENT ( IN ) :: R1 REAL(ReKi), INTENT ( IN ) :: R2 REAL(ReKi), INTENT ( IN ) :: H @@ -401,7 +445,35 @@ SUBROUTINE TaperCalc(R1, R2, H, taperV, h_c) h_c = H*(R1**2 + 2*R1*R2 + 3*R2**2)/4.0/(R1**2 + R1*R2 + R2**2) !( coneV*1./4.*coneH - coneVtip*(1./4.*(coneH-H) + H) )/ taperV ! from base end if -END SUBROUTINE TaperCalc +END SUBROUTINE CylTaperCalc +!---------------------------------------------------------------------------------------------------------------------------------- +!function to return pyramidal taper geometry calculations (volume and center of volume) +SUBROUTINE RecTaperCalc(a0, a1, b0, b1, H, taperV, h_c) + REAL(ReKi), INTENT ( IN ) :: a0 + REAL(ReKi), INTENT ( IN ) :: a1 + REAL(ReKi), INTENT ( IN ) :: b0 + REAL(ReKi), INTENT ( IN ) :: b1 + REAL(ReKi), INTENT ( IN ) :: H + REAL(ReKi), INTENT ( OUT ) :: taperV ! volume of tapered section + REAL(ReKi), INTENT ( OUT ) :: h_c ! center of mass offset from first node + + REAL(ReKi) :: a0b0, a0b1, a1b0, a1b1, tmp + + a0b0 = a0*b0 + a0b1 = a0*b1 + a1b0 = a1*b0 + a1b1 = a1*b1 + + tmp = 2.0*a0b0 + a0b1 + a1b0 + 2.0*a1b1 + if ( EqualRealNos(tmp, 0.0_ReKi) ) then + taperV = 0.0_ReKi + h_c = 0.0_ReKi + else + taperV = abs(H/6.0*tmp) + h_c = 0.5*H*(a0b0 + a0b1 + a1b0 + 3.0*a1b1)/tmp ! from base + end if + +END SUBROUTINE RecTaperCalc !---------------------------------------------------------------------------------------------------------------------------------- SUBROUTINE CylInertia(R1, R2, H, rho, Il, Ir) REAL(ReKi), INTENT ( IN ) :: R1 @@ -431,7 +503,37 @@ SUBROUTINE CylInertia(R1, R2, H, rho, Il, Ir) END SUBROUTINE CylInertia !---------------------------------------------------------------------------------------------------------------------------------- -SUBROUTINE MarineGrowthPartSegment(R1, R2, Rmg1, Rmg2, L, rho, Vinner, Vouter, m_mg, h_c, Ilmg, Irmg) +SUBROUTINE RecInertia(a0, a1, b0, b1, H, rho, Ize, Ixe, Iye) + REAL(ReKi), INTENT ( IN ) :: a0 ! Length of side A at node 0 + REAL(ReKi), INTENT ( IN ) :: a1 ! Length of side A at node 1 + REAL(ReKi), INTENT ( IN ) :: b0 ! Length of side B at node 0 + REAL(ReKi), INTENT ( IN ) :: b1 ! Length of side B at node 1 + REAL(ReKi), INTENT ( IN ) :: H ! Element height/distance from node 0 to node 1 + REAL(ReKi), INTENT ( IN ) :: rho ! density of material + REAL(ReKi), INTENT ( OUT ) :: Ize ! Moment of inertia about element local z-axis (along member axis) + REAL(ReKi), INTENT ( OUT ) :: Ixe ! Moment of inertia about element local x-axis (aligned with sides A) + REAL(ReKi), INTENT ( OUT ) :: Iye ! Moment of inertia about element local y-axis (aligned with sides B) + real(ReKi) :: I1, I2, I3, da, da2, da3, db, db2, db3, a02, a03, b02, b03 + ! All moment of inertia computed about node 0 + da = a1 - a0 + da2 = da * da + da3 = da * da2 + db = b1 - b0 + db2 = db * db + db3 = db * db2 + a02 = a0 * a0 + a03 = a0 * a02 + b02 = b0 * b0 + b03 = b0 * b02 + I1 = rho*H/12.0 * ( db3*(0.2*a1+0.05*a0) + db2*b0*(0.75*a1+0.25*a0) + db*b02*(a1+0.5*a0) + 0.5*(a1+a0)*b03 ) + I2 = rho*H/12.0 * ( da3*(0.2*b1+0.05*b0) + da2*a0*(0.75*b1+0.25*b0) + da*a02*(b1+0.5*b0) + 0.5*(b1+b0)*a03 ) + I3 = rho*H**3 * ( 0.2*a1*b1 + 0.05*a1*b0 + 0.05*a0*b1 + a0*b0/30.0 ) + Ixe = abs(I1 + I3) + Iye = abs(I2 + I3) + Ize = abs(I1 + I2) +END SUBROUTINE RecInertia +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE MarineGrowthPartSegmentCyl(R1, R2, Rmg1, Rmg2, L, rho, Vinner, Vouter, m_mg, h_c, Ilmg, Irmg) REAL(ReKi), INTENT ( IN ) :: R1 REAL(ReKi), INTENT ( IN ) :: R2 @@ -454,14 +556,12 @@ SUBROUTINE MarineGrowthPartSegment(R1, R2, Rmg1, Rmg2, L, rho, Vinner, Vouter, REAL(ReKi) :: Irinner REAL(ReKi) :: Ilouter REAL(ReKi) :: Irouter - - - + ! get V and CV for element - call TaperCalc(R1, R2, L, Vinner, cVinner) + call CylTaperCalc(R1, R2, L, Vinner, cVinner) ! get V and CV for marine growth displacement - call TaperCalc(Rmg1, Rmg2, L, Vouter, cVouter) + call CylTaperCalc(Rmg1, Rmg2, L, Vouter, cVouter) ! get mass and CV specific to marine growth thickness m_mg = (Vouter - Vinner)*rho @@ -479,29 +579,106 @@ SUBROUTINE MarineGrowthPartSegment(R1, R2, Rmg1, Rmg2, L, rho, Vinner, Vouter, Ilmg = Ilouter - Ilinner Irmg = Irouter - Irinner -END SUBROUTINE MarineGrowthPartSegment +END SUBROUTINE MarineGrowthPartSegmentCyl +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE MarineGrowthPartSegmentRec(a1, a2, b1, b2, amg1, amg2, bmg1, bmg2, L, rho, Vinner, Vouter, m_mg, h_c, Izemg, Ixemg, Iyemg) + + REAL(ReKi), INTENT ( IN ) :: a1 + REAL(ReKi), INTENT ( IN ) :: a2 + REAL(ReKi), INTENT ( IN ) :: b1 + REAL(ReKi), INTENT ( IN ) :: b2 + REAL(ReKi), INTENT ( IN ) :: amg1 + REAL(ReKi), INTENT ( IN ) :: amg2 + REAL(ReKi), INTENT ( IN ) :: bmg1 + REAL(ReKi), INTENT ( IN ) :: bmg2 + REAL(ReKi), INTENT ( IN ) :: L + REAL(ReKi), INTENT ( IN ) :: rho ! density of material + REAL(ReKi), INTENT ( OUT ) :: Vinner ! volume from inner radius + REAL(ReKi), INTENT ( OUT ) :: Vouter ! volume from outer radius + REAL(ReKi), INTENT ( OUT ) :: m_mg ! mass of marine growth + REAL(ReKi), INTENT ( OUT ) :: h_c ! center of mass offset from first node + REAL(ReKi), INTENT ( OUT ) :: Izemg ! moment of inertia about axis at first node + REAL(ReKi), INTENT ( OUT ) :: Ixemg ! moment of inertia about element local x-axis at first node + REAL(ReKi), INTENT ( OUT ) :: Iyemg ! moment of inertia about element local y-axis at first node + + ! Local variables + + REAL(ReKi) :: cVinner ! center of volume from inner radius + REAL(ReKi) :: cVouter ! center of volume from outer radius + REAL(ReKi) :: Izeinner + REAL(ReKi) :: Ixeinner + REAL(ReKi) :: Iyeinner + REAL(ReKi) :: Izeouter + REAL(ReKi) :: Ixeouter + REAL(ReKi) :: Iyeouter + + ! get V and CV for element + call RecTaperCalc(a1, a2, b1, b2, L, Vinner, cVinner) + + ! get V and CV for marine growth displacement + call RecTaperCalc(amg1, amg2, bmg1, bmg2, L, Vouter, cVouter) + + ! get mass and CV specific to marine growth thickness + m_mg = (Vouter - Vinner)*rho + if ( EqualRealNos(m_mg, 0.0_ReKi) ) then + h_c = 0.0 + else + h_c = (cVouter*Vouter - cVinner*Vinner)/(Vouter - Vinner) + end if + + ! get two moments of inertia for marine growth as if solid... + call RecInertia(amg1, amg2, bmg1, bmg2, L, rho, Izeouter, Ixeouter, Iyeouter) ! inertias for marine growth if solid + call RecInertia(a1 , a2 , b1, b2, L, rho, Izeinner, Ixeinner, Iyeinner) ! inertias for element if filled with marine growth + + ! subtract to get moments of inertia of marine growth shell + Izemg = Izeouter - Izeinner + Ixemg = Ixeouter - Ixeinner + Iyemg = Iyeouter - Iyeinner + +END SUBROUTINE MarineGrowthPartSegmentRec !---------------------------------------------------------------------------------------------------------------------------------- -SUBROUTINE FloodedBallastPartSegment(R1, R2, L, rho, V, m, h_c, Il, Ir) +SUBROUTINE FloodedBallastPartSegmentCyl(R1, R2, L, rho, V, m, h_c, Il, Ir) REAL(ReKi), INTENT ( IN ) :: R1 ! interior radius of element at node point REAL(ReKi), INTENT ( IN ) :: R2 ! interior radius of other end of part-element REAL(ReKi), INTENT ( IN ) :: L ! distance positive along axis to end of part-element - REAL(ReKi), INTENT ( OUT ) :: V ! volume from inner radius REAL(ReKi), INTENT ( IN ) :: rho ! density of ballast + REAL(ReKi), INTENT ( OUT ) :: V ! volume from inner radius REAL(ReKi), INTENT ( OUT ) :: m ! mass of material - REAL(ReKi), INTENT ( OUT ) :: h_c ! center of mass offset from first node + REAL(ReKi), INTENT ( OUT ) :: h_c ! center of mass offset from first node REAL(ReKi), INTENT ( OUT ) :: Il ! moment of inertia about axis REAL(ReKi), INTENT ( OUT ) :: Ir ! moment of inertia about radial axis from first node + ! get V and CV for flooded part of part-element + call CylTaperCalc(R1, R2, L, V, h_c) + m = rho*V + + call CylInertia(R1, R2, L, rho, Il, Ir) ! inertias for filled section +END SUBROUTINE FloodedBallastPartSegmentCyl +!---------------------------------------------------------------------------------------------------------------------------------- +SUBROUTINE FloodedBallastPartSegmentRec(a1, a2, b1, b2, L, rho, V, m, h_c, Ize, Ixe, Iye) + + REAL(ReKi), INTENT ( IN ) :: a1 ! interior length of side A at node 1 + REAL(ReKi), INTENT ( IN ) :: a2 ! interior length of side A at node 2 + REAL(ReKi), INTENT ( IN ) :: b1 ! interior length of side B at node 1 + REAL(ReKi), INTENT ( IN ) :: b2 ! interior length of side B at node 2 + REAL(ReKi), INTENT ( IN ) :: L ! distance positive along axis to end of part-element + REAL(ReKi), INTENT ( IN ) :: rho ! density of ballast + REAL(ReKi), INTENT ( OUT ) :: V ! volume from inner radius + REAL(ReKi), INTENT ( OUT ) :: m ! mass of material + REAL(ReKi), INTENT ( OUT ) :: h_c ! center of mass offset from first node + REAL(ReKi), INTENT ( OUT ) :: Ize ! moment of inertia about element local z-axis + REAL(ReKi), INTENT ( OUT ) :: Ixe ! moment of inertia about element local x-axis at first node + REAL(ReKi), INTENT ( OUT ) :: Iye ! moment of inertia about element local y-axis at first node ! get V and CV for flooded part of part-element - call TaperCalc(R1, R2, L, V, h_c) + call RecTaperCalc(a1, a2, b1, b2, L, V, h_c) m = rho*V - call CylInertia(R1, R2, L, rho, Il, Ir) ! inertias for filled section + call RecInertia(a1, a2, b1, b2, L, rho, Ize, Ixe, Iye) ! inertias for filled section -END SUBROUTINE FloodedBallastPartSegment +END SUBROUTINE FloodedBallastPartSegmentRec !---------------------------------------------------------------------------------------------------------------------------------- SUBROUTINE WriteSummaryFile( UnSum, numJoints, numNodes, nodes, numMembers, members, & NOutputs, OutParam, MOutLst, JOutLst, uMesh, yMesh, p, m, errStat, errMsg ) @@ -546,11 +723,12 @@ SUBROUTINE WriteSummaryFile( UnSum, numJoints, numNodes, nodes, numMembers, memb CHARACTER(ChanLen) :: tmpName REAL(ReKi) :: totalFillMass, mass_fill, memberVol REAL(ReKi) :: totalMGMass - TYPE(Morison_NodeType) :: node1, node2 + TYPE(Morison_NodeType) :: node1, node2 real(ReKi) :: ptLoad(6) logical :: fillFlag type(Morison_MemberType) :: mem - REAL(ReKi) :: Cd1, Cd2, Ca1, Ca2, Cp1, Cp2, AxCd1, AxCd2, AxCa1, AxCa2, AxCp1, AxCp2, Cb1, Cb2, JAxCd1, JAxCd2, JAxCa1, JAxCa2, JAxCp1, JAxCp2 ! tmp coefs + REAL(ReKi) :: Cd1, CdA1, CdB1, Cd2, CdA2, CdB2, Ca1, CaA1, CaB1, Ca2, CaA2, CaB2, Cp1, Cp2, Cb1, Cb2 + REAL(ReKi) :: AxCd1, AxCd2, AxCa1, AxCa2, AxCp1, AxCp2, JAxCd1, JAxCd2, JAxCa1, JAxCa2, JAxCp1, JAxCp2 real(ReKi) :: F_B(6, numNodes), F_BF(6, numNodes), F_WMG(6, numNodes) INTEGER :: ErrStat2 @@ -781,15 +959,24 @@ SUBROUTINE WriteSummaryFile( UnSum, numJoints, numNodes, nodes, numMembers, memb WRITE( UnSum, '(//)' ) WRITE( UnSum, '(A14,I4,A44)' ) 'Nodes (first [',numJoints,'] are joints, remainder are internal nodes)' WRITE( UnSum, '(/)' ) - WRITE( UnSum, '(1X,A5,21(2X,A10))' ) ' i ', ' MbrIndx ', ' Nxi ', ' Nyi ', ' Nzi ', ' R ', ' t ', ' tMG ', ' MGDens ', ' PropPot ', 'FilledFlag', 'FilledMass', ' Cd ', ' Ca ', ' Cp ', ' Cb ', ' AxCd ', ' AxCa ', ' AxCp ', ' JAxCd ', ' JAxCa ', ' JAxCp ' - WRITE( UnSum, '(1X,A5,21(2X,A10))' ) ' (-) ', ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (kg/m^3) ', ' (-) ', ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ' + WRITE( UnSum, '(1X,A5,31(2X,A10))' ) & + ' i ' , ' MbrIndx ', ' Nxi ', ' Nyi ', ' Nzi ', ' Shape ', ' R ', ' SA ', ' SB ', ' t ', ' tMG ', ' MGDens ', & + ' PropPot ', 'FilledFlag', 'FilledMass', ' Cd ', ' CdA ', ' CdB ', ' Ca ', ' CaA ', ' CaB ', ' Cp ', ' Cb ', & + ' AxCd ', ' AxCa ', ' AxCp ', ' JAxCd ', ' JAxCa ', ' JAxCp ', ' JAxFDMod ', 'JAxVnCOff ', 'JAxFDLoFSc' + WRITE( UnSum, '(1X,A5,31(2X,A10))' ) & + ' (-) ' , ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (kg/m^3) ', & + ' (-) ', ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', & + ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ' ! Write the node data do I = 1,numJoints ! need to add MSL2SWL offset from this because the Positons are relative to SWL, but we should report them relative to MSL here pos = nodes(i)%Position pos(3) = pos(3) + p%WaveField%MSL2SWL - write( UnSum, '(1X,I5,(2X,A10),3(2X,F10.4),2(2X,A10),2(2X,ES10.3),10(2X,A10),3(2X,ES10.3))' ) i,' - ', pos, ' - ', ' - ', nodes(i)%tMG, nodes(i)%MGdensity, ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', nodes(i)%JAxCd, nodes(i)%JAxCa, nodes(i)%JAxCp + write( UnSum, '(1X,I5,(2X,A10),3(2X,F10.4),5(2X,A10),2(2X,ES10.3),14(2X,A10),3(2X,ES10.3),1X,I10,2(2X,ES10.3))' ) & + i, ' - ', pos, ' - ', ' - ', ' - ', ' - ', ' - ', nodes(i)%tMG, nodes(i)%MGdensity, & + ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', ' - ', & + ' - ', ' - ', ' - ',nodes(i)%JAxCd,nodes(i)%JAxCa,nodes(i)%JAxCp,nodes(i)%JAxFDMod,nodes(i)%JAxVnCOff,nodes(i)%JAxFDLoFSc end do c = numJoints do j= 1, numMembers @@ -808,19 +995,37 @@ SUBROUTINE WriteSummaryFile( UnSum, numJoints, numNodes, nodes, numMembers, memb else II=I endif - write( UnSum, '(1X,I5,(2X,I10),3(2X,F10.4),4(2X,ES10.3),2(6X,L6),8(2X,ES10.3),3(7x,A5))' ) c, members(j)%MemberID, pos, members(j)%R(ii), members(j)%R(ii)-members(j)%Rin(ii), members(j)%tMG(ii), members(j)%MGdensity(ii), members(j)%PropPot, fillFlag, members(j)%m_fb_u(ii)+members(j)%m_fb_l(ii), members(j)%Cd(ii), members(j)%Ca(ii), members(j)%Cp(ii), members(j)%Cb(ii), members(j)%AxCd(ii), members(j)%AxCa(ii), members(j)%AxCp(ii), ' - ', ' - ', ' - ' + if ( members(j)%MSecGeom == MSecGeom_Cyl ) then + write( UnSum, '(1X,I5,(2X,I10),3(2X,F10.4),(2X,A10),(2X,ES10.3),2(2X,A10),3(2X,ES10.3),2(6X,L6),2(2X,ES10.3),2(2X,A10),(2X,ES10.3),2(2X,A10),5(2X,ES10.3),6(7x,A5))' ) & + c, members(j)%MemberID, pos, ' C ', members(j)%R(ii), ' - ', ' - ', members(j)%R(ii)-members(j)%Rin(ii), members(j)%tMG(ii), members(j)%MGdensity(ii), & + members(j)%PropPot, fillFlag, members(j)%m_fb_u(ii)+members(j)%m_fb_l(ii), members(j)%Cd(ii), ' - ', ' - ', members(j)%Ca(ii), & + ' - ', ' - ', members(j)%Cp(ii), members(j)%Cb(ii), members(j)%AxCd(ii), members(j)%AxCa(ii), members(j)%AxCp(ii), & + ' - ', ' - ', ' - ', ' - ', ' - ', ' - ' + else if ( members(j)%MSecGeom == MSecGeom_Rec ) then + write( UnSum, '(1X,I5,(2X,I10),3(2X,F10.4),(2X,A10),(2X,A10),5(2X,ES10.3),2(6X,L6),(2X,ES10.3),(2X,A10),2(2X,ES10.3),(2X,A10),7(2X,ES10.3),6(7x,A5))' ) & + c, members(j)%MemberID, pos, ' R ', ' - ', members(j)%Sa(ii), members(j)%Sb(ii), 0.5*(members(j)%Sa(ii)-members(j)%Sain(ii)), members(j)%tMG(ii), members(j)%MGdensity(ii), & + members(j)%PropPot, fillFlag, members(j)%m_fb_u(ii)+members(j)%m_fb_l(ii), ' - ', members(j)%CdA(ii), members(j)%CdB(ii), ' - ', & + members(j)%CaA(ii), members(j)%CaB(ii), members(j)%Cp(ii), members(j)%Cb(ii), members(j)%AxCd(ii), members(j)%AxCa(ii), members(j)%AxCp(ii), & + ' - ', ' - ', ' - ', ' - ', ' - ', ' - ' + end if end do end do - write( UnSum, '(//)' ) write( UnSum, '(A8)' ) 'Members' write( UnSum, '(/)' ) - write( UnSum, '(1X,A8,2X,A6,2X,A6,33(2X,A12))' ) 'MemberID', 'joint1','joint2',' Length ', ' NElem ', ' Volume ', ' MGVolume ', ' R1 ', ' t1 ', ' R2 ', ' t2 ', ' PropPot ', 'FilledFlag', 'FillDensity', ' FillFSLoc ', ' FillMass ', ' Cd1 ', ' Ca1 ', ' Cp1 ', ' Cb1 ', ' AxCd1 ', ' AxCa1 ', ' AxCp1 ', ' JAxCd1 ', ' JAxCa1 ', ' JAxCp1 ', ' Cd2 ', ' Ca2 ', ' Cp2 ', ' Cb2 ', ' AxCd2 ', ' AxCa2 ', ' AxCp2 ', ' JAxCd2 ', ' JAxCa2 ', ' JAxCp2 ' - write( UnSum, '(1X,A8,2X,A6,2X,A6,33(2X,A12))' ) ' (-) ', ' (-) ',' (-) ',' (m) ', ' (-) ', ' (m^3) ', ' (m^3) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ', ' (-) ', ' (kg/m^3) ', ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ' - - - + write( UnSum, '(1X,A8,2X,A6,2X,A6,45(2X,A12))' ) & + 'MemberID' , 'joint1' , 'joint2' , ' Length ' , ' NElem ', ' Volume ', ' MGVolume ', ' R1 ', ' SA1 ', ' SB1 ', ' t1 ', & + ' R2 ', ' SA2 ', ' SB2 ', ' t2 ', ' PropPot ' , 'FilledFlag' , 'FillDensity' , ' FillFSLoc ', ' FillMass ', ' Cd1 ', ' CdA1 ', ' CdB1 ', & + ' Ca1 ', ' CaA1 ', ' CaB1 ' , ' Cp1 ', ' Cb1 ', ' AxCd1 ', ' AxCa1 ', ' AxCp1 ', ' JAxCd1 ', ' JAxCa1 ', ' JAxCp1 ', & + ' Cd2 ', ' CdA2 ', ' CdB2 ', ' Ca2 ', ' CaA2 ', ' CaB2 ', ' Cp2 ', ' Cb2 ', ' AxCd2 ', ' AxCa2 ', ' AxCp2 ', & + ' JAxCd2 ', ' JAxCa2 ', ' JAxCp2 ' + write( UnSum, '(1X,A8,2X,A6,2X,A6,45(2X,A12))' ) & + ' (-) ' , ' (-) ' , ' (-) ' , ' (m) ' , ' (-) ', ' (m^3) ', ' (m^3) ', ' (m) ', ' (m) ', ' (m) ', ' (m) ', & + ' (m) ', ' (m) ', ' (m) ', ' (m) ', ' (-) ' , ' (-) ' , ' (kg/m^3) ' , ' (-) ', ' (kg) ', ' (-) ', ' (-) ', ' (-) ', & + ' (-) ', ' (-) ', ' (-) ' , ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', & + ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', ' (-) ', & + ' (-) ', ' (-) ', ' (-) ' do i = 1,numMembers N = members(i)%NElements @@ -841,10 +1046,22 @@ SUBROUTINE WriteSummaryFile( UnSum, numJoints, numNodes, nodes, numMembers, memb filledFlag = .FALSE. END IF - Cd1 = members(i)%Cd(1) - Cd2 = members(i)%Cd(N+1) - Ca1 = members(i)%Ca(1) - Ca2 = members(i)%Ca(N+1) + IF ( members(i)%MSecGeom == MSecGeom_Cyl ) THEN + Cd1 = members(i)%Cd(1) + Cd2 = members(i)%Cd(N+1) + Ca1 = members(i)%Ca(1) + Ca2 = members(i)%Ca(N+1) + ELSE IF ( members(i)%MSecGeom == MSecGeom_Rec ) THEN + CdA1 = members(i)%CdA(1) + CdA2 = members(i)%CdA(N+1) + CaA1 = members(i)%CaA(1) + CaA2 = members(i)%CaA(N+1) + CdB1 = members(i)%CdB(1) + CdB2 = members(i)%CdB(N+1) + CaB1 = members(i)%CaB(1) + CaB2 = members(i)%CaB(N+1) + END IF + Cp1 = members(i)%Cp(1) Cp2 = members(i)%Cp(N+1) AxCd1 = members(i)%AxCd(1) @@ -863,14 +1080,23 @@ SUBROUTINE WriteSummaryFile( UnSum, numJoints, numNodes, nodes, numMembers, memb JAxCp1 = nodes(members(i)%NodeIndx(1 ))%JAxCp JAxCp2 = nodes(members(i)%NodeIndx(1+N))%JAxCp - - write( UnSum, '(1X,I8,2X,I6,2X,I6,2X,ES12.5,2X,I12, 6(2X,ES12.5),2(2X,L12),23(2X,ES12.5))' ) members(i)%MemberID, & - members(i)%NodeIndx(1), members(i)%NodeIndx(N+1), members(i)%RefLength, N, & - memberVol, MGvolume, members(i)%Rmg(1), members(i)%Rmg(1)-members(i)%Rin(1), & - members(i)%Rmg(N+1), members(i)%Rmg(N+1)-members(i)%Rin(N+1), & - members(i)%PropPot, filledFlag, members(i)%FillDens, members(i)%FillFSLoc, & - mass_fill, Cd1, Ca1, Cp1, Cb1, AxCd1, AxCa1, AxCp1, JAxCd1, JAxCa1, JAxCp1, & - Cd2, Ca2, Cp2, Cb2, AxCd2, AxCa2, AxCp2, JAxCd2, JAxCa2, JAxCp2 + IF ( members(i)%MSecGeom == MSecGeom_Cyl ) THEN + write( UnSum, '(1X,I8,2X,I6,2X,I6,2X,ES12.5,2X,I12, 3(2X,ES12.5),2(2X,A12),2(2X,ES12.5),2(2X,A12),(2X,ES12.5),2(2X,L12), 4(2X,ES12.5),2(2X,A12),(2X,ES12.5),2(2X,A12),9(2X,ES12.5),2(2X,A12),(2X,ES12.5),2(2X,A12),8(2X,ES12.5))' ) members(i)%MemberID, & + members(i)%NodeIndx(1), members(i)%NodeIndx(N+1), members(i)%RefLength, N, & + memberVol, MGvolume, members(i)%Rmg(1), ' - ', ' - ', members(i)%Rmg(1)-members(i)%Rin(1), & + members(i)%Rmg(N+1), ' - ', ' - ', members(i)%Rmg(N+1)-members(i)%Rin(N+1), & + members(i)%PropPot, filledFlag, members(i)%FillDens, members(i)%FillFSLoc, & + mass_fill, Cd1, ' - ', ' - ', Ca1, ' - ', ' - ', Cp1, Cb1, AxCd1, AxCa1, AxCp1, JAxCd1, JAxCa1, JAxCp1, & + Cd2, ' - ', ' - ', Ca2, ' - ', ' - ', Cp2, Cb2, AxCd2, AxCa2, AxCp2, JAxCd2, JAxCa2, JAxCp2 + ELSE IF ( members(i)%MSecGeom == MSecGeom_Rec ) THEN + write( UnSum, '(1X,I8,2X,I6,2X,I6,2X,ES12.5,2X,I12, 2(2X,ES12.5),(2X,A12),3(2X,ES12.5),(2X,A12),3(2X,ES12.5),2(2X,L12), 3(2X,ES12.5),(2X,A12),2(2X,ES12.5),(2X,A12),10(2X,ES12.5),(2X,A12),2(2X,ES12.5),(2X,A12),10(2X,ES12.5))' ) members(i)%MemberID, & + members(i)%NodeIndx(1), members(i)%NodeIndx(N+1), members(i)%RefLength, N, & + memberVol, MGvolume, ' - ', members(i)%SaMG(1), members(i)%SbMG(1), 0.5*(members(i)%SaMG(1)-members(i)%SaIn(1)), & + ' - ', members(i)%SaMG(N+1), members(i)%SbMG(N+1), 0.5*(members(i)%SaMG(N+1)-members(i)%SaIn(N+1)), & + members(i)%PropPot, filledFlag, members(i)%FillDens, members(i)%FillFSLoc, & + mass_fill, ' - ', CdA1, CdB1, ' - ', CaA1, CaB1, Cp1, Cb1, AxCd1, AxCa1, AxCp1, JAxCd1, JAxCa1, JAxCp1, & + ' - ', CdA2, CdB2, ' - ', CaA2, CaB2, Cp2, Cb2, AxCd2, AxCa2, AxCp2, JAxCd2, JAxCa2, JAxCp2 + END IF end do ! i = 1,numMembers @@ -1050,12 +1276,12 @@ end subroutine Morison_GenerateSimulationNodes !==================================================================================================== -SUBROUTINE SetDepthBasedCoefs( z, tMG, NCoefDpth, CoefDpths, Cd, Ca, Cp, AxCd, AxCa, AxCp, Cb ) +SUBROUTINE SetDepthBasedCoefs_Cyl( z, tMG, NCoefDpth, CoefDpths, Cd, Ca, Cp, AxCd, AxCa, AxCp, Cb ) REAL(ReKi), INTENT (IN ) :: z ! Z location relative to MSL inertial system REAL(ReKi), INTENT (IN ) :: tMG INTEGER, INTENT (IN ) :: NCoefDpth - TYPE(Morison_CoefDpths), INTENT (IN ):: CoefDpths(:) + TYPE(Morison_CoefDpthsCyl), INTENT (IN ):: CoefDpths(:) REAL(ReKi), INTENT ( OUT) :: Cd REAL(ReKi), INTENT ( OUT) :: Ca REAL(ReKi), INTENT ( OUT) :: Cp @@ -1118,12 +1344,90 @@ SUBROUTINE SetDepthBasedCoefs( z, tMG, NCoefDpth, CoefDpths, Cd, Ca, Cp, AxCd, A end if -END SUBROUTINE SetDepthBasedCoefs +END SUBROUTINE SetDepthBasedCoefs_Cyl + + +!==================================================================================================== +SUBROUTINE SetDepthBasedCoefs_Rec( z, tMG, NCoefDpth, CoefDpths, CdA, CdB, CaA, CaB, Cp, AxCd, AxCa, AxCp, Cb ) + + REAL(ReKi), INTENT (IN ) :: z ! Z location relative to MSL inertial system + REAL(ReKi), INTENT (IN ) :: tMG + INTEGER, INTENT (IN ) :: NCoefDpth + TYPE(Morison_CoefDpthsRec), INTENT (IN ):: CoefDpths(:) + REAL(ReKi), INTENT ( OUT) :: CdA + REAL(ReKi), INTENT ( OUT) :: CdB + REAL(ReKi), INTENT ( OUT) :: CaA + REAL(ReKi), INTENT ( OUT) :: CaB + REAL(ReKi), INTENT ( OUT) :: Cp + REAL(ReKi), INTENT ( OUT) :: AxCd + REAL(ReKi), INTENT ( OUT) :: AxCa + REAL(ReKi), INTENT ( OUT) :: AxCp + REAL(ReKi), INTENT ( OUT) :: Cb + + INTEGER :: I, indx1, indx2 + REAL(ReKi) :: dd, s + LOGICAL :: foundLess + + + ! Find the table entry(ies) which match the node's depth value + ! The assumption here is that the depth table is stored from largest + ! to smallest in depth + + foundLess = .FALSE. + indx1 = 1 + indx2 = 1 + + if (NCoefDpth == 0) return + + DO I = 1, NCoefDpth + IF ( CoefDpths(I)%Dpth <= z .AND. .NOT. foundLess ) THEN + indx1 = I + foundLess = .TRUE. + END IF + IF ( CoefDpths(I)%Dpth >= z ) THEN + indx2 = I + END IF + + END DO + + ! Linearly interpolate the coef values based on depth + !CALL FindInterpFactor( z, CoefDpths(indx1)%Dpth, CoefDpths(indx2)%Dpth, s ) + + dd = CoefDpths(indx1)%Dpth - CoefDpths(indx2)%Dpth + IF ( EqualRealNos(dd, 0.0_ReKi) ) THEN + s = 0 + ELSE + s = ( CoefDpths(indx1)%Dpth - z ) / dd + END IF + if ( tMG > 0.0_ReKi ) then + CdA = CoefDpths(indx1)%DpthCdAMG*(1-s) + CoefDpths(indx2)%DpthCdAMG*s + CdB = CoefDpths(indx1)%DpthCdBMG*(1-s) + CoefDpths(indx2)%DpthCdBMG*s + CaA = CoefDpths(indx1)%DpthCaAMG*(1-s) + CoefDpths(indx2)%DpthCaAMG*s + CaB = CoefDpths(indx1)%DpthCaBMG*(1-s) + CoefDpths(indx2)%DpthCaBMG*s + Cp = CoefDpths(indx1)%DpthCpMG*(1-s) + CoefDpths(indx2)%DpthCpMG*s + AxCd = CoefDpths(indx1)%DpthAxCdMG*(1-s) + CoefDpths(indx2)%DpthAxCdMG*s + AxCa = CoefDpths(indx1)%DpthAxCaMG*(1-s) + CoefDpths(indx2)%DpthAxCaMG*s + AxCp = CoefDpths(indx1)%DpthAxCpMG*(1-s) + CoefDpths(indx2)%DpthAxCpMG*s + Cb = CoefDpths(indx1)%DpthCbMG*(1-s) + CoefDpths(indx2)%DpthCbMG*s + else + CdA = CoefDpths(indx1)%DpthCdA*(1-s) + CoefDpths(indx2)%DpthCdA*s + CdB = CoefDpths(indx1)%DpthCdB*(1-s) + CoefDpths(indx2)%DpthCdB*s + CaA = CoefDpths(indx1)%DpthCaA*(1-s) + CoefDpths(indx2)%DpthCaA*s + CaB = CoefDpths(indx1)%DpthCaB*(1-s) + CoefDpths(indx2)%DpthCaB*s + Cp = CoefDpths(indx1)%DpthCp*(1-s) + CoefDpths(indx2)%DpthCp*s + AxCd = CoefDpths(indx1)%DpthAxCd*(1-s) + CoefDpths(indx2)%DpthAxCd*s + AxCa = CoefDpths(indx1)%DpthAxCa*(1-s) + CoefDpths(indx2)%DpthAxCa*s + AxCp = CoefDpths(indx1)%DpthAxCp*(1-s) + CoefDpths(indx2)%DpthAxCp*s + Cb = CoefDpths(indx1)%DpthCb*(1-s) + CoefDpths(indx2)%DpthCb*s + end if + + +END SUBROUTINE SetDepthBasedCoefs_Rec !==================================================================================================== -SUBROUTINE SetExternalHydroCoefs( MSL2SWL, MCoefMod, MmbrCoefIDIndx, SimplCd, SimplCdMG, SimplCa, SimplCaMG, SimplCp, & +SUBROUTINE SetExternalHydroCoefs_Cyl( MSL2SWL, MCoefMod, MmbrCoefIDIndx, SimplCd, SimplCdMG, SimplCa, SimplCaMG, SimplCp, & SimplCpMG, SimplAxCd, SimplAxCdMG, SimplAxCa, SimplAxCaMG, SimplAxCp, SimplAxCpMG, SimplCb, SimplCbMG, SimplMCF, CoefMembers, & NCoefDpth, CoefDpths, nodes, member ) ! This private subroutine generates the Cd, Ca, Cp, Cb, CdMG, CaMG, CpMG, and CbMG coefs for the member based on @@ -1147,9 +1451,9 @@ SUBROUTINE SetExternalHydroCoefs( MSL2SWL, MCoefMod, MmbrCoefIDIndx, SimplCd, S real(ReKi), intent(in ) :: SimplCb real(ReKi), intent(in ) :: SimplCbMG logical, intent(in ) :: SimplMCF - type(Morison_CoefMembers), allocatable, intent(in ) :: CoefMembers(:) + type(Morison_CoefMembersCyl), allocatable, intent(in ) :: CoefMembers(:) integer(IntKi), intent(in ) :: NCoefDpth - type(Morison_CoefDpths), allocatable, intent(in ) :: CoefDpths(:) + type(Morison_CoefDpthsCyl),allocatable, intent(in ) :: CoefDpths(:) type(Morison_NodeType), allocatable, intent(in ) :: nodes(:) type(Morison_MemberType), intent(inout) :: member @@ -1181,7 +1485,7 @@ SUBROUTINE SetExternalHydroCoefs( MSL2SWL, MCoefMod, MmbrCoefIDIndx, SimplCd, S member%PropMCF = SimplMCF CASE (2) ! Depth-based model: coefficients are set using depth-based table data do i = 1, member%NElements + 1 - CALL SetDepthBasedCoefs( nodes(member%NodeIndx(i))%Position(3)+MSL2SWL, member%tMG(i), NCoefDpth, CoefDpths, member%Cd(i), member%Ca(i), & + CALL SetDepthBasedCoefs_Cyl( nodes(member%NodeIndx(i))%Position(3)+MSL2SWL, member%tMG(i), NCoefDpth, CoefDpths, member%Cd(i), member%Ca(i), & member%Cp(i), member%AxCd(i), member%AxCa(i), member%AxCp(i), member%Cb(i) ) end do member%PropMCF = CoefDpths(1)%DpthMCF @@ -1210,7 +1514,110 @@ SUBROUTINE SetExternalHydroCoefs( MSL2SWL, MCoefMod, MmbrCoefIDIndx, SimplCd, S member%propMCF = CoefMembers(MmbrCoefIDIndx)%MemberMCF end select -end subroutine SetExternalHydroCoefs +end subroutine SetExternalHydroCoefs_Cyl + +!==================================================================================================== +SUBROUTINE SetExternalHydroCoefs_Rec( MSL2SWL, MCoefMod, MmbrCoefIDIndx, SimplCdA, SimplCdAMG, SimplCdB, SimplCdBMG, SimplCaA, SimplCaAMG, SimplCaB, SimplCaBMG, SimplCp, & + SimplCpMG, SimplAxCd, SimplAxCdMG, SimplAxCa, SimplAxCaMG, SimplAxCp, SimplAxCpMG, SimplCb, SimplCbMG, SimplMCF, CoefMembers, & + NCoefDpth, CoefDpths, nodes, member ) +! This private subroutine generates the Cd, Ca, Cp, Cb, CdMG, CaMG, CpMG, and CbMG coefs for the member based on +! the input data. +!---------------------------------------------------------------------------------------------------- + real(ReKi), intent(in ) :: MSL2SWL + integer(IntKi), intent(in ) :: MCoefMod + integer(IntKi), intent(in ) :: MmbrCoefIDIndx + real(ReKi), intent(in ) :: SimplCdA + real(ReKi), intent(in ) :: SimplCdAMG + real(ReKi), intent(in ) :: SimplCdB + real(ReKi), intent(in ) :: SimplCdBMG + real(ReKi), intent(in ) :: SimplCaA + real(ReKi), intent(in ) :: SimplCaAMG + real(ReKi), intent(in ) :: SimplCaB + real(ReKi), intent(in ) :: SimplCaBMG + real(ReKi), intent(in ) :: SimplCp + real(ReKi), intent(in ) :: SimplCpMG + real(ReKi), intent(in ) :: SimplAxCd + real(ReKi), intent(in ) :: SimplAxCdMG + real(ReKi), intent(in ) :: SimplAxCa + real(ReKi), intent(in ) :: SimplAxCaMG + real(ReKi), intent(in ) :: SimplAxCp + real(ReKi), intent(in ) :: SimplAxCpMG + real(ReKi), intent(in ) :: SimplCb + real(ReKi), intent(in ) :: SimplCbMG + logical, intent(in ) :: SimplMCF + type(Morison_CoefMembersRec), allocatable, intent(in ) :: CoefMembers(:) + integer(IntKi), intent(in ) :: NCoefDpth + type(Morison_CoefDpthsRec), allocatable, intent(in ) :: CoefDpths(:) + type(Morison_NodeType), allocatable, intent(in ) :: nodes(:) + type(Morison_MemberType), intent(inout) :: member + + integer(IntKi) :: i + real(ReKi) :: s + + select case ( MCoefMod ) + + case (1) ! Simple model : all nodes receive the same coefficients + do i = 1, member%NElements + 1 + if ( member%tMG(i) > 0.0_ReKi ) then + member%CdA (i) = SimplCdAMG + member%CdB (i) = SimplCdBMG + member%CaA (i) = SimplCaAMG + member%CaB (i) = SimplCaBMG + member%Cp (i) = SimplCpMG + member%AxCd (i) = SimplAxCdMG + member%AxCa (i) = SimplAxCaMG + member%AxCp (i) = SimplAxCpMG + member%Cb (i) = SimplCbMG + else + member%CdA (i) = SimplCdA + member%CdB (i) = SimplCdB + member%CaA (i) = SimplCaA + member%CaB (i) = SimplCaB + member%Cp (i) = SimplCp + member%AxCd (i) = SimplAxCd + member%AxCa (i) = SimplAxCa + member%AxCp (i) = SimplAxCp + member%Cb (i) = SimplCb + end if + end do + member%PropMCF = SimplMCF + CASE (2) ! Depth-based model: coefficients are set using depth-based table data + do i = 1, member%NElements + 1 + CALL SetDepthBasedCoefs_Rec( nodes(member%NodeIndx(i))%Position(3)+MSL2SWL, member%tMG(i), NCoefDpth, CoefDpths, member%CdA(i), member%CdB(i), & + member%CaA(i), member%CaB(i), member%Cp(i), member%AxCd(i), member%AxCa(i), member%AxCp(i), member%Cb(i) ) + end do + member%PropMCF = CoefDpths(1)%DpthMCF + CASE (3) ! Member-based model: coefficients set using member-specific coefficient tables + do i = 1, member%NElements + 1 + ! Pull member end-node data from the tables and then linearly interpolate it onto the interior member nodes + s = (real(i,ReKi)-1.0) / real(member%NElements,ReKi) + if ( member%tMG(i) > 0.0_ReKi ) then + member%CdA (i) = CoefMembers(MmbrCoefIDIndx)%MemberCdAMG1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCdAMG2 *s + member%CdB (i) = CoefMembers(MmbrCoefIDIndx)%MemberCdBMG1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCdBMG2 *s + member%CaA (i) = CoefMembers(MmbrCoefIDIndx)%MemberCaAMG1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCaAMG2 *s + member%CaB (i) = CoefMembers(MmbrCoefIDIndx)%MemberCaBMG1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCaBMG2 *s + member%Cp (i) = CoefMembers(MmbrCoefIDIndx)%MemberCpMG1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCpMG2 *s + member%Cb (i) = CoefMembers(MmbrCoefIDIndx)%MemberCbMG1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCbMG2 *s + member%AxCd (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCaMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCdMG2*s + member%AxCa (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCaMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCaMG2*s + member%AxCp (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCpMG1*(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCpMG2*s + else + member%CdA (i) = CoefMembers(MmbrCoefIDIndx)%MemberCdA1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCdA2 *s + member%CdB (i) = CoefMembers(MmbrCoefIDIndx)%MemberCdB1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCdB2 *s + member%CaA (i) = CoefMembers(MmbrCoefIDIndx)%MemberCaA1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCaA2 *s + member%CaB (i) = CoefMembers(MmbrCoefIDIndx)%MemberCaB1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCaB2 *s + member%Cp (i) = CoefMembers(MmbrCoefIDIndx)%MemberCp1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCp2 *s + member%Cb (i) = CoefMembers(MmbrCoefIDIndx)%MemberCb1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberCb2 *s + member%AxCd (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCd1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCd2 *s + member%AxCa (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCa1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCa2 *s + member%AxCp (i) = CoefMembers(MmbrCoefIDIndx)%MemberAxCp1 *(1-s) + CoefMembers(MmbrCoefIDIndx)%MemberAxCp2 *s + end if + end do + member%propMCF = CoefMembers(MmbrCoefIDIndx)%MemberMCF + end select + +end subroutine SetExternalHydroCoefs_Rec + !---------------------------------------------------------------------------------------------------------------------------------- SUBROUTINE SetNodeMG( numMGDepths, MGDepths, node, MSL2SWL, tMG, MGdensity ) @@ -1252,9 +1659,7 @@ SUBROUTINE SetNodeMG( numMGDepths, MGDepths, node, MSL2SWL, tMG, MGdensity ) tMG = 0.0 MGdensity = 0.0 ELSE - ! Linearly interpolate the coef values based on depth - !CALL FindInterpFactor( z, CoefDpths(indx1)%Dpth, CoefDpths(indx2)%Dpth, s ) - + ! Linearly interpolate the marine growth thickness and density based on depth dd = MGDepths(indx1)%MGDpth - MGDepths(indx2)%MGDpth IF ( EqualRealNos(dd, 0.0_ReKi) ) THEN s = 0.0_ReKi @@ -1283,9 +1688,6 @@ subroutine AllocateMemberDataArrays( member, memberLoads, errStat, errMsg ) errStat = ErrID_None errMSg = '' call AllocAry(member%NodeIndx , member%NElements+1, 'member%NodeIndx' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%dRdl_mg , member%NElements, 'member%dRdl_mg' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%dRdl_mg_b , member%NElements, 'member%dRdl_mg_b' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%dRdl_in , member%NElements, 'member%dRdl_in' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%floodstatus , member%NElements, 'member%floodstatus' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%alpha , member%NElements, 'member%alpha' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%alpha_fb , member%NElements, 'member%alpha_fb' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) @@ -1296,48 +1698,76 @@ subroutine AllocateMemberDataArrays( member, memberLoads, errStat, errMsg ) call AllocAry(member%h_cfb_u , member%NElements, 'member%h_cfb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%I_lfb_l , member%NElements, 'member%I_lfb_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%I_lfb_u , member%NElements, 'member%I_lfb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%I_rfb_l , member%NElements, 'member%I_rfb_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%I_rfb_u , member%NElements, 'member%I_rfb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%m_mg_l , member%NElements, 'member%m_mg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%m_mg_u , member%NElements, 'member%m_mg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%h_cmg_l , member%NElements, 'member%h_cmg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%h_cmg_u , member%NElements, 'member%h_cmg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%I_lmg_l , member%NElements, 'member%I_lmg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%I_lmg_u , member%NElements, 'member%I_lmg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%I_rmg_l , member%NElements, 'member%I_rmg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%I_rmg_u , member%NElements, 'member%I_rmg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%Cfl_fb , member%NElements, 'member%Cfl_fb ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%Cfr_fb , member%NElements, 'member%Cfr_fb ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%CM0_fb , member%NElements, 'member%CM0_fb ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%R , member%NElements+1, 'member%R ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%RMG , member%NElements+1, 'member%RMG ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%RMGB , member%NElements+1, 'member%RMGB ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%Rin , member%NElements+1, 'member%Rin ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%tMG , member%NElements+1, 'member%tMG ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%MGdensity , member%NElements+1, 'member%MGdensity ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%Cd , member%NElements+1, 'member%Cd ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry(member%Ca , member%NElements+1, 'member%Ca ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%Cp , member%NElements+1, 'member%Cp ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%AxCd , member%NElements+1, 'member%AxCd ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%AxCa , member%NElements+1, 'member%AxCa ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%AxCp , member%NElements+1, 'member%AxCp ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry(member%Cb , member%NElements+1, 'member%Cb ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( memberLoads%F_D , 6, member%NElements+1, 'memberLoads%F_D' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( memberLoads%F_A , 6, member%NElements+1, 'memberLoads%F_A' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( memberLoads%F_B , 6, member%NElements+1, 'memberLoads%F_B' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( memberLoads%F_BF , 6, member%NElements+1, 'memberLoads%F_BF' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - call AllocAry( memberLoads%F_I , 6, member%NElements+1, 'memberLoads%F_I' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) - 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_D , 6, member%NElements+1, 'memberLoads%F_D' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_A , 6, member%NElements+1, 'memberLoads%F_A' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_B , 6, member%NElements+1, 'memberLoads%F_B' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_BF , 6, member%NElements+1, 'memberLoads%F_BF' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( memberLoads%F_I , 6, member%NElements+1, 'memberLoads%F_I' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + 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) + + ! Shape dependent variables + if (member%MSecGeom == MSecGeom_Cyl) then + call AllocAry(member%dRdl_mg , member%NElements, 'member%dRdl_mg' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%dRdl_mg_b , member%NElements, 'member%dRdl_mg_b' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%dRdl_in , member%NElements, 'member%dRdl_in' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_rfb_l , member%NElements, 'member%I_rfb_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_rfb_u , member%NElements, 'member%I_rfb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_rmg_l , member%NElements, 'member%I_rmg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_rmg_u , member%NElements, 'member%I_rmg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%R , member%NElements+1, 'member%R ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%RMG , member%NElements+1, 'member%RMG ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%RMGB , member%NElements+1, 'member%RMGB ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Rin , member%NElements+1, 'member%Rin ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Cd , member%NElements+1, 'member%Cd ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Ca , member%NElements+1, 'member%Ca ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + else if (member%MSecGeom == MSecGeom_Rec) then + call AllocAry(member%dSadl_mg , member%NElements, 'member%dSadl_mg' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%dSadl_mg_b , member%NElements, 'member%dSadl_mg_b' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%dSadl_in , member%NElements, 'member%dSadl_in' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%dSbdl_mg , member%NElements, 'member%dSbdl_mg' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%dSbdl_mg_b , member%NElements, 'member%dSbdl_mg_b' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%dSbdl_in , member%NElements, 'member%dSbdl_in' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_xfb_l , member%NElements, 'member%I_xfb_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_xfb_u , member%NElements, 'member%I_xfb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_yfb_l , member%NElements, 'member%I_yfb_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_yfb_u , member%NElements, 'member%I_yfb_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_xmg_l , member%NElements, 'member%I_xmg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_xmg_u , member%NElements, 'member%I_xmg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_ymg_l , member%NElements, 'member%I_ymg_l ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%I_ymg_u , member%NElements, 'member%I_ymg_u ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Sa , member%NElements+1, 'member%Sa ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%SaMG , member%NElements+1, 'member%SaMG ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%SaMGB , member%NElements+1, 'member%SaMGB ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Sain , member%NElements+1, 'member%Sain ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Sb , member%NElements+1, 'member%Sb ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%SbMG , member%NElements+1, 'member%SbMG ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%SbMGB , member%NElements+1, 'member%SbMGB ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%Sbin , member%NElements+1, 'member%Sbin ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%CdA , member%NElements+1, 'member%CdA ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%CdB , member%NElements+1, 'member%CdB ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%CaA , member%NElements+1, 'member%CaA ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry(member%CaB , member%NElements+1, 'member%CaB ', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + end if if (ErrStat >= AbortErrLev) return ! Initialize everything to zero member%NodeIndx = 0.0_ReKi - member%dRdl_mg = 0.0_ReKi - member%dRdl_mg_b = 0.0_ReKi - member%dRdl_in = 0.0_ReKi member%floodstatus = 0.0_ReKi member%alpha = 0.0_ReKi member%alpha_fb = 0.0_ReKi @@ -1348,27 +1778,15 @@ subroutine AllocateMemberDataArrays( member, memberLoads, errStat, errMsg ) member%h_cfb_u = 0.0_ReKi member%I_lfb_l = 0.0_ReKi member%I_lfb_u = 0.0_ReKi - member%I_rfb_l = 0.0_ReKi - member%I_rfb_u = 0.0_ReKi member%m_mg_l = 0.0_ReKi member%m_mg_u = 0.0_ReKi member%h_cmg_l = 0.0_ReKi member%h_cmg_u = 0.0_ReKi member%I_lmg_l = 0.0_ReKi member%I_lmg_u = 0.0_ReKi - member%I_rmg_l = 0.0_ReKi - member%I_rmg_u = 0.0_ReKi - member%Cfl_fb = 0.0_ReKi - member%Cfr_fb = 0.0_ReKi - member%CM0_fb = 0.0_ReKi - member%R = 0.0_ReKi - member%RMG = 0.0_ReKi - member%RMGB = 0.0_ReKi - member%Rin = 0.0_ReKi + member%tMG = 0.0_ReKi member%MGdensity = 0.0_ReKi - member%Cd = 0.0_ReKi - member%Ca = 0.0_ReKi member%Cp = 0.0_ReKi member%AxCd = 0.0_ReKi member%AxCa = 0.0_ReKi @@ -1383,6 +1801,49 @@ subroutine AllocateMemberDataArrays( member, memberLoads, errStat, errMsg ) memberLoads%F_WMG = 0.0_ReKi memberLoads%F_IMG = 0.0_ReKi + if (member%MSecGeom == MSecGeom_Cyl) then + member%dRdl_mg = 0.0_ReKi + member%dRdl_mg_b = 0.0_ReKi + member%dRdl_in = 0.0_ReKi + member%I_rfb_l = 0.0_ReKi + member%I_rfb_u = 0.0_ReKi + member%I_rmg_l = 0.0_ReKi + member%I_rmg_u = 0.0_ReKi + member%R = 0.0_ReKi + member%RMG = 0.0_ReKi + member%RMGB = 0.0_ReKi + member%Rin = 0.0_ReKi + member%Cd = 0.0_ReKi + member%Ca = 0.0_ReKi + else if (member%MSecGeom == MSecGeom_Rec) then + member%dSadl_mg = 0.0_ReKi + member%dSadl_mg_b = 0.0_ReKi + member%dSadl_in = 0.0_ReKi + member%dSbdl_mg = 0.0_ReKi + member%dSbdl_mg_b = 0.0_ReKi + member%dSbdl_in = 0.0_ReKi + member%I_xfb_l = 0.0_ReKi + member%I_xfb_u = 0.0_ReKi + member%I_yfb_l = 0.0_ReKi + member%I_yfb_u = 0.0_ReKi + member%I_xmg_l = 0.0_ReKi + member%I_xmg_u = 0.0_ReKi + member%I_ymg_l = 0.0_ReKi + member%I_ymg_u = 0.0_ReKi + member%Sa = 0.0_ReKi + member%SaMG = 0.0_ReKi + member%SaMGB = 0.0_ReKi + member%Sain = 0.0_ReKi + member%Sb = 0.0_ReKi + member%SbMG = 0.0_ReKi + member%SbMGB = 0.0_ReKi + member%Sbin = 0.0_ReKi + member%CdA = 0.0_ReKi + member%CdB = 0.0_ReKi + member%CaA = 0.0_ReKi + member%CaB = 0.0_ReKi + end if + end subroutine AllocateMemberDataArrays !---------------------------------------------------------------------------------------------------------------------------------- subroutine FlipMemberNodeData( member, nodes, doSwap) @@ -1421,23 +1882,28 @@ subroutine FlipMemberNodeData( member, nodes, doSwap) member%NodeIndx(1+i) = member%NodeIndx(numMemNodes-i) member%NodeIndx(numMemNodes-i) = indx end do + + ! Flip the sign of the spin angle + member%MSpinOrient = -member%MSpinOrient end if end subroutine FlipMemberNodeData !---------------------------------------------------------------------------------------------------------------------------------- -subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrFilledIDIndx, propSet1, propSet2, InitInp, errStat, errMsg ) +subroutine SetMemberProperties_Cyl( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrFilledIDIndx, propSet1, propSet2, InitInp, errStat, errMsg ) real(ReKi), intent (in ) :: gravity type(Morison_MemberType), intent (inout) :: member integer(IntKi), intent (in ) :: MCoefMod integer(IntKi), intent (in ) :: MmbrCoefIDIndx integer(IntKi), intent (in ) :: MmbrFilledIDIndx - type(Morison_MemberPropType), intent (in ) :: propSet1 ! property set of node 1 - type(Morison_MemberPropType), intent (in ) :: propSet2 ! property set of node N+1 + type(Morison_MemberPropTypeCyl), intent (in ) :: propSet1 ! property set of node 1 + type(Morison_MemberPropTypeCyl), intent (in ) :: propSet2 ! property set of node N+1 type(Morison_InitInputType), intent (in ) :: InitInp integer(IntKi), intent ( out) :: errStat ! returns a non-zero value when an error occurs character(*), intent ( out) :: errMsg ! Error message if errStat /= ErrID_None + character(*), parameter :: RoutineName = 'SetMemberProperties_Cyl' + integer(IntKi) :: N, i real(ReKi) :: s, dl real(ReKi) :: vec(3) @@ -1497,10 +1963,10 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF member%RMG(i) = member%R(i) + member%tMG(i) end do - call SetExternalHydroCoefs( InitInp%WaveField%MSL2SWL, MCoefMod, MmbrCoefIDIndx, InitInp%SimplCd, InitInp%SimplCdMG, InitInp%SimplCa, InitInp%SimplCaMG, InitInp%SimplCp, & + call SetExternalHydroCoefs_Cyl( InitInp%WaveField%MSL2SWL, MCoefMod, MmbrCoefIDIndx, InitInp%SimplCd, InitInp%SimplCdMG, InitInp%SimplCa, InitInp%SimplCaMG, InitInp%SimplCp, & InitInp%SimplCpMG, InitInp%SimplAxCd, InitInp%SimplAxCdMG, InitInp%SimplAxCa, InitInp%SimplAxCaMG, InitInp%SimplAxCp, InitInp%SimplAxCpMG, & InitInp%SimplCb, InitInp%SimplCbMG, InitInp%SimplMCF, & - InitInp%CoefMembers, InitInp%NCoefDpth, InitInp%CoefDpths, InitInp%Nodes, member ) + InitInp%CoefMembersCyl, InitInp%NCoefDpthCyl, InitInp%CoefDpthsCyl, InitInp%Nodes, member ) ! calculate member radius with marine growth scaled by sqrt(Cb) for buoyancy/hydrostatic load calculation do i = 1, member%NElements+1 @@ -1515,25 +1981,25 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF IF ( member%PropMCF .AND. ( .NOT. member%PropPot )) THEN ! Check if surface piercing IF ( Za*Zb > 0 ) THEN ! Two end joints of the member on the same side of the SWL - CALL SetErrStat(ErrID_Fatal, 'MacCamy-Fuchs members must be surface piercing. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + CALL SetErrStat(ErrID_Fatal, 'MacCamy-Fuchs members must be surface piercing. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) RETURN END IF ! Check inclination If ( ABS(phi) .GE. 0.174533 ) THEN ! If inclination from vertical is greater than 10 deg - CALL SetErrStat(ErrID_Fatal, 'MacCamy-Fuchs members must be within 10 degrees from vertical. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + CALL SetErrStat(ErrID_Fatal, 'MacCamy-Fuchs members must be within 10 degrees from vertical. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) RETURN END IF ! Check radius DO i = 1, member%NElements+1 IF ( (member%RMG(i) .GT. 1.1_ReKi*REAL(0.5_SiKi*InitInp%WaveField%MCFD)) .OR. (member%RMG(i) .LT. 0.9_ReKi*REAL(0.5_SiKi*InitInp%WaveField%MCFD)) ) THEN ! Error because MacCamy-Fuchs members must have a diameter within +/-10% of MCFD specified in seastate. - CALL SetErrStat(ErrID_Fatal, 'MacCamy-Fuchs members must have a diameter within +/-10% of MCFD specified in the SeaState input file. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + CALL SetErrStat(ErrID_Fatal, 'MacCamy-Fuchs members must have a diameter within +/-10% of MCFD specified in the SeaState input file. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) RETURN END IF END DO ! Check draft-to-radius ratio IF ( (-InitInp%Nodes(member%NodeIndx(1))%Position(3)) < 0.5_SiKi*InitInp%WaveField%MCFD ) THEN - CALL SetErrStat(ErrID_Fatal, 'Initial draft of MacCamy-Fuchs members should be at least as large as their radius. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + CALL SetErrStat(ErrID_Fatal, 'Initial draft of MacCamy-Fuchs members should be at least as large as their radius. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) RETURN END IF END IF @@ -1574,16 +2040,16 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF ! Check the member does not exhibit any of the following conditions if (.not. member%PropPot) then - if (member%MHstLMod == 1) then + if (member%MHstLMod == 1) then ! Only cylindrical members are allowed to use MHstLMod = 1 if ( abs(Zb) < abs(member%Rmg(N+1)*sinPhi) ) then - call SetErrStat(ErrID_Fatal, 'The upper end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + call SetErrStat(ErrID_Fatal, 'The upper end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) end if if ( abs(Za) < abs(member%Rmg(1)*sinPhi) ) then - call SetErrStat(ErrID_Fatal, 'The lower end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + call SetErrStat(ErrID_Fatal, 'The lower end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) end if end if if ( ( Za < -InitInp%WaveField%EffWtrDpth .and. Zb >= -InitInp%WaveField%EffWtrDpth ) .and. ( phi > 10.0*d2r .or. abs((member%RMG(N+1) - member%RMG(1))/member%RefLength)>0.1 ) ) then - call SetErrStat(ErrID_Fatal, 'A member which crosses the seabed must not be inclined more than 10 degrees from vertical or have a taper larger than 0.1. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + call SetErrStat(ErrID_Fatal, 'A member which crosses the seabed must not be inclined more than 10 degrees from vertical or have a taper larger than 0.1. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) end if end if @@ -1599,7 +2065,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF if (Za > -InitInp%WaveField%EffWtrDpth) then ! find the lowest node above the seabed if (cosPhi < 0.173648178 ) then ! phi > 80 degrees and member is seabed crossing - call SetErrStat(ErrID_Fatal, 'A seabed crossing member must have an inclination angle of <= 80 degrees from vertical. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties' ) + call SetErrStat(ErrID_Fatal, 'A seabed crossing member must have an inclination angle of <= 80 degrees from vertical. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) end if member%h_floor = (-InitInp%WaveField%EffWtrDpth-Za)/cosPhi ! get the distance from the node to the seabed along the member axis (negative value) @@ -1623,14 +2089,16 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF member%dRdl_in( i) = (member%Rin( i+1) - member%Rin( i))/dl member%dRdl_mg_b(i) = (member%RMGB(i+1) - member%RMGB(i))/dl - member%alpha( i) = GetAlpha(member%RMGB(i), member%RMGB(i+1)) ! Only used to distribute external buoyancy load to nodes - member%alpha_fb(i) = GetAlpha(member%Rin( i), member%Rin( i+1)) + member%alpha( i) = GetAlphaCyl(member%RMGB(i), member%RMGB(i+1)) ! Only used to distribute external buoyancy load to nodes + member%alpha_fb(i) = GetAlphaCyl(member%Rin( i), member%Rin( i+1)) end do - member%Vinner = 0.0_ReKi ! Total volume of member without marine growth - member%Vouter = 0.0_ReKi ! Total outer volume of member including marine growth - member%Vballast = 0.0_ReKi ! Total ballasted volume of member + member%Vinner = 0.0_ReKi ! Total volume of member without marine growth + member%Vouter = 0.0_ReKi ! Total outer volume of member including marine growth + member%Vballast = 0.0_ReKi ! Total ballasted volume of member + member%elem_fill = 0 ! Last (partially) filled element of the member + member%h_fill = 0.0 ! Axial length of elem_fill occupied by water ballast ! force-related constants for each element do i = 1, member%NElements @@ -1650,8 +2118,8 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF RmidMG = 0.5*(member%RMG(i)+member%RMG(i+1)) ! radius with marine growth at middle of segment, where division occurs Lmid = 0.5*dl ! = 0.5*(R2-R1)/m half-length of segment - CALL MarineGrowthPartSegment(member%R(i ), Rmid, member%RMG(i ),RmidMG, Lmid, member%MGDensity(i), Vinner_l, Vouter_l, member%m_mg_l(i), member%h_cmg_l(i), member%I_lmg_l(i), member%I_rmg_l(i)) ! get precomputed quantities for lower half-segment - CALL MarineGrowthPartSegment(member%R(i+1), Rmid, member%RMG(i+1),RmidMG,-Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomputed quantities for upper half-segment + CALL MarineGrowthPartSegmentCyl(member%R(i ), Rmid, member%RMG(i ),RmidMG, Lmid, member%MGDensity(i), Vinner_l, Vouter_l, member%m_mg_l(i), member%h_cmg_l(i), member%I_lmg_l(i), member%I_rmg_l(i)) ! get precomputed quantities for lower half-segment + CALL MarineGrowthPartSegmentCyl(member%R(i+1), Rmid, member%RMG(i+1),RmidMG,-Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomputed quantities for upper half-segment else if (i == member%i_floor) then ! crossing seabed: get the properties for part-element above the seabed and lump to the upper node @@ -1660,7 +2128,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF RmidMG = (-member%h_floor*member%RMG(i) +(dl+member%h_floor)*member%RMG(i+1))/dl Lmid = -member%h_floor - CALL MarineGrowthPartSegment(member%R(i+1), Rmid, member%RMG(i+1),RmidMG, -Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomputed quantities for upper half-segment + CALL MarineGrowthPartSegmentCyl(member%R(i+1), Rmid, member%RMG(i+1),RmidMG, -Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_rmg_u(i)) ! get precomputed quantities for upper half-segment Vinner_l = 0.0 Vouter_l = 0.0 end if @@ -1675,8 +2143,8 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF ! get the properties for each half-element lumped to the appropriate node Rmidin = 0.5*(member%Rin(i)+member%Rin(i+1)) ! radius of member interior at middle of segment, where division occurs Lmid = 0.5*dl ! = 0.5*(R2-R1)/m half-length of segment - CALL FloodedBallastPartSegment(member%Rin(i ), Rmidin, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_rfb_l(i)) ! get precomputed quantities for lower half-segment - CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomputed quantities for upper half-segment + CALL FloodedBallastPartSegmentCyl(member%Rin(i ), Rmidin, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_rfb_l(i)) ! get precomputed quantities for lower half-segment + CALL FloodedBallastPartSegmentCyl(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomputed quantities for upper half-segment ! partially filled element, so split at FillFSLoc else if ((i > member%i_floor) .AND. (member%FillFSLoc < Zb)) then @@ -1684,16 +2152,15 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF ! get the properties for each partial-element lumped to the appropriate node Lmid = member%FillFSLoc - Za Rmidin = member%Rin(i)+(Lmid/(Zb-Za))*(member%Rin(i+1)-member%Rin(i)) ! radius of member interior at middle of segment, where division occurs - CALL FloodedBallastPartSegment(member%Rin(i ), Rmidin, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_rfb_l(i)) ! get precomputed quantities for lower half-segment - CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, 0.0_ReKi, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomputed quantities for upper half-segment + CALL FloodedBallastPartSegmentCyl(member%Rin(i ), Rmidin, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_rfb_l(i)) ! get precomputed quantities for lower half-segment + CALL FloodedBallastPartSegmentCyl(member%Rin(i+1), Rmidin, -Lmid, 0.0_ReKi, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomputed quantities for upper half-segment else if (i == member%i_floor) then ! Hopefully we don't have a partially filled element crossing the seabed. ! crossing seabed: get the properties for part-element above the seabed and lump to the upper node - RmidMG = (-member%h_floor*member%RMG(i) +(dl+member%h_floor)*member%RMG(i+1))/dl Rmidin = (-member%h_floor*member%Rin(i) +(dl+member%h_floor)*member%Rin(i+1))/dl Lmid = -member%h_floor - CALL FloodedBallastPartSegment(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomputed quantities for upper half-segment + CALL FloodedBallastPartSegmentCyl(member%Rin(i+1), Rmidin, -Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_rfb_u(i)) ! get precomputed quantities for upper half-segment Vballast_l = 0.0 end if @@ -1721,7 +2188,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF member%Vsubmerged = member%Vsubmerged + Vouter_l + Vouter_u else if ((0.0 > Za) .AND. (0.0 < Zb)) then ! Bug fix per OpenFAST issue #844 GJH 2/3/2022 ! if (i == 1) then - ! call SetErrStat(ErrID_Fatal, 'The lowest element of a member must not cross the free surface. This is true for MemberID '//trim(num2lstr(member%MemberID)), errStat, errMsg, 'SetMemberProperties') + ! call SetErrStat(ErrID_Fatal, 'The lowest element of a member must not cross the free surface. This is true for MemberID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName) ! end if ! partially submerged element @@ -1729,7 +2196,7 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF member%Vouter = member%Vouter + Vouter_l + Vouter_u ! compute volume portion which is submerged Lmid = -Za/cosPhi - call TaperCalc( member%Rmg(i), member%Rmg(i)+Lmid*member%dRdl_mg(i), Lmid, Vouter_l, h_c) + call CylTaperCalc( member%Rmg(i), member%Rmg(i)+Lmid*member%dRdl_mg(i), Lmid, Vouter_l, h_c) member%Vsubmerged = member%Vsubmerged + Vouter_l @@ -1743,73 +2210,391 @@ subroutine SetMemberProperties( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrF ! NOTE: this section of code is somewhat redundant with "flooded ballast inertia" section above li = dl*(i-1) - ! fully buried element - if (Zb < -InitInp%WaveField%EffWtrDpth) then + + if (Zb < -InitInp%WaveField%EffWtrDpth) then ! Fully buried element + member%floodstatus(i) = 0 - ! fully filled elements - else if (member%memfloodstatus > 0 .and. member%FillFSLoc > Zb) then + else if (member%memfloodstatus > 0 .and. member%FillFSLoc >= Zb) then ! Fully flooded elements + member%floodstatus(i) = 1 + if ( EqualRealNos(member%FillFSLoc, Zb) .or. (i==member%NElements) ) then ! No partially filled elements + member%elem_fill = i + member%h_fill = dl + end if member%Vballast = member%Vballast + Vballast_l + Vballast_u - ! depth-adjusted force distribution constant - member%alpha_fb_star(i) = member%alpha_fb(i)*( Zb - member%FillFSLoc )**3 / ( ( (1-member%alpha_fb(i))*(Za - member%FillFSLoc))**3 + member%alpha_fb(i)*(Zb - member%FillFSLoc)**3 ) - - ! force and moment magnitude constants - - member%Cfl_fb(i) = TwoPi * member%dRdl_in(i) * member%FillDens * gravity * dl *( (li - member%l_fill)*member%Rin(i) + 0.5*((li - member%l_fill)* member%dRdl_in(i) + member%Rin(i))*dl + 1.0/3.0* member%dRdl_in(i)*dl**2 ) - member%Cfr_fb(i) = Pi * member%FillDens * gravity * dl *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*dl +1.0/3.0 * member%dRdl_in(i)**2 *dl**2 ) - member%CM0_fb(i) = TwoPi * member%FillDens * gravity * dl *( 0.25*dl**3* member%dRdl_in(i)**4 + 0.25*dl**3* member%dRdl_in(i)**2 + dl**2* member%dRdl_in(i)**3*member%Rin(i) + 2.0/3.0*dl**2* member%dRdl_in(i)*member%Rin(i) + 1.5*dl* member%dRdl_in(i)**2*member%Rin(i)**2 + 0.5*dl*member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)**3 ) - - - ! partially filled element - else if ((member%memfloodstatus > 0) .and. (member%FillFSLoc > Za) .AND. (member%FillFSLoc < Zb)) then - - ! Need to enforce the modeling requirement that the first/bottom-most element of a member be fully flooded - if (i == 1) then - call SetErrStat(ErrID_Fatal,'The modeling of partially flooded/ballested members requires that the first/bottom-most element of a member must be fully flooded. This is not true for MemberID '//trim(num2lstr(member%MemberID)),ErrStat,ErrMsg,'SetMemberProperties') - return - end if - ! Need to enforce the modeling requirement that a partially flooded member must not be close to horizontal - if ( (InitInp%Nodes(member%NodeIndx(N+1))%Position(3) - member%Rin(N+1)*sinPhi) < member%FillFSLoc ) then - call SetErrStat(ErrID_Fatal,'The modeling of partially flooded/ballested members requires the the member not be near horizontal. This is not true for MemberID '//trim(num2lstr(member%MemberID)),ErrStat,ErrMsg,'SetMemberProperties') - return - end if + else if ((member%memfloodstatus > 0) .and. (member%FillFSLoc > Za) .AND. (member%FillFSLoc < Zb)) then ! Partially flooded element member%floodstatus(i) = 2 - - ! length along axis from node i to fill level - member%h_fill = member%l_fill - (i-1)*dl - !Since this element is only partially flooded/ballasted, compute the Volume fraction which is filled - call TaperCalc( member%Rin(i), member%Rin(i)+member%h_fill*member%dRdl_in(i), member%h_fill, Vballast_l, h_c) - Vballast_u = 0.0 - member%Vballast = member%Vballast + Vballast_l + Vballast_u ! Note: Vballast_l will match calculations above - - - ! depth-adjusted force distribution constant - member%alpha_fb_star(i) = (1 - member%alpha_fb(i))*( Za - member%FillFSLoc )**3 / ( ( (1-member%alpha_fb(i))*(Za - member%FillFSLoc))**3 - member%alpha_fb(i)*(Zb - member%FillFSLoc)**3 ) - - ! force and moment magnitude constants - member%Cfl_fb(i) = TwoPi * member%dRdl_in(i) * member%FillDens * gravity * member%h_fill *( (li - member%l_fill)*member%Rin(i) + 0.5*((li - member%l_fill)*member%dRdl_in(i) + member%Rin(i))*member%h_fill + 1.0/3.0*member%dRdl_in(i)*member%h_fill**2 ) - member%Cfr_fb(i) = Pi * member%FillDens * gravity * member%h_fill *( member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)*member%h_fill +1.0/3.0 *member%dRdl_in(i)**2 *member%h_fill**2 ) - member%CM0_fb(i) = TwoPi * member%FillDens * gravity * member%h_fill *( 0.25*member%h_fill**3*member%dRdl_in(i)**4 + 0.25*member%h_fill**3*member%dRdl_in(i)**2 + member%h_fill**2*member%dRdl_in(i)**3*member%Rin(i) + 2.0/3.0*member%h_fill**2*member%dRdl_in(i)*member%Rin(i) & - + 1.5*member%h_fill*member%dRdl_in(i)**2*member%Rin(i)**2 + 0.5*member%h_fill*member%Rin(i)**2 + member%dRdl_in(i)*member%Rin(i)**3 ) & - -0.25 * member%FillDens * gravity * Pi * ( member%Rin(i) + member%h_fill*member%dRdl_in(i))**4 - - ! unflooded element - else + member%elem_fill = i + member%h_fill = member%l_fill - (i-1)*dl + call CylTaperCalc( member%Rin(i), member%Rin(i)+member%h_fill*member%dRdl_in(i), member%h_fill, Vballast_l, h_c) + member%Vballast = member%Vballast + Vballast_l ! Note: Vballast_l will match calculations above + + else ! Unflooded element + member%floodstatus(i) = 0 end if - - end do ! end looping through elements - - -end subroutine SetMemberProperties + end do ! end looping through elements -!---------------------------------------------------------------------------------------------------------------------------------- -subroutine SetupMembers( InitInp, p, m, errStat, errMsg ) +end subroutine SetMemberProperties_Cyl + +subroutine SetMemberProperties_Rec( gravity, member, MCoefMod, MmbrCoefIDIndx, MmbrFilledIDIndx, propSet1, propSet2, InitInp, errStat, errMsg ) + real(ReKi), intent (in ) :: gravity + type(Morison_MemberType), intent (inout) :: member + integer(IntKi), intent (in ) :: MCoefMod + integer(IntKi), intent (in ) :: MmbrCoefIDIndx + integer(IntKi), intent (in ) :: MmbrFilledIDIndx + type(Morison_MemberPropTypeRec), intent (in ) :: propSet1 ! property set of node 1 + type(Morison_MemberPropTypeRec), intent (in ) :: propSet2 ! property set of node N+1 + type(Morison_InitInputType), intent (in ) :: InitInp + integer(IntKi), intent ( out) :: errStat ! returns a non-zero value when an error occurs + character(*), intent ( out) :: errMsg ! Error message if errStat /= ErrID_None + + character(*), parameter :: RoutineName = 'SetMemberProperties_Rec' + + integer(IntKi) :: N, i + real(ReKi) :: s, dl + real(ReKi) :: vec(3) + real(ReKi) :: memLength + real(ReKi) :: Za + real(ReKi) :: Zb + real(ReKi) :: phi + real(ReKi) :: sinPhi + real(ReKi) :: cosPhi + real(ReKi) :: SaMid, SbMid + real(ReKi) :: SaMidMG, SbMidMG + real(ReKi) :: SaMidIn, SbMidIn + real(ReKi) :: Lmid + real(ReKi) :: li + real(ReKi) :: Vinner_l, Vinner_u, Vouter_l, Vouter_u, Vballast_l, Vballast_u + real(ReKi) :: tk(1,3), Imat(3,3), CMatrix(3,3) + REAL(ReKi) :: h_c ! center of mass offset from first node + + errStat = ErrID_None + errMSg = '' + + N = member%NElements + dl = member%dl + + vec = InitInp%Nodes(member%NodeIndx(N+1))%Position - InitInp%Nodes(member%NodeIndx(1))%Position + + ! calculate reference orientation information. Note: members are straight to start + memLength = member%RefLength + member%k(1:3) = (vec/memLength) ! vector along member from start to end point, length > 0 was already checked when the members were parsed and generated from the input file data + tk(1,1) = member%k(1) + tk(1,2) = member%k(2) + tk(1,3) = member%k(3) + member%kkt = matmul(transpose(tk),tk) + call Eye(Imat,errStat,errMsg) + member%Ak = Imat - member%kkt + IF (member%MSecGeom == MSecGeom_Rec) THEN + CALL Morison_DirCosMtrx( InitInp%Nodes(member%NodeIndx(1))%Position, InitInp%Nodes(member%NodeIndx(N+1))%Position, member%MSpinOrient, CMatrix ) + member%x_hat = CMatrix(1:3,1) + member%y_hat = CMatrix(1:3,2) + END IF + phi = acos( max(-1.0_ReKi, min(1.0_ReKi, vec(3)/memLength) ) ) ! incline angle + sinPhi = sin(phi) + cosPhi = cos(phi) + member%cosPhi_ref = cosPhi + + ! These are all per node and not done here, yet + + do i = 1, member%NElements+1 + call SetNodeMG( InitInp%NMGDepths, InitInp%MGDepths, InitInp%Nodes(member%NodeIndx(i)), InitInp%WaveField%MSL2SWL, member%tMG(i), member%MGDensity(i) ) + end do + + member%Sa( 1) = propSet1%PropA + member%SaMG(1) = propSet1%PropA + 2.0 * member%tMG(1) + member%Sain(1) = propSet1%PropA - 2.0 * propSet1%PropThck + member%Sb( 1) = propSet1%PropB + member%SbMG(1) = propSet1%PropB + 2.0 * member%tMG(1) + member%Sbin(1) = propSet1%PropB - 2.0 * propSet1%PropThck + member%Sa( N+1) = propSet2%PropA + member%SaMG(N+1) = propSet2%PropA + 2.0 * member%tMG(N+1) + member%Sain(N+1) = propSet2%PropA - 2.0 * propSet2%PropThck + member%Sb( N+1) = propSet2%PropB + member%SbMG(N+1) = propSet2%PropB + 2.0 * member%tMG(N+1) + member%Sbin(N+1) = propSet2%PropB - 2.0 * propSet2%PropThck + do i = 2, member%NElements + s = (real(i,ReKi)-1.0) / real(member%NElements,ReKi) + member%Sa( i) = member%Sa( 1)*(1-s) + member%Sa( N+1)*s + member%Sain(i) = member%Sain(1)*(1-s) + member%Sain(N+1)*s + member%SaMG(i) = member%Sa(i) + 2.0 * member%tMG(i) + member%Sb( i) = member%Sb( 1)*(1-s) + member%Sb( N+1)*s + member%Sbin(i) = member%Sbin(1)*(1-s) + member%Sbin(N+1)*s + member%SbMG(i) = member%Sb(i) + 2.0 * member%tMG(i) + end do + + call SetExternalHydroCoefs_Rec( InitInp%WaveField%MSL2SWL, MCoefMod, MmbrCoefIDIndx, InitInp%SimplRecCdA, InitInp%SimplRecCdAMG, InitInp%SimplRecCdB, InitInp%SimplRecCdBMG, & + InitInp%SimplRecCaA, InitInp%SimplRecCaAMG, InitInp%SimplRecCaB, InitInp%SimplRecCaBMG, InitInp%SimplRecCp, & + InitInp%SimplRecCpMG, InitInp%SimplRecAxCd, InitInp%SimplRecAxCdMG, InitInp%SimplRecAxCa, InitInp%SimplRecAxCaMG, InitInp%SimplRecAxCp, InitInp%SimplRecAxCpMG, & + InitInp%SimplRecCb, InitInp%SimplRecCbMG, InitInp%SimplRecMCF, & + InitInp%CoefMembersRec, InitInp%NCoefDpthRec, InitInp%CoefDpthsRec, InitInp%Nodes, member ) + + ! calculate member radius with marine growth scaled by sqrt(Cb) for buoyancy/hydrostatic load calculation + do i = 1, member%NElements+1 + member%SaMGB(i) = member%SaMG(i) * SQRT(member%Cb(i)) + member%SbMGB(i) = member%SbMG(i) * SQRT(member%Cb(i)) + end do + + ! calculate reference incline angle and heading, and related trig values. Note: members are straight to start + Za = InitInp%Nodes(member%NodeIndx(1 ))%Position(3) + Zb = InitInp%Nodes(member%NodeIndx(N+1))%Position(3) + + ! Check if members with the MacCamy-Fuchs diffraction model and not modeled by potential flow satisfy the necessary criteria. + IF ( member%PropMCF .AND. ( .NOT. member%PropPot )) THEN + CALL SetErrStat(ErrID_Fatal, 'MacCamy-Fuchs diffraction correction cannot be applied to rectangular members. Check member with ID '//trim(num2lstr(member%MemberID))//'. ', errStat, errMsg, RoutineName ) + END IF + + ! find fill location of member (previously in SetElementFillProps) + member%MmbrFilledIDIndx = MmbrFilledIDIndx ! Set this to the parameter version of this member data + if ( MmbrFilledIDIndx > 0 ) then + member%FillDens = InitInp%FilledGroups(MmbrFilledIDIndx)%FillDens + member%FillFSLoc = InitInp%FilledGroups(MmbrFilledIDIndx)%FillFSLoc - InitInp%WaveField%MSL2SWL + if (member%FillFSLoc >= Zb) then + member%z_overfill = member%FillFSLoc - Zb + member%l_fill = member%RefLength + member%memfloodstatus = 1 ! fully flooded + elseif (Za >= member%FillFSLoc) then + ! No ballast + member%memfloodstatus = 0 + member%z_overfill = 0.0_ReKi + member%l_fill = 0.0_ReKi + else + member%z_overfill =0 + if ( Zb <= -InitInp%WaveField%EffWtrDpth ) then + member%memfloodstatus = 0 ! member fully buried in seabed + member%l_fill = 0 + else + member%memfloodstatus = 2 ! partially flooded member + member%l_fill = (member%FillFSLoc - Za)/cosPhi + end if + + end if + + else + member%FillDens = 0.0 + member%FillFSLoc = 0.0 ! Future calculations for ballasting MUST verify that MbrFilledIDIndx > 0 for any ballasting calcs or this value will cause errors + member%z_overfill =0 + member%l_fill = 0 + member%memfloodstatus = 0 + end if + + ! Check the member does not exhibit any of the following conditions + if (.not. member%PropPot) then + ! MHstLMod=1 is not allowed for rectangular members at the moment. Skip the following check. + ! if (member%MHstLMod == 1) then + ! if ( abs(Zb) < abs(member%Rmg(N+1)*sinPhi) ) then + ! call SetErrStat(ErrID_Fatal, 'The upper end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) + ! end if + ! if ( abs(Za) < abs(member%Rmg(1)*sinPhi) ) then + ! call SetErrStat(ErrID_Fatal, 'The lower end-plate of a member must not cross the water plane. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) + ! end if + ! end if + if ( ( Za < -InitInp%WaveField%EffWtrDpth .and. Zb >= -InitInp%WaveField%EffWtrDpth ) .and. ( phi > 10.0*d2r .or. abs((member%SaMG(N+1) - member%SaMG(1))/member%RefLength)>0.1 .or. abs((member%SbMG(N+1) - member%SbMG(1))/member%RefLength)>0.1 ) ) then + call SetErrStat(ErrID_Fatal, 'A member which crosses the seabed must not be inclined more than 10 degrees from vertical or have a taper larger than 0.1. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) + end if + end if + + ! calculate h_floor if seabed-piercing + member%h_floor = 0.0_ReKi + member%i_floor = member%NElements+1 ! Default to entire member is below the seabed + member%doEndBuoyancy = .false. + if (Za < -InitInp%WaveField%EffWtrDpth) then + do i= 2, member%NElements+1 + Za = InitInp%Nodes(member%NodeIndx(i))%Position(3) + if (Za > -InitInp%WaveField%EffWtrDpth) then ! find the lowest node above the seabed + + if (cosPhi < 0.173648178 ) then ! phi > 80 degrees and member is seabed crossing + call SetErrStat(ErrID_Fatal, 'A seabed crossing member must have an inclination angle of <= 80 degrees from vertical. This is not true for Member ID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName ) + end if + + member%h_floor = (-InitInp%WaveField%EffWtrDpth-Za)/cosPhi ! get the distance from the node to the seabed along the member axis (negative value) + member%i_floor = i-1 ! record the number of the element that pierces the seabed + member%doEndBuoyancy = .true. + exit + else if ( EqualRealNos(Za, -InitInp%WaveField%EffWtrDpth ) ) then + member%doEndBuoyancy = .true. + end if + end do + else + member%i_floor = 0 ! lower end is at or above the seabed + end if + + ! calculate element-level values + do i = 1, member%NElements + member%dSadl_mg( i) = (member%SaMG( i+1) - member%SaMG( i))/dl + member%dSadl_in( i) = (member%Sain( i+1) - member%Sain( i))/dl + member%dSadl_mg_b(i) = (member%SaMGB(i+1) - member%SaMGB(i))/dl + + member%dSbdl_mg( i) = (member%SbMG( i+1) - member%SbMG( i))/dl + member%dSbdl_in( i) = (member%Sbin( i+1) - member%Sbin( i))/dl + member%dSbdl_mg_b(i) = (member%SbMGB(i+1) - member%SbMGB(i))/dl + + member%alpha( i) = GetAlphaRec(member%SaMGB(i), member%SaMGB(i+1), member%SbMGB(i), member%SbMGB(i+1)) ! Only used to distribute external buoyancy load to nodes + member%alpha_fb(i) = GetAlphaRec(member%Sain( i), member%Sain( i+1), member%Sbin( i), member%Sbin( i+1)) + + end do + + member%Vinner = 0.0_ReKi ! Total volume of member without marine growth + member%Vouter = 0.0_ReKi ! Total outer volume of member including marine growth + member%Vballast = 0.0_ReKi ! Total ballasted volume of member + member%elem_fill = 0 ! Last (partially) filled element of the member + member%h_fill = 0.0 ! Axial length of elem_fill occupied by water ballast + + ! force-related constants for each element + do i = 1, member%NElements + + Za = InitInp%Nodes(member%NodeIndx( i))%Position(3) ! z location of node i + Zb = InitInp%Nodes(member%NodeIndx(i+1))%Position(3) ! z location of node i+1 + + ! ------------------ marine growth weight and inertia ------------------------------------------------ + Vinner_l = 0.0 + Vouter_l = 0.0 + Vinner_u = 0.0 + Vouter_u = 0.0 + if (i > member%i_floor) then + ! full marine growth: get the properties for each half-element lumped to the appropriate node + + SaMid = 0.5*(member%Sa( i)+member%Sa( i+1)) ! length of Side A at middle of segment, where division occurs + SaMidMG = 0.5*(member%SaMG(i)+member%SaMG(i+1)) ! length of Side A with marine growth at middle of segment, where division occurs + SbMid = 0.5*(member%Sb( i)+member%Sb( i+1)) ! length of Side B at middle of segment, where division occurs + SbMidMG = 0.5*(member%SbMG(i)+member%SbMG(i+1)) ! length of Side B with marine growth at middle of segment, where division occurs + Lmid = 0.5*dl ! half-length of segment + + CALL MarineGrowthPartSegmentRec(member%Sa(i ), SaMid, member%Sb(i ), SbMid, member%SaMG(i ), SaMidMG, member%SbMG(i ), SbMidMG, Lmid, member%MGDensity(i), Vinner_l, Vouter_l, member%m_mg_l(i), member%h_cmg_l(i), member%I_lmg_l(i), member%I_xmg_l(i), member%I_ymg_l(i)) ! get precomputed quantities for lower half-segment + CALL MarineGrowthPartSegmentRec(member%Sa(i+1), SaMid, member%Sb(i+1), SbMid, member%SaMG(i+1), SaMidMG, member%SbMG(i+1), SbMidMG,-Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_xmg_u(i), member%I_ymg_u(i)) ! get precomputed quantities for upper half-segment + + else if (i == member%i_floor) then + ! crossing seabed: get the properties for part-element above the seabed and lump to the upper node + + SaMid = (-member%h_floor*member%Sa( i) +(dl+member%h_floor)*member%Sa( i+1))/dl + SaMidMG = (-member%h_floor*member%SaMG(i) +(dl+member%h_floor)*member%SaMG(i+1))/dl + SbMid = (-member%h_floor*member%Sb( i) +(dl+member%h_floor)*member%Sb( i+1))/dl + SbMidMG = (-member%h_floor*member%SbMG(i) +(dl+member%h_floor)*member%SbMG(i+1))/dl + Lmid = -member%h_floor + + CALL MarineGrowthPartSegmentRec(member%Sa(i+1), SaMid, member%Sb(i+1), SbMid, member%SaMG(i+1), SaMidMG, member%SbMG(i+1), SbMidMG,-Lmid, member%MGDensity(i), Vinner_u, Vouter_u, member%m_mg_u(i), member%h_cmg_u(i), member%I_lmg_u(i), member%I_xmg_u(i), member%I_ymg_u(i)) ! get precomputed quantities for upper half-segment + Vinner_l = 0.0 + Vouter_l = 0.0 + end if + + ! ------------------ flooded ballast inertia --------------------------------------------------------- + Vballast_l = 0.0 + Vballast_U = 0.0 + if (member%memfloodstatus > 0 .and. (member%FillFSLoc > Za)) then + ! Fully filled element, so split in middle + if ((i > member%i_floor) .and. (member%FillFSLoc >= Zb)) then + + ! get the properties for each half-element lumped to the appropriate node + SaMidIn = 0.5*(member%Sain(i)+member%Sain(i+1)) ! length of side A of member interior at middle of segment, where division occurs + SbMidIn = 0.5*(member%Sbin(i)+member%Sbin(i+1)) ! length of side B of member interior at middle of segment, where division occurs + Lmid = 0.5*dl ! half-length of segment + CALL FloodedBallastPartSegmentRec(member%Sain(i ), SaMidIn, member%Sbin(i ), SbMidIn, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_xfb_l(i), member%I_yfb_l(i)) ! get precomputed quantities for lower half-segment + CALL FloodedBallastPartSegmentRec(member%Sain(i+1), SaMidIn, member%Sbin(i+1), SbMidIn,-Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_xfb_u(i), member%I_yfb_u(i)) ! get precomputed quantities for upper half-segment + + ! partially filled element, so split at FillFSLoc + else if ((i > member%i_floor) .AND. (member%FillFSLoc < Zb)) then + + ! get the properties for each partial-element lumped to the appropriate node + Lmid = member%FillFSLoc - Za + SaMidIn = member%Sain(i)+(Lmid/(Zb-Za))*(member%Sain(i+1)-member%Sain(i)) ! length of side A of member interior at middle of segment, where division occurs + SbMidIn = member%Sbin(i)+(Lmid/(Zb-Za))*(member%Sbin(i+1)-member%Sbin(i)) ! length of side A of member interior at middle of segment, where division occurs + CALL FloodedBallastPartSegmentRec(member%Sain(i ), SaMidIn, member%Sbin(i ), SbMidIn, Lmid, member%FillDens, Vballast_l, member%m_fb_l(i), member%h_cfb_l(i), member%I_lfb_l(i), member%I_xfb_l(i), member%I_yfb_l(i)) ! get precomputed quantities for lower half-segment + CALL FloodedBallastPartSegmentRec(member%Sain(i+1), SaMidIn, member%Sbin(i+1), SbMidIn,-Lmid, 0.0_ReKi, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_xfb_u(i), member%I_yfb_u(i)) ! get precomputed quantities for upper half-segment + + else if (i == member%i_floor) then ! Hopefully we don't have a partially filled element crossing the seabed. + + ! crossing seabed: get the properties for part-element above the seabed and lump to the upper node + SaMidIn = (-member%h_floor*member%Sain(i) +(dl+member%h_floor)*member%Sain(i+1))/dl + SbMidIn = (-member%h_floor*member%Sbin(i) +(dl+member%h_floor)*member%Sbin(i+1))/dl + Lmid = -member%h_floor + CALL FloodedBallastPartSegmentRec(member%Sain(i+1), SaMidIn, member%Sbin(i+1), SbMidIn,-Lmid, member%FillDens, Vballast_u, member%m_fb_u(i), member%h_cfb_u(i), member%I_lfb_u(i), member%I_xfb_u(i), member%I_yfb_u(i)) ! get precomputed quantities for upper half-segment + Vballast_l = 0.0 + + end if + else ! Either no ballast flooding in member, or this particular element isn't flooded at all + Vballast_u = 0.0 + Vballast_l = 0.0 + member%m_fb_u(i) = 0.0 + member%h_cfb_u(i) = 0.0 + member%I_lfb_u(i) = 0.0 + member%I_xfb_u(i) = 0.0 + member%I_yfb_u(i) = 0.0 + endif + + ! Determine volumes to add to Non-WAMIT modeled members, etc. + if (.not. member%PropPot) then + + if (Zb < -InitInp%WaveField%EffWtrDpth) then + ! fully buried element, do not add these volume contributions to totals + else if (0.0 >= Zb) then ! Bug fix per OpenFAST issue #844 GJH 2/3/2022 + ! fully submerged elements. + ! NOTE: For an element which is fractionaly in the seabed, the entire element volume is added to totals + member%Vinner = member%Vinner + Vinner_l + Vinner_u + member%Vouter = member%Vouter + Vouter_l + Vouter_u + member%Vsubmerged = member%Vsubmerged + Vouter_l + Vouter_u + else if ((0.0 > Za) .AND. (0.0 < Zb)) then ! Bug fix per OpenFAST issue #844 GJH 2/3/2022 + ! if (i == 1) then + ! call SetErrStat(ErrID_Fatal, 'The lowest element of a member must not cross the free surface. This is true for MemberID '//trim(num2lstr(member%MemberID)), errStat, errMsg, RoutineName) + ! end if + + ! partially submerged element + member%Vinner = member%Vinner + Vinner_l + Vinner_u + member%Vouter = member%Vouter + Vouter_l + Vouter_u + ! compute volume portion which is submerged + Lmid = -Za/cosPhi + call RecTaperCalc( member%SaMG(i), member%SaMG(i)+Lmid*member%dSadl_mg(i), member%SbMG(i), member%SbMG(i)+Lmid*member%dSbdl_mg(i), Lmid, Vouter_l, h_c) + member%Vsubmerged = member%Vsubmerged + Vouter_l + + else ! fully above the water + member%Vinner = member%Vinner + Vinner_l + Vinner_u + member%Vouter = member%Vouter + Vouter_l + Vouter_u + end if + end if + + ! ------------------ flooded ballast weight (done) -------------------- + ! NOTE: this section of code is somewhat redundant with "flooded ballast inertia" section above + + li = dl*(i-1) + + if (Zb < -InitInp%WaveField%EffWtrDpth) then ! Fully buried element + + member%floodstatus(i) = 0 + + else if (member%memfloodstatus > 0 .and. member%FillFSLoc >= Zb) then ! Fully flooded elements + + member%floodstatus(i) = 1 + if ( EqualRealNos(member%FillFSLoc, Zb) .or. (i==member%NElements) ) then ! No partially filled elements + member%elem_fill = i + member%h_fill = dl + end if + member%Vballast = member%Vballast + Vballast_l + Vballast_u + + else if ((member%memfloodstatus > 0) .and. (member%FillFSLoc > Za) .AND. (member%FillFSLoc < Zb)) then ! Partially flooded element + + member%floodstatus(i) = 2 + member%elem_fill = i + member%h_fill = member%l_fill - (i-1)*dl + call RecTaperCalc( member%Sain(i), member%Sain(i)+member%h_fill*member%dSadl_in(i), member%Sbin(i), member%Sbin(i)+member%h_fill*member%dSbdl_in(i), member%h_fill, Vballast_l, h_c) + member%Vballast = member%Vballast + Vballast_l ! Note: Vballast_l will match calculations above + + else ! Unflooded element + + member%floodstatus(i) = 0 + + end if + + end do ! end looping through elements + +end subroutine SetMemberProperties_Rec + +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine SetupMembers( InitInp, p, m, errStat, errMsg ) type(Morison_InitInputType), intent (inout) :: InitInp type(Morison_ParameterType), intent (inout) :: p type(Morison_MiscVarType), intent (inout) :: m @@ -1842,13 +2627,14 @@ subroutine SetupMembers( InitInp, p, m, errStat, errMsg ) END IF do i = 1, p%NMembers - p%Members(i)%MemberID = InitInp%InpMembers(i)%MemberID - p%Members(i)%RefLength = InitInp%InpMembers(i)%RefLength - p%Members(i)%dl = InitInp%InpMembers(i)%dl - p%Members(i)%NElements = InitInp%InpMembers(i)%NElements - p%Members(i)%PropPot = InitInp%InpMembers(i)%PropPot - p%Members(i)%MHstLMod = InitInp%InpMembers(i)%MHstLMod - ! p%Members(i)%MCF = InitInp%InpMembers(i)%MCF + p%Members(i)%MemberID = InitInp%InpMembers(i)%MemberID + p%Members(i)%RefLength = InitInp%InpMembers(i)%RefLength + p%Members(i)%dl = InitInp%InpMembers(i)%dl + p%Members(i)%NElements = InitInp%InpMembers(i)%NElements + p%Members(i)%PropPot = InitInp%InpMembers(i)%PropPot + p%Members(i)%MHstLMod = InitInp%InpMembers(i)%MHstLMod + p%Members(i)%MSecGeom = InitInp%InpMembers(i)%MSecGeom + p%Members(i)%MSpinOrient = InitInp%InpMembers(i)%MSpinOrient call AllocateMemberDataArrays(p%Members(i), m%MemberLoads(i), errStat2, errMsg2) call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'SetupMembers') @@ -1866,7 +2652,11 @@ subroutine SetupMembers( InitInp, p, m, errStat, errMsg ) prop2Indx = InitInp%InpMembers(I)%MPropSetID2Indx end if ! Now populate the various member data arrays using the HydroDyn input file data - call SetMemberProperties( InitInp%Gravity, p%Members(i), InitInp%InpMembers(i)%MCoefMod, InitInp%InpMembers(i)%MmbrCoefIDIndx, InitInp%InpMembers(i)%MmbrFilledIDIndx, InitInp%MPropSets(prop1Indx), InitInp%MPropSets(prop2Indx), InitInp, errStat2, errMsg2 ) + if (p%Members(i)%MSecGeom == MSecGeom_Cyl) then + call SetMemberProperties_Cyl( InitInp%Gravity, p%Members(i), InitInp%InpMembers(i)%MCoefMod, InitInp%InpMembers(i)%MmbrCoefIDIndx, InitInp%InpMembers(i)%MmbrFilledIDIndx, InitInp%MPropSetsCyl(prop1Indx), InitInp%MPropSetsCyl(prop2Indx), InitInp, errStat2, errMsg2 ) + else if (p%Members(i)%MSecGeom == MSecGeom_Rec) then + call SetMemberProperties_Rec( InitInp%Gravity, p%Members(i), InitInp%InpMembers(i)%MCoefMod, InitInp%InpMembers(i)%MmbrCoefIDIndx, InitInp%InpMembers(i)%MmbrFilledIDIndx, InitInp%MPropSetsRec(prop1Indx), InitInp%MPropSetsRec(prop2Indx), InitInp, errStat2, errMsg2 ) + end if call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'SetupMembers') if (ErrStat >= AbortErrLev) return end do @@ -1903,7 +2693,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In character(*), parameter :: RoutineName = 'Morison_Init' TYPE(Morison_MemberType) :: member ! the current member - INTEGER :: i, j + INTEGER :: i, j, im REAL(ReKi) :: v2D(3,1), pos(3) real(ReKi) :: An(3), An_drag(3), Vn(3), I_n(3), sgn, Amag, Amag_drag, Vmag, Imag, Ir_MG_end, Il_MG_end, R_I(3,3), IRl_mat(3,3), tMG, MGdens integer(IntKi) :: MemberEndIndx @@ -1927,6 +2717,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In p%AMMod = InitInp%AMMod p%VisMeshes = InitInp%VisMeshes ! visualization mesh for morison elements p%PtfmYMod = InitInp%PtfmYMod + p%NFillGroups = InitInp%NFillGroups ! Pointer to SeaState WaveField p%WaveField => InitInp%WaveField @@ -2124,7 +2915,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In ! loop through each member attached to the joint, getting the radius of its appropriate end DO J = 1, InitInp%InpJoints(I)%NConnections - ! identify attached member and which end to us + ! identify attached member and which end to use IF (InitInp%InpJoints(I)%ConnectionList(J) > 0) THEN ! set up for end node 1 !TODO: Should not perform a copy here? A pointer to data would be better? member = p%Members(InitInp%InpJoints(I)%ConnectionList(J)) @@ -2142,32 +2933,44 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In IF ( MemberEndIndx == 1 ) THEN sgn = -1.0 ! Local coord sys points into member at starting node, so flip sign of local z vector ELSE - sgn = 1.0 ! Local coord sys points out of member at ending node, so leave sign of local z vector + sgn = 1.0 ! Local coord sys points out of member at ending node, so leave sign of local z vector END IF ! Account for reordering of what the original node for the end was -- This affects the sign of the An term which can pose a problem for members crossing the waterline if (member%Flipped) sgn = -1.0 * sgn - ! Compute the signed quantities for this member end (for drag regardless of PropPot value), and add them to the joint values - An_drag = An_drag + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**2 ! area-weighted normal vector - - ! For the following quantities, the attached member cannot be modeled using WAMIT if we're to count it - IF (.NOT. member%PropPot) THEN - - ! Compute the signed quantities for this member end, and add them to the joint values - An = An + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**2 ! area-weighted normal vector - Vn = Vn + sgn* member%k* (member%RMG(MemberEndIndx))**3 ! r^3-weighted normal vector used for mass - I_n=I_n + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**4 ! r^4-weighted normal vector used for moments of inertia - if (tMG == -999.0) then - ! All member nodes at this joint will have the same MG thickness and density, so only do this once - tMG = member%tMG(MemberEndIndx) - MGdens = member%MGdensity(MemberEndIndx) - end if + IF ( member%MSecGeom == MSecGeom_Cyl ) THEN + ! Compute the signed quantities for this member end (for drag regardless of PropPot value), and add them to the joint values + An_drag = An_drag + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**2 ! area-weighted normal vector + ! For the following quantities, the attached member cannot be modeled using WAMIT if we're to count it + IF (.NOT. member%PropPot) THEN + ! Compute the signed quantities for this member end, and add them to the joint values + An = An + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**2 ! area-weighted normal vector + Vn = Vn + sgn* member%k*TwoPi/3.0_ReKi*(member%RMG(MemberEndIndx))**3 ! r^3-weighted normal vector used for mass + I_n=I_n + sgn* member%k*Pi*(member%RMG(MemberEndIndx))**4 ! r^4-weighted normal vector used for moments of inertia + END IF + ELSE IF ( member%MSecGeom == MSecGeom_Rec ) THEN + ! Compute the signed quantities for this member end (for drag regardless of PropPot value), and add them to the joint values + An_drag = An_drag + sgn* member%k*(member%SaMG(MemberEndIndx) * member%SbMG(MemberEndIndx)) ! area-weighted normal vector + ! For the following quantities, the attached member cannot be modeled using WAMIT if we're to count it + IF (.NOT. member%PropPot) THEN + ! Compute the signed quantities for this member end, and add them to the joint values + An = An + sgn* member%k*(member%SaMG(MemberEndIndx) * member%SbMG(MemberEndIndx)) ! area-weighted normal vector + Vn = Vn + sgn* member%k*2.0_ReKi/3.0_ReKi*SQRT((member%SaMG(MemberEndIndx)*member%SbMG(MemberEndIndx)))**3/SQRT(Pi) ! volume-weighted normal vector used for mass + ! Don't have a good way to handle marine growth moment of inertia for rectangular endplates. Use an approximation for now, which should be reasonble for nearly square members + I_n=I_n + sgn* member%k* ( (member%SaMG(MemberEndIndx)**3 * member%SbMG(MemberEndIndx)) + (member%SaMG(MemberEndIndx) * member%SbMG(MemberEndIndx)**3) ) /6.0_ReKi + END IF + ELSE + call SetErrStat( ErrId_Fatal, " Unrecognized member cross section geometry ", errStat, errMsg, RoutineName ); return + END IF + + IF (tMG == -999.0) THEN + ! All member nodes at this joint will have the same MG thickness and density, so only do this once + tMG = member%tMG(MemberEndIndx) + MGdens = member%MGdensity(MemberEndIndx) END IF - - END DO !J = 1, InitInp%InpJoints(I)%NConnections - Vn = Vn*TwoPi/3.0_ReKi ! Semisphere volume is Vn = 2/3 pi \sum (r_MG^3 k) + END DO !J = 1, InitInp%InpJoints(I)%NConnections p%An_End(:,i) = An_drag Amag_drag = Dot_Product(An_drag ,An_drag) @@ -2194,8 +2997,8 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In endif ! marine growth mass/inertia magnitudes - p%Mass_MG_End(i) = MGdens * tMG * Amag - p%F_WMG_End(3,i) = -MGdens * tMG * Amag * InitInp%Gravity ! Z component of the directional force due to marine growth mass at joint + p%Mass_MG_End(i) = MGdens * tMG * Amag + p%F_WMG_End(3,i) = -MGdens * tMG * Amag * InitInp%Gravity ! Z component of the directional force due to marine growth mass at joint Ir_MG_end = 0.25 * MGdens * tMG * Imag ! radial moment of inertia magnitude Il_MG_end = 0.5 * MGdens * tMG * Imag ! axial moment of inertia magnitude @@ -2203,7 +3006,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In call RodrigMat(I_n, R_I, errStat, errMsg) IF ( errStat >= AbortErrLev ) RETURN - ! globally-oreinted moment of inertia matrix for joint + ! globally-oriented moment of inertia matrix for joint Irl_mat = 0.0 Irl_mat(1,1) = Ir_MG_end Irl_mat(2,2) = Ir_MG_end @@ -2225,6 +3028,35 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In END DO ! looping through nodes that are joints, i + ! Copy ballast group information to parameters + ALLOCATE ( p%FilledGroups(p%NFillGroups), STAT = ErrStat2 ) + IF ( ErrStat2 /= 0 ) THEN + call SetErrStat(ErrID_Fatal,'Error allocating space for FilledGroups array.',errStat,errMsg,RoutineName ); return + END IF + DO i=1,p%NFillGroups + CALL Morison_CopyFilledGroupType(InitInp%FilledGroups(i),p%FilledGroups(i),0,ErrStat2,ErrMsg2) + IF ( ErrStat2 /= 0 ) THEN + call SetErrStat(ErrID_Fatal,'Error copying FilledGroups array.',errStat,errMsg,RoutineName ); return + END IF + END DO + ! Determine if the filled group is open to the environment through the open end of members buried in the seabed + DO i = 1,p%NFillGroups + p%FilledGroups(i)%IsOpen = .false. + DO j = 1,p%FilledGroups(i)%FillNumM + im = p%FilledGroups(i)%FillMList(j) + IF ( p%Members(im)%i_floor > 0 ) THEN + p%FilledGroups(i)%IsOpen = .true. + IF ( p%FilledGroups(i)%FillFSLoc > p%WaveField%MSL2SWL ) THEN + call SetErrStat(ErrID_Fatal,' FillFSLoc cannot be higher than MSL2SWL if FillMList contains any member that is fully or partially buried in the seabed. ',errStat,errMsg,RoutineName ); return + END IF + IF ( .not. EqualRealNos( p%FilledGroups(i)%FillDens, p%WaveField%WtrDens) ) THEN + call SetErrStat(ErrID_Fatal,' FillDens must be the same as the external water density if FillMList contains any member that is fully or partially buried in the seabed. ',errStat,errMsg,RoutineName ); return + END IF + EXIT + END IF + END DO + END DO + ! Define initial guess for the system inputs here: ! u%DummyInput = 0 ! Define system output initializations (set up mesh) here: @@ -2407,19 +3239,38 @@ SUBROUTINE RodrigMat(a, R, errStat, errMsg) END SUBROUTINE RodrigMat !---------------------------------------------------------------------------------------------------------------------------------- -FUNCTION GetAlpha(R1,R2) +FUNCTION GetAlphaCyl(R1,R2) ! calculates relative center of volume location for a (tapered) cylindrical element - real(ReKi) :: GetAlpha + real(ReKi) :: GetAlphaCyl REAL(ReKi), INTENT ( IN ) :: R1 ! interior radius of element at node point REAL(ReKi), INTENT ( IN ) :: R2 ! interior radius of other end of part-element IF ( EqualRealNos(R1, R2) ) THEN ! Also cover the case where R1=R2=0 - GetAlpha = 0.5 + GetAlphaCyl = 0.5 + ELSE + GetAlphaCyl = (R1*R1 + 2.0*R1*R2 + 3.0*R2*R2)/4.0/(R1*R1 + R1*R2 + R2*R2) + END IF + +END FUNCTION GetAlphaCyl + +FUNCTION GetAlphaRec(a0,a1,b0,b1) + ! calculates relative center of volume location for a (tapered) rectangular element + real(ReKi) :: GetAlphaRec + REAL(ReKi), INTENT ( IN ) :: a0 ! Length of side A of element at node 1 + REAL(ReKi), INTENT ( IN ) :: a1 ! Length of side A of element at node 2 + REAL(ReKi), INTENT ( IN ) :: b0 ! Length of side B of element at node 1 + REAL(ReKi), INTENT ( IN ) :: b1 ! Length of side B of element at node 2 + + REAL(ReKi) :: tmp + tmp = 2.0*a0*b0+a0*b1+a1*b0+2.0*a1*b1 + + IF ( EqualRealNos(tmp, 0.0_ReKi) ) THEN ! zero volume + GetAlphaRec = 0.5 ELSE - GetAlpha = (R1*R1 + 2.0*R1*R2 + 3.0*R2*R2)/4.0/(R1*R1 + R1*R2 + R2*R2) + GetAlphaRec = 0.5 * (a0*b0+a0*b1+a1*b0+3.0*a1*b1) / tmp END IF -END FUNCTION GetAlpha +END FUNCTION GetAlphaRec !---------------------------------------------------------------------------------------------------------------------------------- SUBROUTINE AllocateNodeLoadVariables(InitInp, p, m, NNodes, errStat, errMsg ) @@ -2463,6 +3314,7 @@ SUBROUTINE AllocateNodeLoadVariables(InitInp, p, m, NNodes, errStat, errMsg ) call AllocAry( p%DP_Const_End , 3, p%NJoints, 'p%DP_Const_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%V_rel_n , p%NJoints, 'm%V_rel_n' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( m%V_rel_n_HiPass , p%NJoints, 'm%V_rel_n_HiPass', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) + call AllocAry( m%zFillGroup , p%NFillGroups, 'm%zFillGroup' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( p%DragMod_End , p%NJoints, 'p%DragMod_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( p%DragLoFSc_End , p%NJoints, 'p%DragLoFSc_End' , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) call AllocAry( p%VRelNFiltConst , p%NJoints, 'p%VRelNFiltConst', errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, routineName) @@ -2530,20 +3382,16 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, REAL(ReKi) :: tanPhi REAL(ReKi) :: sinBeta, sinBeta1, sinBeta2 REAL(ReKi) :: cosBeta, cosBeta1, cosBeta2 - REAL(ReKi) :: CMatrix(3,3), CTrans(3,3) ! Direction cosine matrix for element, and its transpose - REAL(ReKi) :: z1 - REAL(ReKi) :: z2 - REAL(ReKi) :: r1 - REAL(ReKi) :: r2 - REAL(ReKi) :: r1b - REAL(ReKi) :: r2b - REAL(ReKi) :: rMidb - REAL(ReKi) :: dRdl_mg ! shorthand for taper including marine growth of element i - REAL(ReKi) :: dRdl_mg_b ! shorthand for taper including marine growth of element i with radius scaling by sqrt(Cb) - REAL(ReKi) :: RMGFSInt ! Member radius with marine growth at the intersection with the instantaneous free surface + REAL(ReKi) :: CMatrix(3,3), CMatrix1(3,3), CMatrix2(3,3), CTrans(3,3) ! Direction cosine matrix for element, and its transpose + REAL(ReKi) :: l, z1, z2, zMid, r1, r2, r1b, r2b, r1In, r2In, rMidIn, rn, rn1, rn2, z_hi, zFillGroup + REAL(ReKi) :: Sa1, Sa2, Sa1b, Sa2b, SaMidb, Sa1In, Sa2In, SaMidIn + REAL(ReKi) :: Sb1, Sb2, Sb1b, Sb2b, SbMidb, Sb1In, Sb2In, SbMidIn + REAL(ReKi) :: dRdl_mg, dSadl_mg, dSbdl_mg ! shorthand for taper including marine growth of element i + REAL(ReKi) :: dRdl_mg_b, dSadl_mg_b, dSbdl_mg_b ! shorthand for taper including marine growth of element i with radius scaling by sqrt(Cb) + REAL(ReKi) :: RMGFSInt, SaMGFSInt, SbMGFSInt ! Member radius with marine growth at the intersection with the instantaneous free surface REAL(ReKi) :: g ! gravity constant REAL(ReKi) :: k_hat(3), k_hat1(3), k_hat2(3) ! Elemental unit vector pointing from 1st node to 2nd node of the element - REAL(ReKi) :: n_hat(3) + REAL(ReKi) :: n_hat(3) ! Free surface unit normal vector pointing from water to air REAL(ReKi) :: Fr !radial component of buoyant force REAL(ReKi) :: Fl !axial component of buoyant force REAL(ReKi) :: Moment !moment induced about the center of the cylinder's bottom face @@ -2556,7 +3404,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, REAL(ReKi) :: omega_s2(3) REAL(ReKi) :: pos1(3), pos2(3) REAL(ReKi) :: Imat(3,3) - REAL(ReKi) :: iArm(3), iTerm(3), Ioffset, h_c, dRdl_p, dRdl_pp, f_hydro(3), Am(3,3), lstar, deltal, deltalLeft, deltalRight + REAL(ReKi) :: iArm(3), iTerm(3), h_c, dRdl_p, dRdl_pp, dSadl_p, dSadl_pp, dSbdl_p, dSbdl_pp, f_hydro(3), Am(3,3), lstar, deltal, deltalLeft, deltalRight REAL(ReKi) :: h, h_c_AM, deltal_AM REAL(ReKi) :: F_WMG(6), F_IMG(6), F_If(6), F_B0(6), F_B1(6), F_B2(6), F_B_End(6) REAL(ReKi) :: AM_End(3,3), An_End(3), DP_Const_End(3), I_MG_End(3,3) @@ -2581,28 +3429,29 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, REAL(ReKi) :: Df_hydro_lumped(6) REAL(ReKi) :: FVFSInt(3) REAL(ReKi) :: FAFSInt(3) + REAL(ReKi) :: SAFSInt(3) REAL(ReKi) :: FDynPFSInt REAL(ReKi) :: vrelFSInt(3) REAL(ReKi) :: FAMCFFSInt(3) INTEGER(IntKi) :: MemSubStat, NumFSX REAL(DbKi) :: theta1, theta2 - REAL(ReKi) :: y_hat(3), z_hat(3), posMid(3), zetaMid, FSPt(3) + REAL(ReKi) :: x_hat(3), x_hat1(3), x_hat2(3), y_hat(3), y_hat1(3), y_hat2(3), z_hat(3), posMid(3), zetaMid, FSPt(3) INTEGER(IntKi) :: secStat INTEGER(IntKi) :: nodeInWater REAL(SiKi) :: WaveElev1, WaveElev2, WaveElev, FDynP, FV(3), FA(3), FAMCF(3) - LOGICAL :: Is1stElement + LOGICAL :: Is1stElement, Is1stFloodedMember ! Initialize errStat - errStat = ErrID_None - errMsg = "" - Imat = 0.0_ReKi + errStat = ErrID_None + errMsg = "" + Imat = 0.0_ReKi g = p%Gravity !=============================================================================================== ! Get displaced positions of the hydrodynamic nodes CALL GetDisplacedNodePosition( .FALSE., m%DispNodePosHdn ) ! For hydrodynamic loads; depends on WaveDisp and WaveStMod CALL GetDisplacedNodePosition( .TRUE. , m%DispNodePosHst ) ! For hydrostatic loads; always use actual displaced position - + !=============================================================================================== ! Calculate the fluid kinematics at all mesh nodes and store for use in the equations below CALL WaveField_GetWaveKin( p%WaveField, m%WaveField_m, Time, m%DispNodePosHdn, .FALSE., m%nodeInWater, m%WaveElev1, m%WaveElev2, m%WaveElev, m%FDynP, m%FV, m%FA, m%FAMCF, ErrStat2, ErrMsg2 ) @@ -2612,6 +3461,29 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, m%vrel(:,j) = ( m%FV(:,j) - u%Mesh%TranslationVel(:,j) ) * m%nodeInWater(j) END DO + !=============================================================================================== + ! Get the instantaneous highest point of internal ballast for each filled group + ! This is the elevation with zero internal hydrostatic pressure + DO i = 1,p%NFillGroups + IF ( p%FilledGroups(i)%IsOpen ) THEN + m%zFillGroup(i) = 0.0 ! SWL because ballast group open to the environment follows the external hydrostatic pressure field + ELSE + Is1stFloodedMember = .true. + DO j = 1,p%FilledGroups(i)%FillNumM + im = p%FilledGroups(i)%FillMList(j) + IF (p%Members(im)%memfloodstatus>0) THEN + CALL getMemBallastHiPt(p%Members(im),z_hi,ErrStat2,ErrMsg2); if (Failed()) return + IF ( Is1stFloodedMember ) THEN + m%zFillGroup(i) = z_hi + Is1stFloodedMember = .false. + ELSE + m%zFillGroup(i) = MAX(m%zFillGroup(i), z_hi) + END IF + END IF + END DO + END IF + END DO + ! ============================================================================================== ! Calculate instantaneous loads on each member except for the hydrodynamic loads on member ends. ! This covers aspects of the load calculations previously in CreateDistributedMesh. @@ -2680,26 +3552,46 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, call GetOrientationAngles( pos1, pos2, phi, sinPhi, cosPhi, tanPhi, sinBeta, cosBeta, k_hat, errStat2, errMsg2 ) call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - call Morison_DirCosMtrx( pos1, pos2, CMatrix ) + ! Compute element to global DirCos matrix for undisplaced structure first + call Morison_DirCosMtrx( u%Mesh%Position(:,mem%NodeIndx(i )), u%Mesh%Position(:,mem%NodeIndx(i+1)), mem%MSpinOrient, CMatrix ) + ! Prepend body motion - Assuming the rotation of the starting node is representative of the whole element + CMatrix = matmul(transpose(u%Mesh%Orientation(:,:,mem%NodeIndx(i))),CMatrix) CTrans = transpose(CMatrix) + ! Note: CMatrix is element local to global displaced. CTrans is the opposite. ! save some commonly used variables dl = mem%dl z1 = pos1(3) ! get node z locations from input mesh z2 = pos2(3) - r1 = mem%RMG(i ) ! outer radius at element nodes including marine growth - r2 = mem%RMG(i+1) - r1b = mem%RMGB(i ) ! outer radius at element nodes including marine growth scaled by sqrt(Cb) - r2b = mem%RMGB(i+1) - dRdl_mg = mem%dRdl_mg(i) ! Taper of element including marine growth - dRdl_mg_b = mem%dRdl_mg_b(i) ! Taper of element including marine growth with radius scaling by sqrt(Cb) a_s1 = u%Mesh%TranslationAcc(:, mem%NodeIndx(i )) alpha_s1 = u%Mesh%RotationAcc (:, mem%NodeIndx(i )) omega_s1 = u%Mesh%RotationVel (:, mem%NodeIndx(i )) a_s2 = u%Mesh%TranslationAcc(:, mem%NodeIndx(i+1)) alpha_s2 = u%Mesh%RotationAcc (:, mem%NodeIndx(i+1)) omega_s2 = u%Mesh%RotationVel (:, mem%NodeIndx(i+1)) - + IF (mem%MSecGeom == MSecGeom_Cyl) THEN + r1 = mem%RMG(i ) ! outer radius at element nodes including marine growth + r2 = mem%RMG(i+1) + r1b = mem%RMGB(i ) ! outer radius at element nodes including marine growth scaled by sqrt(Cb) + r2b = mem%RMGB(i+1) + dRdl_mg = mem%dRdl_mg(i) ! Taper of element including marine growth + dRdl_mg_b = mem%dRdl_mg_b(i) ! Taper of element including marine growth with radius scaling by sqrt(Cb) + ELSE IF (mem%MSecGeom == MSecGeom_Rec) THEN + Sa1 = mem%SaMG(i ) ! outer side A at element nodes including marine growth + Sa2 = mem%SaMG(i+1) + Sb1 = mem%SbMG(i ) ! outer side B at element nodes including marine growth + Sb2 = mem%SbMG(i+1) + Sa1b = mem%SaMGB(i ) ! outer side A at element nodes including marine growth scaled by sqrt(Cb) + Sa2b = mem%SaMGB(i+1) + Sb1b = mem%SbMGB(i ) ! outer side B at element nodes including marine growth scaled by sqrt(Cb) + Sb2b = mem%SbMGB(i+1) + dSadl_mg = mem%dSadl_mg(i) ! Taper of element side A including marine growth + dSadl_mg_b = mem%dSadl_mg_b(i) ! Taper of element side A including marine growth with radius scaling by sqrt(Cb) + dSbdl_mg = mem%dSbdl_mg(i) ! Taper of element side B including marine growth + dSbdl_mg_b = mem%dSbdl_mg_b(i) ! Taper of element side B including marine growth with radius scaling by sqrt(Cb) + END IF + ! ------------------ marine growth: Sides: Section 4.1.2 -------------------- + ! ----- marine growth weight F_WMG = 0.0_ReKi ! lower node @@ -2718,33 +3610,42 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_WMG(1:3) y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_WMG(4:6) + ! ----- marine growth inertial load ! lower node - Ioffset = mem%h_cmg_l(i)*mem%h_cmg_l(i)*mem%m_mg_l(i) Imat = 0.0_ReKi - Imat(1,1) = mem%I_rmg_l(i) - Ioffset - Imat(2,2) = mem%I_rmg_l(i) - Ioffset + IF (mem%MSecGeom == MSecGeom_Cyl) THEN + Imat(1,1) = mem%I_rmg_l(i) + Imat(2,2) = mem%I_rmg_l(i) + ELSE IF (mem%MSecGeom == MSecGeom_Rec) THEN + Imat(1,1) = mem%I_xmg_l(i) + Imat(2,2) = mem%I_ymg_l(i) + END IF Imat(3,3) = mem%I_lmg_l(i) Imat = matmul(matmul(CMatrix, Imat), CTrans) iArm = mem%h_cmg_l(i) * k_hat iTerm = ( -a_s1 - cross_product(omega_s1, cross_product(omega_s1,iArm )) - cross_product(alpha_s1,iArm) ) * mem%m_mg_l(i) F_IMG(1:3) = iTerm - F_IMG(4:6) = - cross_product(a_s1 * mem%m_mg_l(i), mem%h_cmg_l(i) * k_hat) + matmul(Imat, alpha_s1) & + F_IMG(4:6) = - matmul(Imat, alpha_s1) - cross_product(iArm,a_s1 * mem%m_mg_l(i)) & - cross_product(omega_s1,matmul(Imat,omega_s1)) m%memberLoads(im)%F_IMG(:,i) = m%memberLoads(im)%F_IMG(:,i) + F_IMG y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + F_IMG(1:3) y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + F_IMG(4:6) - + ! upper node - Ioffset = mem%h_cmg_u(i)*mem%h_cmg_u(i)*mem%m_mg_u(i) Imat = 0.0_ReKi - Imat(1,1) = mem%I_rmg_u(i) - Ioffset - Imat(2,2) = mem%I_rmg_u(i) - Ioffset + IF (mem%MSecGeom == MSecGeom_Cyl) THEN + Imat(1,1) = mem%I_rmg_u(i) + Imat(2,2) = mem%I_rmg_u(i) + ELSE IF (mem%MSecGeom == MSecGeom_Rec) THEN + Imat(1,1) = mem%I_xmg_u(i) + Imat(2,2) = mem%I_ymg_u(i) + END IF Imat(3,3) = mem%I_lmg_u(i) Imat = matmul(matmul(CMatrix, Imat), CTrans) iArm = mem%h_cmg_u(i) * k_hat iTerm = ( -a_s2 - cross_product(omega_s2, cross_product(omega_s2,iArm )) - cross_product(alpha_s2,iArm) ) * mem%m_mg_u(i) F_IMG(1:3) = iTerm - F_IMG(4:6) = - cross_product(a_s2 * mem%m_mg_u(i), mem%h_cmg_u(i) * k_hat) + matmul(Imat, alpha_s2) & + F_IMG(4:6) = - matmul(Imat, alpha_s2) - cross_product(iArm,a_s2 * mem%m_mg_u(i)) & - cross_product(omega_s2,matmul(Imat,omega_s2)) m%memberLoads(im)%F_IMG(:,i+1) = m%memberLoads(im)%F_IMG(:,i+1) + F_IMG y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_IMG(1:3) @@ -2778,20 +3679,32 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ELSE IF (mem%MHstLMod == 2) THEN ! Alternative hydrostatic load calculation ! Get free surface elevation and normal at the element midpoint (both assumed constant over the element) posMid = 0.5 * (pos1+pos2) - rMidb = 0.5 * (r1b +r2b ) + ! rn is only used to estimate free surface normal numerically + IF (mem%MSecGeom == MSecGeom_Cyl) THEN + rn = 0.5 * (r1b +r2b ) + ELSE IF (mem%MSecGeom == MSecGeom_Rec) THEN + rn = MAX( 0.5*(Sa1b+Sa2b), 0.5*(Sb1b+Sb2b) ) + END IF IF (p%WaveField%WaveStMod > 0) THEN CALL GetTotalWaveElev( Time, posMid, ZetaMid, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL GetFreeSurfaceNormal( Time, posMid, rMidb, n_hat, ErrStat2, ErrMsg2 ) + CALL GetFreeSurfaceNormal( Time, posMid, rn, n_hat, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) FSPt = (/posMid(1),posMid(2),ZetaMid/) ! Reference point on the free surface ELSE FSPt = (/posMid(1),posMid(2),0.0_ReKi/) n_hat = (/0.0,0.0,1.0/) - END IF - CALL GetSectionUnitVectors( k_hat, y_hat, z_hat ) - CALL getElementHstLds_Mod2( pos1, pos2, FSPt, k_hat, y_hat, z_hat, n_hat, r1b, r2b, dl, F_B1, F_B2, ErrStat2, ErrMsg2) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + END IF + + IF (mem%MSecGeom == MSecGeom_Cyl) THEN + CALL GetSectionUnitVectors_Cyl( k_hat, y_hat, z_hat ) + CALL getElementHstLds_Mod2_Cyl( pos1, pos2, FSPt, k_hat, y_hat, z_hat, n_hat, r1b, r2b, dl, F_B1, F_B2, ErrStat2, ErrMsg2) + ELSE IF (mem%MSecGeom == MSecGeom_Rec) THEN + CALL GetSectionUnitVectors_Rec( CMatrix, x_hat, y_hat ) + CALL getElementHstLds_Mod2_Rec( pos1, pos2, FSPt, k_hat, x_hat, y_hat, n_hat, Sa1b, Sa2b, Sb1b, Sb2b, dl, F_B1, F_B2, ErrStat2, ErrMsg2) + END IF + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! Add nodal loads to mesh m%memberLoads(im)%F_B(:,i ) = m%memberLoads(im)%F_B(:,i ) + F_B1 m%memberLoads(im)%F_B(:,i+1) = m%memberLoads(im)%F_B(:,i+1) + F_B2 @@ -2804,121 +3717,146 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, END IF ! NOT Modeled with Potential flow theory ! --------------------------- flooded ballast: sides: Always compute regardless of PropPot setting ------------------------------ - DO i = max(mem%i_floor,1), N ! loop through member elements that are not completely buried in the seabed - - ! calculate instantaneous incline angle and heading, and related trig values - ! the first and last NodeIndx values point to the corresponding Joint nodes indices which are at the start of the Mesh - pos1 = m%DispNodePosHst(:,mem%NodeIndx(i )) - pos2 = m%DispNodePosHst(:,mem%NodeIndx(i+1)) + ! NOTE: For memfloodstatus and floodstatus: 0 = fully buried or not ballasted, 1 = fully flooded, 2 = partially flooded + IF ( mem%memfloodstatus > 0 ) THEN ! Fully or partially flooded member + zFillGroup = m%zFillGroup(mem%MmbrFilledIDIndx) + DO i = max(mem%i_floor,1), N ! loop through member elements that are not completely buried in the seabed + IF (mem%floodstatus(i)>0) THEN + ! calculate instantaneous incline angle and heading, and related trig values + ! the first and last NodeIndx values point to the corresponding Joint nodes indices which are at the start of the Mesh + pos1 = m%DispNodePosHst(:,mem%NodeIndx(i )) + pos2 = m%DispNodePosHst(:,mem%NodeIndx(i+1)) + + call GetOrientationAngles( pos1, pos2, phi, sinPhi, cosPhi, tanPhi, sinBeta, cosBeta, k_hat, errStat2, errMsg2 ); if (Failed()) return + ! Compute element to global DirCos matrix for undisplaced structure first + call Morison_DirCosMtrx( u%Mesh%Position(:,mem%NodeIndx(i )), u%Mesh%Position(:,mem%NodeIndx(i+1)), mem%MSpinOrient, CMatrix ) + ! Prepend body motion - Assuming the rotation of the starting node is representative of the whole element + CMatrix = matmul(transpose(u%Mesh%Orientation(:,:,mem%NodeIndx(i))),CMatrix) + CTrans = transpose(CMatrix) + ! Note: CMatrix is element local to global displaced. CTrans is the opposite. + ! save some commonly used variables + dl = mem%dl + z1 = pos1(3) ! get displaced node z locations + z2 = pos2(3) + a_s1 = u%Mesh%TranslationAcc(:, mem%NodeIndx(i )) + alpha_s1 = u%Mesh%RotationAcc (:, mem%NodeIndx(i )) + omega_s1 = u%Mesh%RotationVel (:, mem%NodeIndx(i )) + a_s2 = u%Mesh%TranslationAcc(:, mem%NodeIndx(i+1)) + alpha_s2 = u%Mesh%RotationAcc (:, mem%NodeIndx(i+1)) + omega_s2 = u%Mesh%RotationVel (:, mem%NodeIndx(i+1)) + IF (mem%MSecGeom == MSecGeom_Cyl) THEN + r1In = mem%Rin(i ) ! outer radius at element nodes including marine growth + r2In = mem%Rin(i+1) + IF ( mem%floodstatus(i) == 1 ) THEN ! Fully flooded element + zMid = 0.5 * (z1 + z2 ) + rMidIn = 0.5 * (r1In + r2In) + ELSE ! Partially flooded element + zMid = z1 + mem%h_fill * k_hat(3) + l = mem%h_fill/mem%dl + rMidIn = r1In * (1.0-l) + r2In * l + END IF + ELSE IF (mem%MSecGeom == MSecGeom_Rec) THEN + Sa1In = mem%Sain(i ) ! outer side A at element nodes including marine growth + Sa2In = mem%Sain(i+1) + Sb1In = mem%Sbin(i ) ! outer side B at element nodes including marine growth + Sb2In = mem%Sbin(i+1) + IF ( mem%floodstatus(i) == 1 ) THEN ! Fully flooded element + zMid = 0.5 * (z1 + z2 ) + SaMidIn = 0.5 * (Sa1In + Sa2In) + SbMidIn = 0.5 * (Sb1In + Sb2In) + ELSE ! Partially flooded element + zMid = z1 + mem%h_fill * k_hat(3) + l = mem%h_fill/mem%dl + SaMidIn = Sa1In * (1.0-l) + Sa2In * l + SbMidIn = Sb1In * (1.0-l) + Sb2In * l + END IF + END IF - call GetOrientationAngles( pos1, pos2, phi, sinPhi, cosPhi, tanPhi, sinBeta, cosBeta, k_hat, errStat2, errMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - call Morison_DirCosMtrx( pos1, pos2, CMatrix ) - CTrans = transpose(CMatrix) - ! save some commonly used variables - dl = mem%dl - z1 = pos1(3) ! get node z locations from input mesh - z2 = pos2(3) - r1 = mem%RMG(i ) ! outer radius at element nodes including marine growth - r2 = mem%RMG(i+1) - r1b = mem%RMGB(i ) ! outer radius at element nodes including marine growth scaled by sqrt(Cb) - r2b = mem%RMGB(i+1) - dRdl_mg = mem%dRdl_mg(i) ! Taper of element including marine growth - dRdl_mg_b = mem%dRdl_mg_b(i) ! Taper of element including marine growth with radius scaling by sqrt(Cb) - a_s1 = u%Mesh%TranslationAcc(:, mem%NodeIndx(i )) - alpha_s1 = u%Mesh%RotationAcc (:, mem%NodeIndx(i )) - omega_s1 = u%Mesh%RotationVel (:, mem%NodeIndx(i )) - a_s2 = u%Mesh%TranslationAcc(:, mem%NodeIndx(i+1)) - alpha_s2 = u%Mesh%RotationAcc (:, mem%NodeIndx(i+1)) - omega_s2 = u%Mesh%RotationVel (:, mem%NodeIndx(i+1)) - - ! ------------------ flooded ballast inertia: sides: Section 6.1.1 : Always compute regardless of PropPot setting --------------------- - ! lower node - Ioffset = mem%h_cfb_l(i)*mem%h_cfb_l(i)*mem%m_fb_l(i) - Imat = 0.0_ReKi - Imat(1,1) = mem%I_rfb_l(i) - Ioffset - Imat(2,2) = mem%I_rfb_l(i) - Ioffset - Imat(3,3) = mem%I_lfb_l(i) - Imat = matmul(matmul(CMatrix, Imat), CTrans) - iArm = mem%h_cfb_l(i) * k_hat - iTerm = ( -a_s1 - cross_product(omega_s1, cross_product(omega_s1,iArm )) - cross_product(alpha_s1,iArm) ) * mem%m_fb_l(i) - F_If(1:3) = iTerm - F_If(4:6) = - cross_product(a_s1 * mem%m_fb_l(i), mem%h_cfb_l(i) * k_hat) + matmul(Imat, alpha_s1) & - - cross_product(omega_s1,matmul(Imat,omega_s1)) - m%memberLoads(im)%F_If(:,i) = m%memberLoads(im)%F_If(:,i) + F_If - y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + F_If(1:3) - y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + F_If(4:6) - - ! upper node - Ioffset = mem%h_cfb_u(i)*mem%h_cfb_u(i)*mem%m_fb_u(i) - Imat = 0.0_ReKi - Imat(1,1) = mem%I_rfb_u(i) - Ioffset - Imat(2,2) = mem%I_rfb_u(i) - Ioffset - Imat(3,3) = mem%I_lfb_u(i) - Imat = matmul(matmul(CMatrix, Imat), CTrans) - iArm = mem%h_cfb_u(i) * k_hat - iTerm = ( -a_s2 - cross_product(omega_s2, cross_product(omega_s2,iArm )) - cross_product(alpha_s2,iArm) ) * mem%m_fb_u(i) - F_If(1:3) = iTerm - F_If(4:6) = - cross_product(a_s2 * mem%m_fb_u(i), mem%h_cfb_u(i) * k_hat) + matmul(Imat, alpha_s2) & - - cross_product(omega_s2,matmul(Imat,omega_s2)) - m%memberLoads(im)%F_If(:,i+1) = m%memberLoads(im)%F_If(:,i+1) + F_If - y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_If(1:3) - y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_If(4:6) - - ! ------------------ flooded ballast weight : sides : Section 5.1.2 & 5.2.2 : Always compute regardless of PropPot setting --------------------- - - ! NOTE: For memfloodstatus and floodstatus: 0 = fully buried or not ballasted, 1 = fully flooded, 2 = partially flooded - - ! fully filled elements - if (mem%floodstatus(i) == 1) then - - ! Compute lstar - if ( mem%memfloodstatus == 2) then - ! partially flooded MEMBER - lstar = dl*(i-1) - mem%l_fill - elseif (cosPhi >= 0.0 ) then - lstar = dl*(i-N-1) - else - lstar = dl*(i-1) - end if - Fl =TwoPi * mem%dRdl_in(i) * mem%FillDens * p%gravity * dl *( -( mem%Rin(i) + 0.5* mem%dRdl_in(i)*dl )*mem%z_overfill + & - ( lstar*mem%Rin(i) + 0.5*(lstar*mem%dRdl_in(i) + mem%Rin(i) )*dl + mem%dRdl_in(i)*dl**2/3.0 )*cosphi ) + ! ------------------ flooded ballast inertia: sides: Section 6.1.1 : Always compute regardless of PropPot setting --------------------- + ! lower node + Imat = 0.0_ReKi + IF (mem%MSecGeom == MSecGeom_Cyl) THEN + Imat(1,1) = mem%I_rfb_l(i) + Imat(2,2) = mem%I_rfb_l(i) + ELSE IF (mem%MSecGeom == MSecGeom_Rec) THEN + Imat(1,1) = mem%I_xfb_l(i) + Imat(2,2) = mem%I_yfb_l(i) + END IF + Imat(3,3) = mem%I_lfb_l(i) + Imat = matmul(matmul(CMatrix, Imat), CTrans) + iArm = mem%h_cfb_l(i) * k_hat + iTerm = ( -a_s1 - cross_product(omega_s1, cross_product(omega_s1,iArm )) - cross_product(alpha_s1,iArm) ) * mem%m_fb_l(i) + F_If(1:3) = iTerm + F_If(4:6) = - matmul(Imat, alpha_s1) - cross_product(iArm,a_s1 * mem%m_fb_l(i)) & + - cross_product(omega_s1,matmul(Imat,omega_s1)) + m%memberLoads(im)%F_If(:,i) = m%memberLoads(im)%F_If(:,i) + F_If + y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + F_If(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + F_If(4:6) + + ! upper node + Imat = 0.0_ReKi + IF (mem%MSecGeom == MSecGeom_Cyl) THEN + Imat(1,1) = mem%I_rfb_u(i) + Imat(2,2) = mem%I_rfb_u(i) + ELSE IF (mem%MSecGeom == MSecGeom_Rec) THEN + Imat(1,1) = mem%I_xfb_u(i) + Imat(2,2) = mem%I_yfb_u(i) + END IF + Imat(3,3) = mem%I_lfb_u(i) + Imat = matmul(matmul(CMatrix, Imat), CTrans) + iArm = mem%h_cfb_u(i) * k_hat + iTerm = ( -a_s2 - cross_product(omega_s2, cross_product(omega_s2,iArm )) - cross_product(alpha_s2,iArm) ) * mem%m_fb_u(i) + F_If(1:3) = iTerm + F_If(4:6) = - matmul(Imat, alpha_s2) - cross_product(iArm,a_s2 * mem%m_fb_u(i)) & + - cross_product(omega_s2,matmul(Imat,omega_s2)) + m%memberLoads(im)%F_If(:,i+1) = m%memberLoads(im)%F_If(:,i+1) + F_If + y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_If(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_If(4:6) + + ! ------------------ flooded ballast weight : sides : Section 5.1.2 & 5.2.2 : Always compute regardless of PropPot setting --------------------- + F_B1 = 0.0 + F_B2 = 0.0 + IF (mem%MSecGeom == MSecGeom_Cyl) THEN + F_B1(3) = - p%gravity * mem%m_fb_l(i) + F_B1(1:3) = F_B1(1:3) + mem%FillDens * p%gravity * pi * ( rMidIn*rMidIn*(zMid-zFillGroup) - r1In*r1In*(z1-zFillGroup) ) * k_hat + F_B1(4:6) = -( p%gravity * mem%m_fb_l(i) * mem%h_cfb_l(i) + mem%FillDens * p%gravity * 0.25*pi*(rMidIn**4-r1In**4) ) * Cross_Product(k_hat,(/0.0,0.0,1.0/)) + IF ( mem%FloodStatus(i) == 1 ) THEN + F_B2(3) = - p%gravity * mem%m_fb_u(i) + F_B2(1:3) = F_B2(1:3) + mem%FillDens * p%gravity * pi * ( r2In*r2In*(z2-zFillGroup) - rMidIn*rMidIn*(zMid-zFillGroup) ) * k_hat + F_B2(4:6) = -( p%gravity * mem%m_fb_u(i) * mem%h_cfb_u(i) + mem%FillDens * p%gravity * 0.25*pi*(r2In**4-rMidIn**4) ) * Cross_Product(k_hat,(/0.0,0.0,1.0/)) + ELSE IF ( i == mem%elem_fill ) THEN ! Need to include end load here + F_B1(1:3) = F_B1(1:3) + mem%FillDens * p%gravity * pi * rMidIn**2* (zFillGroup - zMid) * k_hat + F_B1(4:6) = F_B1(4:6) + mem%FillDens * p%gravity * 0.25 * pi * rMidIn**4* Cross_Product(k_hat,(/0.0,0.0,1.0/)) + END IF + ELSE IF (mem%MSecGeom == MSecGeom_Rec) THEN + CALL GetSectionUnitVectors_Rec( CMatrix, x_hat, y_hat ) + F_B1(3) = - p%gravity * mem%m_fb_l(i) + F_B1(1:3) = F_B1(1:3) + mem%FillDens * p%gravity * ( SaMidIn*SbMidIn*(zMid-zFillGroup) - Sa1In*Sb1In*(z1-zFillGroup) ) * k_hat + F_B1(4:6) = - p%gravity * mem%m_fb_l(i) * mem%h_cfb_l(i) * Cross_Product(k_hat,(/0.0,0.0,1.0/)) & + + mem%FillDens * p%gravity / 12.0 * ( (Sa1In**3*Sb1In*x_hat(3)*y_hat - Sa1In*Sb1In**3*y_hat(3)*x_hat ) - & + (SaMidIn**3*SbMidIn*x_hat(3)*y_hat - SaMidIn*SbMidIn**3*y_hat(3)*x_hat ) ) + IF ( mem%FloodStatus(i) == 1 ) THEN + F_B2(3) = - p%gravity * mem%m_fb_u(i) + F_B2(1:3) = F_B2(1:3) + mem%FillDens * p%gravity * ( Sa2In*Sb2In*(z2-zFillGroup) - SaMidIn*SbMidIn*(zMid-zFillGroup) ) * k_hat + F_B2(4:6) = - p%gravity * mem%m_fb_u(i) * mem%h_cfb_u(i) * Cross_Product(k_hat,(/0.0,0.0,1.0/)) & + + mem%FillDens * p%gravity / 12.0 * ( (SaMidIn**3*SbMidIn*x_hat(3)*y_hat - SaMidIn*SbMidIn**3*y_hat(3)*x_hat ) - & + (Sa2In**3*Sb2In*x_hat(3)*y_hat - Sa2In*Sb2In**3*y_hat(3)*x_hat ) ) + ELSE IF ( i == mem%elem_fill ) THEN ! Need to include end load here + F_B1(1:3) = F_B1(1:3) + mem%FillDens * p%gravity * SaMidIn*SbMidIn*(zFillGroup-zMid) * k_hat + F_B1(4:6) = F_B1(4:6) + mem%FillDens * p%gravity / 12.0 * (SaMidIn**3*SbMidIn*x_hat(3)*y_hat - SaMidIn*SbMidIn**3*y_hat(3)*x_hat) + END IF + END IF - ! forces and moment in tilted coordinates about node i - Fr = mem%Cfr_fb(i)*sinPhi - Moment = mem%CM0_fb(i)*sinPhi - Fr*mem%alpha_fb_star(i)*dl - - ! calculate full vector and distribute to nodes - call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, (1-mem%alpha_fb_star(i)), F_B1, F_B2) - m%memberLoads(im)%F_BF(:, i) = m%memberLoads(im)%F_BF(:, i) + F_B2 ! 1-alpha - m%memberLoads(im)%F_BF(:, i+1) = m%memberLoads(im)%F_BF(:, i+1) + F_B1 ! alpha - y%Mesh%Force (:,mem%NodeIndx(i )) = y%Mesh%Force (:,mem%NodeIndx(i )) + F_B2(1:3) - y%Mesh%Moment(:,mem%NodeIndx(i )) = y%Mesh%Moment(:,mem%NodeIndx(i )) + F_B2(4:6) - y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_B1(1:3) - y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_B1(4:6) - - ! partially filled element - else if (mem%floodstatus(i) == 2) then - - ! forces and moment in tilted coordinates about node i - Fl = mem%Cfl_fb(i)*cosPhi - Fr = mem%Cfr_fb(i)*sinPhi - Moment = mem%CM0_fb(i)*sinPhi + Fr*(1 - mem%alpha_fb_star(i))*dl - - ! calculate full vector and distribute to nodes - call DistributeElementLoads(Fl, Fr, Moment, sinPhi, cosPhi, sinBeta, cosBeta, mem%alpha_fb_star(i), F_B1, F_B2) - m%memberLoads(im)%F_BF(:, i) = m%memberLoads(im)%F_BF(:, i) + F_B1 ! alpha - m%memberLoads(im)%F_BF(:, i-1) = m%memberLoads(im)%F_BF(:, i-1) + F_B2 ! 1- alpha - y%Mesh%Force (:,mem%NodeIndx(i )) = y%Mesh%Force (:,mem%NodeIndx(i )) + F_B1(1:3) - y%Mesh%Moment(:,mem%NodeIndx(i )) = y%Mesh%Moment(:,mem%NodeIndx(i )) + F_B1(4:6) - y%Mesh%Force (:,mem%NodeIndx(i-1)) = y%Mesh%Force (:,mem%NodeIndx(i-1)) + F_B2(1:3) - y%Mesh%Moment(:,mem%NodeIndx(i-1)) = y%Mesh%Moment(:,mem%NodeIndx(i-1)) + F_B2(4:6) - - ! no load for unflooded element or element fully below seabed - - end if - - END DO ! i = max(mem%i_floor,1), N ! loop through member elements that are not fully buried in the seabed + m%memberLoads(im)%F_BF(:, i ) = m%memberLoads(im)%F_BF(:, i ) + F_B1 + m%memberLoads(im)%F_BF(:, i+1) = m%memberLoads(im)%F_BF(:, i+1) + F_B2 + y%Mesh%Force (:,mem%NodeIndx(i )) = y%Mesh%Force (:,mem%NodeIndx(i )) + F_B1(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i )) = y%Mesh%Moment(:,mem%NodeIndx(i )) + F_B1(4:6) + y%Mesh%Force (:,mem%NodeIndx(i+1)) = y%Mesh%Force (:,mem%NodeIndx(i+1)) + F_B2(1:3) + y%Mesh%Moment(:,mem%NodeIndx(i+1)) = y%Mesh%Moment(:,mem%NodeIndx(i+1)) + F_B2(4:6) + + END IF ! mem%floodstatus(i) > 0 + END DO ! i = max(mem%i_floor,1), N ! loop through member elements that are not fully buried in the seabed + END IF ! Fully or partially flooded member !-----------------------------------------------------------------------------------------------------! ! External Hydrodynamic Side Loads - Start ! @@ -2937,7 +3875,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! Get positions of node i and i+1 pos1 = m%DispNodePosHdn(:,mem%NodeIndx(i )) pos2 = m%DispNodePosHdn(:,mem%NodeIndx(i+1)) - + ! Free surface elevation above or below node i and i+1 Zeta1 = m%WaveElev(mem%NodeIndx(i)) Zeta2 = m%WaveElev(mem%NodeIndx(i+1)) @@ -2965,22 +3903,49 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, FSInt = SubRatio * (pos2-pos1) + pos1 END IF - ! Compute the slope of member radius - IF (i == 1) THEN - dRdl_p = abs(mem%dRdl_mg(i)) - dRdl_pp = mem%dRdl_mg(i) - ELSE IF ( i > 1 .AND. i < (N+1)) THEN - dRdl_p = 0.5*( abs(mem%dRdl_mg(i-1)) + abs(mem%dRdl_mg(i)) ) - dRdl_pp = 0.5*( mem%dRdl_mg(i-1) + mem%dRdl_mg(i) ) - ELSE - dRdl_p = abs(mem%dRdl_mg(N)) - dRdl_pp = mem%dRdl_mg(N) + ! Compute the slope of member radius/side length + IF (mem%MSecGeom==MSecGeom_Cyl) THEN + IF (i == 1) THEN + dRdl_p = abs(mem%dRdl_mg(i)) + dRdl_pp = mem%dRdl_mg(i) + ELSE IF ( i > 1 .AND. i < (N+1)) THEN + dRdl_p = 0.5*( abs(mem%dRdl_mg(i-1)) + abs(mem%dRdl_mg(i)) ) + dRdl_pp = 0.5*( mem%dRdl_mg(i-1) + mem%dRdl_mg(i) ) + ELSE + dRdl_p = abs(mem%dRdl_mg(N)) + dRdl_pp = mem%dRdl_mg(N) + END IF + ELSE IF (mem%MSecGeom==MSecGeom_Rec) THEN + IF (i == 1) THEN + dSadl_p = abs(mem%dSadl_mg(i)) + dSadl_pp = mem%dSadl_mg(i) + dSbdl_p = abs(mem%dSbdl_mg(i)) + dSbdl_pp = mem%dSbdl_mg(i) + ELSE IF ( i > 1 .AND. i < (N+1)) THEN + dSadl_p = 0.5*( abs(mem%dSadl_mg(i-1)) + abs(mem%dSadl_mg(i)) ) + dSadl_pp = 0.5*( mem%dSadl_mg(i-1) + mem%dSadl_mg(i) ) + dSbdl_p = 0.5*( abs(mem%dSbdl_mg(i-1)) + abs(mem%dSbdl_mg(i)) ) + dSbdl_pp = 0.5*( mem%dSbdl_mg(i-1) + mem%dSbdl_mg(i) ) + ELSE + dSadl_p = abs(mem%dSadl_mg(N)) + dSadl_pp = mem%dSadl_mg(N) + dSbdl_p = abs(mem%dSbdl_mg(N)) + dSbdl_pp = mem%dSbdl_mg(N) + END IF END IF - + !-------------------- hydrodynamic drag loads: sides: Section 7.1.2 ------------------------! vec = matmul( mem%Ak,m%vrel(:,mem%NodeIndx(i)) ) - f_hydro = mem%Cd(i)*p%WaveField%WtrDens*mem%RMG(i)*TwoNorm(vec)*vec + & - 0.5*mem%AxCd(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*dRdl_p * abs(dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )) * matmul( mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) + IF (mem%MSecGeom==MSecGeom_Cyl) THEN + f_hydro = mem%Cd(i)*p%WaveField%WtrDens*mem%RMG(i)*TwoNorm(vec)*vec + & ! radial part + 0.5*mem%AxCd(i)*p%WaveField%WtrDens * pi*mem%RMG(i)*dRdl_p * & ! axial part + abs(dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )) * matmul( mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) ! axial part cont'd + ELSE IF (mem%MSecGeom==MSecGeom_Rec) THEN + f_hydro = 0.5*mem%CdB(i)*p%WaveField%WtrDens*mem%SbMG(i)*TwoNorm(vec)*Dot_Product(vec,mem%x_hat)*mem%x_hat + & ! local x-direction + 0.5*mem%CdA(i)*p%WaveField%WtrDens*mem%SaMG(i)*TwoNorm(vec)*Dot_Product(vec,mem%y_hat)*mem%y_hat + & ! local z-direction + 0.25*mem%AxCd(i)*p%WaveField%WtrDens * (dSadl_p*mem%SbMG(i) + dSbdl_p*mem%SaMG(i)) * & ! axial part + abs(dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )) * matmul( mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) ! axial part cont'd + END IF CALL LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%memberLoads(im)%F_D(:, i) ) y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_D(1:3, i) y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_D(4:6, i) @@ -2990,9 +3955,14 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, IF ( .NOT. mem%PropPot ) THEN !-------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------! - Am = mem%Ca(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*mem%Ak + 2.0*mem%AxCa(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p*mem%kkt - f_hydro = -matmul( Am, u%Mesh%TranslationAcc(:,mem%NodeIndx(i)) ) - + IF (mem%MSecGeom==MSecGeom_Cyl) THEN + Am = mem%Ca(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*mem%Ak + 2.0*mem%AxCa(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p*mem%kkt + f_hydro = -matmul( Am, u%Mesh%TranslationAcc(:,mem%NodeIndx(i)) ) + ELSE IF (mem%MSecGeom==MSecGeom_Rec) THEN + f_hydro = -p%WaveField%WtrDens*mem%CaB(i) * 0.25*pi*mem%SbMG(i)*mem%SbMG(i) * Dot_Product(u%Mesh%TranslationAcc(:,mem%NodeIndx(i)),mem%x_hat)*mem%x_hat & + -p%WaveField%WtrDens*mem%CaA(i) * 0.25*pi*mem%SaMG(i)*mem%SaMG(i) * Dot_Product(u%Mesh%TranslationAcc(:,mem%NodeIndx(i)),mem%y_hat)*mem%y_hat & + -0.5*p%WaveField%WtrDens*mem%AxCa(i) * (dSbdl_p*mem%SaMG(i)+dSadl_p*mem%SbMG(i))*SQRT(mem%SaMG(i)*mem%SbMG(i)) * Dot_Product(u%Mesh%TranslationAcc(:,mem%NodeIndx(i)),mem%k)*mem%k + END IF IF ( p%AMMod .EQ. 0_IntKi ) THEN ! Compute added-mass force up to the SWL z1 = u%Mesh%Position(3, mem%NodeIndx(i)) - p%WaveField%MSL2SWL ! Undisplaced z-position of the current node IF ( z1 > 0.0_ReKi ) THEN ! Node is above SWL undisplaced; zero added-mass force @@ -3023,16 +3993,25 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_A(4:6, i) !--------------------- hydrodynamic inertia loads: sides: Section 7.1.4 --------------------------! - IF (mem%PropMCF) THEN - f_hydro= p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FAMCF(:,mem%NodeIndx(i)) ) + & - 2.0*mem%AxCa(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & - 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k - ELSE - f_hydro=(mem%Ca(i)+mem%Cp(i))*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & - 2.0*mem%AxCa(i) *p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & - 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k + IF (mem%MSecGeom==MSecGeom_Cyl) THEN + IF (mem%PropMCF) THEN + f_hydro= p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FAMCF(:,mem%NodeIndx(i)) ) + & + 2.0*mem%AxCa(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k + ELSE + f_hydro=(mem%Ca(i)+mem%Cp(i))*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*mem%AxCa(i) *p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k + END IF + ELSE IF (mem%MSecGeom==MSecGeom_Rec) THEN + ! Note: MacCamy-Fuchs correction cannot be applied to rectangular members + f_hydro= mem%Cp(i)*p%WaveField%WtrDens* mem%SaMG(i)*mem%SbMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & ! transver FK component + m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)* (mem%SaMG(i)*dSbdl_pp+dSadl_pp*mem%SbMG(i)) *mem%k + & ! axial FK component + p%WaveField%WtrDens*mem%CaB(i) * 0.25*pi*mem%SbMG(i)*mem%SbMG(i) * Dot_Product(m%FA(:,mem%NodeIndx(i)),mem%x_hat)*mem%x_hat + & ! x-component of diffraction part + p%WaveField%WtrDens*mem%CaA(i) * 0.25*pi*mem%SaMG(i)*mem%SaMG(i) * Dot_Product(m%FA(:,mem%NodeIndx(i)),mem%y_hat)*mem%y_hat + & ! y-component of diffraction part + 0.5*p%WaveField%WtrDens*mem%AxCa(i) * (dSbdl_p*mem%SaMG(i)+dSadl_p*mem%SbMG(i))*SQRT(mem%SaMG(i)*mem%SbMG(i)) * & ! axial component of diffraction part + Dot_Product(m%FA(:,mem%NodeIndx(i)),mem%k)*mem%k ! axial component of diffraction part cont'd END IF - CALL LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%memberLoads(im)%F_I(:, i) ) y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_I(1:3, i) y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_I(4:6, i) @@ -3055,6 +4034,9 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, IF ( mem%PropMCF .AND. ( .NOT. mem%PropPot ) ) THEN FAMCFFSInt = REAL(FAMCF,ReKi) END IF + ! Structure translational acceleration at the free surface intersection + SAFSInt = SubRatio * u%Mesh%TranslationAcc(:,mem%NodeIndx(FSElem+1)) + & + (1.0-SubRatio) * u%Mesh%TranslationAcc(:,mem%NodeIndx(FSElem )) ! Viscous drag: ! Compute relative velocity at the free surface intersection. @@ -3063,38 +4045,74 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, SubRatio * u%Mesh%TranslationVel(:,mem%NodeIndx(FSElem+1)) + & (1.0-SubRatio) * u%Mesh%TranslationVel(:,mem%NodeIndx(FSElem )) & ) - dRdl_p = abs(mem%dRdl_mg(FSElem)) - RMGFSInt = SubRatio * mem%RMG(FSElem+1) + (1.0-SubRatio) * mem%RMG(FSElem) - vec = matmul( mem%Ak,vrelFSInt ) - F_DS = mem%Cd(FSElem)*p%WaveField%WtrDens*RMGFSInt*TwoNorm(vec)*vec + & - 0.5*mem%AxCd(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*dRdl_p * & - abs(dot_product( mem%k, vrelFSInt )) * matmul( mem%kkt, vrelFSInt ) + IF (mem%MSecGeom==MSecGeom_Cyl) THEN + dRdl_p = abs(mem%dRdl_mg(FSElem)) + dRdl_pp = mem%dRdl_mg(FSElem) + RMGFSInt = SubRatio * mem%RMG(FSElem+1) + (1.0-SubRatio) * mem%RMG(FSElem) - ! Hydrodynamic added mass and inertia loads - IF ( .NOT. mem%PropPot ) THEN - - ! ------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------ - IF (p%AMMod > 0_IntKi) THEN - Am = mem%Ca(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt*mem%Ak + & - 2.0*mem%AxCa(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt*dRdl_p*mem%kkt - F_AS = -matmul( Am, & - SubRatio * u%Mesh%TranslationAcc(:,mem%NodeIndx(FSElem+1)) + & - (1.0-SubRatio) * u%Mesh%TranslationAcc(:,mem%NodeIndx(FSElem )) ) + vec = matmul( mem%Ak,vrelFSInt ) + F_DS = mem%Cd(FSElem)*p%WaveField%WtrDens*RMGFSInt*TwoNorm(vec)*vec + & + 0.5*mem%AxCd(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*dRdl_p * & + abs(dot_product( mem%k, vrelFSInt )) * matmul( mem%kkt, vrelFSInt ) + + ! Hydrodynamic added mass and inertia loads + IF ( .NOT. mem%PropPot ) THEN + + ! ------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------ + IF (p%AMMod > 0_IntKi) THEN + Am = mem%Ca(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt*mem%Ak + & + 2.0*mem%AxCa(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt*dRdl_p*mem%kkt + F_AS = -matmul( Am, & + SubRatio * u%Mesh%TranslationAcc(:,mem%NodeIndx(FSElem+1)) + & + (1.0-SubRatio) * u%Mesh%TranslationAcc(:,mem%NodeIndx(FSElem )) ) + END IF + + ! ------------------- hydrodynamic inertia loads: sides: Section 7.1.4 ------------------------ + IF ( mem%PropMCF) THEN + F_IS= p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt * matmul( mem%Ak, FAMCFFSInt ) + & + 2.0*mem%AxCa(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt*dRdl_p * matmul( mem%kkt, FAFSInt ) + & + 2.0*mem%AxCp(FSElem) *pi*RMGFSInt *dRdl_pp * FDynPFSInt*mem%k + ELSE + F_IS=(mem%Ca(FSElem)+mem%Cp(FSElem))*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt * matmul( mem%Ak, FAFSInt ) + & + 2.0*mem%AxCa(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt*dRdl_p * matmul( mem%kkt, FAFSInt ) + & + 2.0*mem%AxCp(FSElem) *pi*RMGFSInt *dRdl_pp * FDynPFSInt*mem%k + END IF END IF + ELSE IF (mem%MSecGeom==MSecGeom_Rec) THEN + dSadl_p = abs(mem%dSadl_mg(FSElem)) + dSadl_pp = mem%dSadl_mg(FSElem) + dSbdl_p = abs(mem%dSbdl_mg(FSElem)) + dSbdl_pp = mem%dSbdl_mg(FSElem) + SaMGFSInt = SubRatio * mem%SaMG(FSElem+1) + (1.0-SubRatio) * mem%SaMG(FSElem) + SbMGFSInt = SubRatio * mem%SbMG(FSElem+1) + (1.0-SubRatio) * mem%SbMG(FSElem) + + vec = matmul( mem%Ak,vrelFSInt ) + F_DS = 0.5*mem%CdB(FSElem)*p%WaveField%WtrDens*SbMGFSInt*TwoNorm(vec)*Dot_Product(vec,mem%x_hat)*mem%x_hat + & ! local x-direction + 0.5*mem%CdA(FSElem)*p%WaveField%WtrDens*SaMGFSInt*TwoNorm(vec)*Dot_Product(vec,mem%y_hat)*mem%y_hat + & ! local z-direction + 0.25*mem%AxCd(FSElem)*p%WaveField%WtrDens * (dSadl_p*SbMGFSInt + dSbdl_p*SaMGFSInt) * & ! axial part + abs(dot_product( mem%k, vrelFSInt )) * matmul( mem%kkt, vrelFSInt ) ! axial part cont'd + + ! Hydrodynamic added mass and inertia loads + IF ( .NOT. mem%PropPot ) THEN + + ! ------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------ + IF (p%AMMod > 0_IntKi) THEN + F_AS = -p%WaveField%WtrDens*mem%CaB(FSElem) * 0.25*pi*SbMGFSInt*SbMGFSInt * Dot_Product(SAFSInt,mem%x_hat)*mem%x_hat & + -p%WaveField%WtrDens*mem%CaA(FSElem) * 0.25*pi*SaMGFSInt*SaMGFSInt * Dot_Product(SAFSInt,mem%y_hat)*mem%y_hat & + -0.5*p%WaveField%WtrDens*mem%AxCa(FSElem) * (dSbdl_p*SaMGFSInt+dSadl_p*SbMGFSInt)*SQRT(SaMGFSInt*SbMGFSInt) * Dot_Product(SAFSInt,mem%k)*mem%k + END IF - ! ------------------- hydrodynamic inertia loads: sides: Section 7.1.4 ------------------------ - IF ( mem%PropMCF) THEN - F_IS= p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt * matmul( mem%Ak, FAMCFFSInt ) + & - 2.0*mem%AxCa(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt*dRdl_p * matmul( mem%kkt, FAFSInt ) + & - 2.0*mem%AxCp(FSElem) *pi*RMGFSInt *dRdl_pp * FDynPFSInt*mem%k - ELSE - F_IS=(mem%Ca(FSElem)+mem%Cp(FSElem))*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt * matmul( mem%Ak, FAFSInt ) + & - 2.0*mem%AxCa(FSElem)*p%WaveField%WtrDens*pi*RMGFSInt*RMGFSInt*dRdl_p * matmul( mem%kkt, FAFSInt ) + & - 2.0*mem%AxCp(FSElem) *pi*RMGFSInt *dRdl_pp * FDynPFSInt*mem%k + ! ------------------- hydrodynamic inertia loads: sides: Section 7.1.4 ------------------------ + F_IS= mem%Cp(FSElem)*p%WaveField%WtrDens* SaMGFSInt*SbMGFSInt * matmul( mem%Ak, FAFSInt ) + & ! transver FK component + FDynPFSInt*mem%AxCp(FSElem)* (SaMGFSInt*dSbdl_pp+dSadl_pp*SbMGFSInt) *mem%k + & ! axial FK component + p%WaveField%WtrDens*mem%CaB(FSElem) * 0.25*pi*SbMGFSInt*SbMGFSInt * Dot_Product(FAFSInt,mem%x_hat)*mem%x_hat + & ! x-component of diffraction part + p%WaveField%WtrDens*mem%CaA(FSElem) * 0.25*pi*SaMGFSInt*SaMGFSInt * Dot_Product(FAFSInt,mem%y_hat)*mem%y_hat + & ! y-component of diffraction part + 0.5*p%WaveField%WtrDens*mem%AxCa(FSElem) * (dSbdl_p*SaMGFSInt+dSadl_p*SbMGFSInt)*SQRT(SaMGFSInt*SbMGFSInt) * & ! axial component of diffraction part + Dot_Product(FAFSInt,mem%k)*mem%k ! axial component of diffraction part cont'd + END IF END IF - !----------------------------------------------------------------------------------------------------! ! Perform the load redistribution for smooth time series ! !----------------------------------------------------------------------------------------------------! @@ -3245,30 +4263,63 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, h_c = 0.5_ReKi * ( deltalRight - deltalLeft ) END IF - ! Compute the slope of the member radius - IF (i == 1) THEN - dRdl_p = abs(mem%dRdl_mg(i)) - dRdl_pp = mem%dRdl_mg(i) - ELSE IF ( i > 1 .AND. i < (N+1)) THEN - dRdl_p = 0.5*( abs(mem%dRdl_mg(i-1)) + abs(mem%dRdl_mg(i)) ) - dRdl_pp = 0.5*( mem%dRdl_mg(i-1) + mem%dRdl_mg(i) ) - ELSE - dRdl_p = abs(mem%dRdl_mg(N)) - dRdl_pp = mem%dRdl_mg(N) + ! Compute the slope of member radius/side length + IF (mem%MSecGeom==MSecGeom_Cyl) THEN + IF (i == 1) THEN + dRdl_p = abs(mem%dRdl_mg(i)) + dRdl_pp = mem%dRdl_mg(i) + ELSE IF ( i > 1 .AND. i < (N+1)) THEN + dRdl_p = 0.5*( abs(mem%dRdl_mg(i-1)) + abs(mem%dRdl_mg(i)) ) + dRdl_pp = 0.5*( mem%dRdl_mg(i-1) + mem%dRdl_mg(i) ) + ELSE + dRdl_p = abs(mem%dRdl_mg(N)) + dRdl_pp = mem%dRdl_mg(N) + END IF + ELSE IF (mem%MSecGeom==MSecGeom_Rec) THEN + IF (i == 1) THEN + dSadl_p = abs(mem%dSadl_mg(i)) + dSadl_pp = mem%dSadl_mg(i) + dSbdl_p = abs(mem%dSbdl_mg(i)) + dSbdl_pp = mem%dSbdl_mg(i) + ELSE IF ( i > 1 .AND. i < (N+1)) THEN + dSadl_p = 0.5*( abs(mem%dSadl_mg(i-1)) + abs(mem%dSadl_mg(i)) ) + dSadl_pp = 0.5*( mem%dSadl_mg(i-1) + mem%dSadl_mg(i) ) + dSbdl_p = 0.5*( abs(mem%dSbdl_mg(i-1)) + abs(mem%dSbdl_mg(i)) ) + dSbdl_pp = 0.5*( mem%dSbdl_mg(i-1) + mem%dSbdl_mg(i) ) + ELSE + dSadl_p = abs(mem%dSadl_mg(N)) + dSadl_pp = mem%dSadl_mg(N) + dSbdl_p = abs(mem%dSbdl_mg(N)) + dSbdl_pp = mem%dSbdl_mg(N) + END IF END IF !--------------------- hydrodynamic drag loads: sides: Section 7.1.2 --------------------------------! vec = matmul( mem%Ak,m%vrel(:,mem%NodeIndx(i)) ) - f_hydro = mem%Cd(i)*p%WaveField%WtrDens*mem%RMG(i)*TwoNorm(vec)*vec + & - 0.5*mem%AxCd(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*dRdl_p * abs(dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )) * matmul( mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) + IF (mem%MSecGeom==MSecGeom_Cyl) THEN + f_hydro = mem%Cd(i)*p%WaveField%WtrDens*mem%RMG(i)*TwoNorm(vec)*vec + & ! radial part + 0.5*mem%AxCd(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*dRdl_p * & ! axial part + abs(dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )) * matmul( mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) ! axial part cont'd + ELSE IF (mem%MSecGeom==MSecGeom_Rec) THEN + f_hydro = 0.5*mem%CdB(i)*p%WaveField%WtrDens*mem%SbMG(i)*TwoNorm(vec)*Dot_Product(vec,mem%x_hat)*mem%x_hat + & ! local x-direction + 0.5*mem%CdA(i)*p%WaveField%WtrDens*mem%SaMG(i)*TwoNorm(vec)*Dot_Product(vec,mem%y_hat)*mem%y_hat + & ! local z-direction + 0.25*mem%AxCd(i)*p%WaveField%WtrDens * (dSadl_p*mem%SbMG(i) + dSbdl_p*mem%SaMG(i)) * & ! axial part + abs(dot_product( mem%k, m%vrel(:,mem%NodeIndx(i)) )) * matmul( mem%kkt, m%vrel(:,mem%NodeIndx(i)) ) ! axial part cont'd + END IF CALL LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%memberLoads(im)%F_D(:, i) ) y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_D(1:3, i) y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_D(4:6, i) IF ( .NOT. mem%PropPot ) THEN !-------------------- hydrodynamic added mass loads: sides: Section 7.1.3 ------------------------! - Am = mem%Ca(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*mem%Ak + 2.0*mem%AxCa(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p*mem%kkt - f_hydro = -matmul( Am, u%Mesh%TranslationAcc(:,mem%NodeIndx(i)) ) + IF (mem%MSecGeom==MSecGeom_Cyl) THEN + Am = mem%Ca(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*mem%Ak + 2.0*mem%AxCa(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p*mem%kkt + f_hydro = -matmul( Am, u%Mesh%TranslationAcc(:,mem%NodeIndx(i)) ) + ELSE IF (mem%MSecGeom==MSecGeom_Rec) THEN + f_hydro = -p%WaveField%WtrDens*mem%CaB(i) * 0.25*pi*mem%SbMG(i)*mem%SbMG(i) * Dot_Product(u%Mesh%TranslationAcc(:,mem%NodeIndx(i)),mem%x_hat)*mem%x_hat & + -p%WaveField%WtrDens*mem%CaA(i) * 0.25*pi*mem%SaMG(i)*mem%SaMG(i) * Dot_Product(u%Mesh%TranslationAcc(:,mem%NodeIndx(i)),mem%y_hat)*mem%y_hat & + -0.5*p%WaveField%WtrDens*mem%AxCa(i) * (dSbdl_p*mem%SaMG(i)+dSadl_p*mem%SbMG(i))*SQRT(mem%SaMG(i)*mem%SbMG(i)) * Dot_Product(u%Mesh%TranslationAcc(:,mem%NodeIndx(i)),mem%k)*mem%k + END IF IF ( p%AMMod .EQ. 0_IntKi ) THEN ! Always compute added-mass force on nodes below SWL when undisplaced z1 = u%Mesh%Position(3, mem%NodeIndx(i)) - p%WaveField%MSL2SWL ! Undisplaced z-position of the current node IF ( z1 > 0.0_ReKi ) THEN ! Node is above SWL when undisplaced; zero added-mass force @@ -3304,14 +4355,24 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, y%Mesh%Moment(:,mem%NodeIndx(i)) = y%Mesh%Moment(:,mem%NodeIndx(i)) + m%memberLoads(im)%F_A(4:6, i) !-------------------- hydrodynamic inertia loads: sides: Section 7.1.4 ---------------------------! - IF ( mem%PropMCF ) THEN - f_hydro= p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FAMCF(:,mem%NodeIndx(i)) ) + & - 2.0*mem%AxCa(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & - 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k - ELSE - f_hydro=(mem%Ca(i)+mem%Cp(i))*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & - 2.0*mem%AxCa(i) *p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & - 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k + IF (mem%MSecGeom==MSecGeom_Cyl) THEN + IF ( mem%PropMCF ) THEN + f_hydro= p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FAMCF(:,mem%NodeIndx(i)) ) + & + 2.0*mem%AxCa(i)*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k + ELSE + f_hydro=(mem%Ca(i)+mem%Cp(i))*p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*mem%AxCa(i) *p%WaveField%WtrDens*pi*mem%RMG(i)*mem%RMG(i)*dRdl_p * matmul( mem%kkt, m%FA(:,mem%NodeIndx(i)) ) + & + 2.0*m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)*pi*mem%RMG(i)*dRdl_pp*mem%k + END IF + ELSE IF (mem%MSecGeom==MSecGeom_Rec) THEN + ! Note: MacCamy-Fuchs correction cannot be applied to rectangular members + f_hydro= mem%Cp(i)*p%WaveField%WtrDens* mem%SaMG(i)*mem%SbMG(i) * matmul( mem%Ak, m%FA(:,mem%NodeIndx(i)) ) + & ! transver FK component + m%FDynP(mem%NodeIndx(i))*mem%AxCp(i)* (mem%SaMG(i)*dSbdl_pp+dSadl_pp*mem%SbMG(i)) *mem%k + & ! axial FK component + p%WaveField%WtrDens*mem%CaB(i) * 0.25*pi*mem%SbMG(i)*mem%SbMG(i) * Dot_Product(m%FA(:,mem%NodeIndx(i)),mem%x_hat)*mem%x_hat + & ! x-component of diffraction part + p%WaveField%WtrDens*mem%CaA(i) * 0.25*pi*mem%SaMG(i)*mem%SaMG(i) * Dot_Product(m%FA(:,mem%NodeIndx(i)),mem%y_hat)*mem%y_hat + & ! y-component of diffraction part + 0.5*p%WaveField%WtrDens*mem%AxCa(i) * (dSbdl_p*mem%SaMG(i)+dSadl_p*mem%SbMG(i))*SQRT(mem%SaMG(i)*mem%SbMG(i)) * & ! axial component of diffraction part + Dot_Product(m%FA(:,mem%NodeIndx(i)),mem%k)*mem%k ! axial component of diffraction part cont'd END IF CALL LumpDistrHydroLoads( f_hydro, mem%k, deltal, h_c, m%memberLoads(im)%F_I(:, i) ) y%Mesh%Force (:,mem%NodeIndx(i)) = y%Mesh%Force (:,mem%NodeIndx(i)) + m%memberLoads(im)%F_I(1:3, i) @@ -3324,7 +4385,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, !-----------------------------------------------------------------------------------------------------! ! External Hydrodynamic Side Loads - End ! !-----------------------------------------------------------------------------------------------------! - + !-----------------------------------------------------------------------------------------------------! ! Any end plate loads that are modeled on a per-member basis: F_B and F_BF ! !-----------------------------------------------------------------------------------------------------! @@ -3351,42 +4412,41 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, z1 = m%DispNodePosHst(3,mem%NodeIndx( 1)) z2 = m%DispNodePosHst(3,mem%NodeIndx(N+1)) + if (mem%MSecGeom == MSecGeom_Rec) then + ! Compute total orientation matrix of starting and ending joints + call Morison_DirCosMtrx( u%Mesh%Position(:,mem%NodeIndx(1)), u%Mesh%Position(:,mem%NodeIndx(N+1)), mem%MSpinOrient, CMatrix ) + CMatrix1 = matmul(transpose(u%Mesh%Orientation(:,:,mem%NodeIndx(1 ))),CMatrix) + CALL GetSectionUnitVectors_Rec( CMatrix1, x_hat1, y_hat1 ) + CMatrix2 = matmul(transpose(u%Mesh%Orientation(:,:,mem%NodeIndx(N+1))),CMatrix) + CALL GetSectionUnitVectors_Rec( CMatrix2, x_hat2, y_hat2 ) + end if + + !----------------------------------- filled buoyancy loads: starts -----------------------------------! - !TODO: Do the equations below still work if z1 > z2 ? - !TODO: Should not have to test seabed crossing in time-marching loop - if ( mem%i_floor == 0 ) then ! both ends are above seabed - !--- Water ballast buoyancy --- - ! if member is fully flooded - if (mem%memfloodstatus == 1) then - !if (mem%z_overfill >= 0) then - Fl = -mem%FillDens * g * pi *mem%Rin( 1)**2* (mem%z_overfill + max(z2-z1, 0.0_ReKi)) - Moment = mem%FillDens * g * pi *0.25*mem%Rin( 1)**4*sinPhi - call AddEndLoad(Fl, Moment, sinPhi1, cosPhi1, sinBeta1, cosBeta1, m%F_BF_End(:, mem%NodeIndx(1))) - - Fl = mem%FillDens * g * pi *mem%Rin(N+1)**2* (mem%z_overfill + max(z1-z2, 0.0_ReKi)) - Moment = -mem%FillDens * g * pi *0.25*mem%Rin(N+1)**4*sinPhi - call AddEndLoad(Fl, Moment, sinPhi2, cosPhi2, sinBeta2, cosBeta2, m%F_BF_End(:, mem%NodeIndx(N+1))) - - ! if member is partially flooded - else if (mem%l_fill > 0) then - Fl = -mem%FillDens * g * pi *mem%Rin(1)**2*mem%l_fill*cosPhi - Moment = mem%FillDens * g * pi *0.25*mem%Rin(1)**4*sinPhi - call AddEndLoad(Fl, Moment, sinPhi1, cosPhi1, sinBeta1, cosBeta1, m%F_BF_End(:, mem%NodeIndx(1))) - else - ! no load if member is not flooded at all + if ( mem%memfloodstatus > 0 ) then + + if ( mem%i_floor == 0 ) then ! If the member is not buried in the seabed, compute the internal hydrostatic load on the starting endplate + if ( mem%MSecGeom == MSecGeom_Cyl ) then + m%F_BF_End(1:3, mem%NodeIndx( 1)) = m%F_BF_End(1:3, mem%NodeIndx( 1)) - mem%FillDens * g * pi * mem%Rin( 1)**2* (zFillGroup - z1) * k_hat1 + m%F_BF_End(4:6, mem%NodeIndx( 1)) = m%F_BF_End(4:6, mem%NodeIndx( 1)) - mem%FillDens * g * 0.25 * pi * mem%Rin( 1)**4* Cross_Product(k_hat1,(/0.0,0.0,1.0/)) + else if ( mem%MSecGeom == MSecGeom_Rec ) then + m%F_BF_End(1:3, mem%NodeIndx( 1)) = m%F_BF_End(1:3, mem%NodeIndx( 1)) - mem%FillDens * g * mem%SaIn( 1) *mem%SbIn( 1)* (zFillGroup - z1) * k_hat1 + m%F_BF_End(4:6, mem%NodeIndx( 1)) = m%F_BF_End(4:6, mem%NodeIndx( 1)) - mem%FillDens * g / 12.0 * (mem%SaIn( 1)**3*mem%SbIn( 1)*x_hat1(3)*y_hat1 - mem%SaIn(1)*mem%SbIn(1)**3*y_hat1(3)*x_hat1) + end if end if - - elseif ( mem%i_floor < mem%NElements+1 ) then ! upper node is still above the seabed, but lower node is below seabed - !if (mem%z_overfill >= 0) then - if (mem%memfloodstatus == 1) then - Fl = mem%FillDens * g * pi *mem%Rin(N+1)**2* (mem%z_overfill + max(z1-z2, 0.0_ReKi)) - Moment = -mem%FillDens * g * pi *0.25*mem%Rin(N+1)**4*sinPhi - call AddEndLoad(Fl, Moment, sinPhi2, cosPhi2, sinBeta2, cosBeta2, m%F_BF_End(:, mem%NodeIndx(N+1))) + + if ( (mem%i_floor 0) THEN CALL GetTotalWaveElev( Time, pos1, Zeta1, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL GetFreeSurfaceNormal( Time, pos1, r1, n_hat, ErrStat2, ErrMsg2 ) + CALL GetFreeSurfaceNormal( Time, pos1, rn1, n_hat, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) FSPt = (/pos1(1),pos1(2),Zeta1/) ! Reference point on the free surface ELSE FSPt = (/pos1(1),pos1(2),0.0_ReKi/) n_hat = (/0.0,0.0,1.0/) END IF - CALL GetSectionUnitVectors( k_hat1, y_hat, z_hat ) - CALL GetSectionFreeSurfaceIntersects( REAL(pos1,DbKi), REAL(FSPt,DbKi), k_hat1, y_hat, z_hat, n_hat, REAL(r1,DbKi), theta1, theta2, secStat) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL GetEndPlateHstLds(pos1, k_hat1, y_hat, z_hat, r1, theta1, theta2, F_B_End) - m%F_B_End(:, mem%NodeIndx( 1)) = m%F_B_End(:, mem%NodeIndx( 1)) + F_B_End - IF (mem%MHstLMod == 1) THEN ! Check for partially wetted end plates - IF ( .NOT.( EqualRealNos((theta2-theta1),0.0_DbKi) .OR. EqualRealNos((theta2-theta1),2.0_DbKi*PI_D) ) ) THEN - CALL SetErrStat(ErrID_Warn, 'End plate is partially wetted with MHstLMod = 1. The buoyancy load and distribution potentially have large error. This has happened to the first node of Member ID ' //trim(num2lstr(mem%MemberID)), errStat, errMsg, RoutineName ) - END IF - END IF + + if (mem%MSecGeom==MSecGeom_Cyl) then + CALL GetSectionUnitVectors_Cyl( k_hat1, y_hat, z_hat ) + CALL GetSectionFreeSurfaceIntersects_Cyl( REAL(pos1,DbKi), REAL(FSPt,DbKi), k_hat1, y_hat, z_hat, n_hat, REAL(r1,DbKi), theta1, theta2, secStat) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL GetEndPlateHstLds_Cyl(pos1, k_hat1, y_hat, z_hat, r1, theta1, theta2, F_B_End) + IF (mem%MHstLMod == 1) THEN ! Check for partially wetted end plates + IF ( .NOT.( EqualRealNos((theta2-theta1),0.0_DbKi) .OR. EqualRealNos((theta2-theta1),2.0_DbKi*PI_D) ) ) THEN + CALL SetErrStat(ErrID_Warn, 'End plate is partially wetted with MHstLMod = 1. The buoyancy load and distribution potentially have large error. This has happened to the first node of Member ID ' //trim(num2lstr(mem%MemberID)), errStat, errMsg, RoutineName ) + END IF + END IF + else if (mem%MSecGeom==MSecGeom_Rec) then + CALL GetSectionUnitVectors_Rec( CMatrix1, x_hat, y_hat ) + CALL GetEndPlateHstLds_Rec(pos1, k_hat1, x_hat, y_hat, Sa1, Sb1, FSPt, n_hat, F_B_End) + end if + m%F_B_End(:, mem%NodeIndx( 1)) = m%F_B_End(:, mem%NodeIndx( 1)) + F_B_End + ! Compute loads on the end plate of node N+1 IF (p%WaveField%WaveStMod > 0) THEN CALL GetTotalWaveElev( Time, pos2, Zeta2, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL GetFreeSurfaceNormal( Time, pos2, r2, n_hat, ErrStat2, ErrMsg2 ) + CALL GetFreeSurfaceNormal( Time, pos2, rn2, n_hat, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) FSPt = (/pos2(1),pos2(2),Zeta2/) ! Reference point on the free surface ELSE FSPt = (/pos2(1),pos2(2),0.0_ReKi/) n_hat = (/0.0,0.0,1.0/) END IF - CALL GetSectionUnitVectors( k_hat2, y_hat, z_hat ) - CALL GetSectionFreeSurfaceIntersects( REAL(pos2,DbKi), REAL(FSPt,DbKi), k_hat2, y_hat, z_hat, n_hat, REAL(r2,DbKi), theta1, theta2, secStat) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL GetEndPlateHstLds(pos2, k_hat2, y_hat, z_hat, r2, theta1, theta2, F_B_End) - m%F_B_End(:, mem%NodeIndx(N+1)) = m%F_B_End(:, mem%NodeIndx(N+1)) - F_B_End - IF (mem%MHstLMod == 1) THEN ! Check for partially wetted end plates - IF ( .NOT.( EqualRealNos((theta2-theta1),0.0_DbKi) .OR. EqualRealNos((theta2-theta1),2.0_DbKi*PI_D) ) ) THEN - CALL SetErrStat(ErrID_Warn, 'End plate is partially wetted with MHstLMod = 1. The buoyancy load and distribution potentially have large error. This has happened to the last node of Member ID ' //trim(num2lstr(mem%MemberID)), errStat, errMsg, RoutineName ) + + if (mem%MSecGeom==MSecGeom_Cyl) then + CALL GetSectionUnitVectors_Cyl( k_hat2, y_hat, z_hat ) + CALL GetSectionFreeSurfaceIntersects_Cyl( REAL(pos2,DbKi), REAL(FSPt,DbKi), k_hat2, y_hat, z_hat, n_hat, REAL(r2,DbKi), theta1, theta2, secStat) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL GetEndPlateHstLds_Cyl(pos2, k_hat2, y_hat, z_hat, r2, theta1, theta2, F_B_End) + IF (mem%MHstLMod == 1) THEN ! Check for partially wetted end plates + IF ( .NOT.( EqualRealNos((theta2-theta1),0.0_DbKi) .OR. EqualRealNos((theta2-theta1),2.0_DbKi*PI_D) ) ) THEN + CALL SetErrStat(ErrID_Warn, 'End plate is partially wetted with MHstLMod = 1. The buoyancy load and distribution potentially have large error. This has happened to the last node of Member ID ' //trim(num2lstr(mem%MemberID)), errStat, errMsg, RoutineName ) + END IF END IF - END IF + else if (mem%MSecGeom==MSecGeom_Rec) then + CALL GetSectionUnitVectors_Rec( CMatrix2, x_hat, y_hat ) + CALL GetEndPlateHstLds_Rec(pos2, k_hat2, x_hat, y_hat, Sa2, Sb2, FSPt, n_hat, F_B_End) + end if + m%F_B_End(:, mem%NodeIndx(N+1)) = m%F_B_End(:, mem%NodeIndx(N+1)) - F_B_End + elseif ( mem%doEndBuoyancy ) then ! The member crosses the seabed line so only the upper end potentially have hydrostatic load ! Only compute the loads on the end plate of node N+1 IF (p%WaveField%WaveStMod > 0) THEN CALL GetTotalWaveElev( Time, pos2, Zeta2, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL GetFreeSurfaceNormal( Time, pos2, r2, n_hat, ErrStat2, ErrMsg2 ) + CALL GetFreeSurfaceNormal( Time, pos2, rn2, n_hat, ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) FSPt = (/pos2(1),pos2(2),Zeta2/) ! Reference point on the free surface ELSE FSPt = (/pos2(1),pos2(2),0.0_ReKi/) n_hat = (/0.0,0.0,1.0/) END IF - CALL GetSectionUnitVectors( k_hat2, y_hat, z_hat ) - CALL GetSectionFreeSurfaceIntersects( REAL(pos2,DbKi), REAL(FSPt,DbKi), k_hat2, y_hat, z_hat, n_hat, REAL(r2,DbKi), theta1, theta2, secStat) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL GetEndPlateHstLds(pos2, k_hat2, y_hat, z_hat, r2, theta1, theta2, F_B_End) - m%F_B_End(:, mem%NodeIndx(N+1)) = m%F_B_End(:, mem%NodeIndx(N+1)) - F_B_End - IF (mem%MHstLMod == 1) THEN ! Check for partially wetted end plates - IF ( .NOT.( EqualRealNos((theta2-theta1),0.0_DbKi) .OR. EqualRealNos((theta2-theta1),2.0_DbKi*PI_D) ) ) THEN - CALL SetErrStat(ErrID_Warn, 'End plate is partially wetted with MHstLMod = 1. The buoyancy load and distribution potentially have large error. This has happened to the last node of Member ID ' //trim(num2lstr(mem%MemberID)), errStat, errMsg, RoutineName ) + + if (mem%MSecGeom==MSecGeom_Cyl) then + CALL GetSectionUnitVectors_Cyl( k_hat2, y_hat, z_hat ) + CALL GetSectionFreeSurfaceIntersects_Cyl( REAL(pos2,DbKi), REAL(FSPt,DbKi), k_hat2, y_hat, z_hat, n_hat, REAL(r2,DbKi), theta1, theta2, secStat) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL GetEndPlateHstLds_Cyl(pos2, k_hat2, y_hat, z_hat, r2, theta1, theta2, F_B_End) + IF (mem%MHstLMod == 1) THEN ! Check for partially wetted end plates + IF ( .NOT.( EqualRealNos((theta2-theta1),0.0_DbKi) .OR. EqualRealNos((theta2-theta1),2.0_DbKi*PI_D) ) ) THEN + CALL SetErrStat(ErrID_Warn, 'End plate is partially wetted with MHstLMod = 1. The buoyancy load and distribution potentially have large error. This has happened to the last node of Member ID ' //trim(num2lstr(mem%MemberID)), errStat, errMsg, RoutineName ) + END IF END IF - END IF + else if (mem%MSecGeom==MSecGeom_Rec) then + CALL GetSectionUnitVectors_Rec( CMatrix2, x_hat, y_hat ) + CALL GetEndPlateHstLds_Rec(pos2, k_hat2, x_hat, y_hat, Sa2, Sb2, FSPt, n_hat, F_B_End) + end if + m%F_B_End(:, mem%NodeIndx(N+1)) = m%F_B_End(:, mem%NodeIndx(N+1)) - F_B_End + ! else ! entire member is buried below the seabed end if - + end if ! PropPot !----------------------------------- external buoyancy loads: ends -----------------------------------! end do ! im - looping through members - + !---------------------------------------------------------------------------------------------------------------! ! External Hydrodynamic Joint Loads - Start ! ! F_D_End, F_I_End, F_A_End, F_IMG_End ! @@ -3480,8 +4572,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! NOTE: All wave kinematics have already been zeroed out above the SWL or instantaneous wave height (for WaveStMod > 0), ! so loads derived from the kinematics will be correct without the use of a nodeInWater value, but other loads need to be ! multiplied by nodeInWater to zero them out above the SWL or instantaneous wave height. - !TODO: Where's F_WMF_End computed? - + DO J = 1, p%NJoints ! Obtain the node index because WaveVel, WaveAcc, and WaveDynP are defined in the node indexing scheme, not the markers (No longer relevant?) ! The first NJoints nodes are all the joints with the rest being the internal nodes. See Morison_GenerateSimulationNodes. @@ -3493,7 +4584,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! Therefore, no need to check PropPot here. ! Effect of wave stretching already baked into m%FDynP, m%FA, and m%vrel. No additional modification needed. - + ! Joint yaw offset call YawJoint(J,u%PtfmRefY,AM_End,An_End,DP_Const_End,I_MG_End,ErrStat2,ErrMsg2) call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) @@ -3507,11 +4598,8 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, m%F_I_End(:,J) = (DP_Const_End * m%FDynP(j) + matmul(AM_End,m%FA(:,j))) ! Marine growth inertia: ends: Section 4.2.2 - ! With wave stretching, m%nodeInWater is based on the instantaneous free surface and the current body position if (WaveDisp/=0). - ! This should still be ok because with wave stretching, we do not allow joints to come out of water if initially submerged or - ! enter water if initially out of water. This is enforced when computing the side loads above. - m%F_IMG_End(1:3,j) = -m%nodeInWater(j) * p%Mass_MG_End(j)*qdotdot(1:3) - m%F_IMG_End(4:6,j) = -m%nodeInWater(j) * (matmul(I_MG_End,qdotdot(4:6)) - cross_product(u%Mesh%RotationVel(:,J),matmul(I_MG_End,u%Mesh%RotationVel(:,J)))) + m%F_IMG_End(1:3,j) = -p%Mass_MG_End(j)*qdotdot(1:3) + m%F_IMG_End(4:6,j) = -matmul(I_MG_End,qdotdot(4:6)) - cross_product(u%Mesh%RotationVel(:,J),matmul(I_MG_End,u%Mesh%RotationVel(:,J))) ! Compute the dot product of the relative velocity vector with the directional Area of the Joint ! m%nodeInWater(j) is probably not necessary because m%vrel is zeroed when the node is out of water @@ -3522,7 +4610,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, ! Record most up-to-date vmagf and vmag at join J m%v_rel_n(j) = vmag m%v_rel_n_HiPass(j) = vmagf - + ! Evaluate drag force and combine all per-joint loads DO I=1,6 IF (I < 4 ) THEN ! Three force components @@ -3544,7 +4632,7 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat, END DO ! I=1,6 END DO ! J = 1, p%NJoints - + !---------------------------------------------------------------------------------------------------------------! ! External Hydrodynamic Joint Loads - End ! !---------------------------------------------------------------------------------------------------------------! @@ -3623,7 +4711,7 @@ SUBROUTINE GetFreeSurfaceNormal( Time, pos, r, n, ErrStat, ErrMsg) END SUBROUTINE GetFreeSurfaceNormal - SUBROUTINE GetSectionUnitVectors( k, y, z ) + SUBROUTINE GetSectionUnitVectors_Cyl( k, y, z ) REAL(ReKi), INTENT( In ) :: k(3) ! Member axial unit vector REAL(ReKi), INTENT( OUT ) :: y(3) ! Horizontal unit vector perpendicular to k REAL(ReKi), INTENT( OUT ) :: z(3) ! Unit vector perpendicular to k and y with positive vertical component @@ -3638,9 +4726,17 @@ SUBROUTINE GetSectionUnitVectors( k, y, z ) y = -y; z = -z; END IF - END SUBROUTINE GetSectionUnitVectors + END SUBROUTINE GetSectionUnitVectors_Cyl - SUBROUTINE GetSectionFreeSurfaceIntersects( pos0, FSPt, k_hat, y_hat, z_hat, n_hat, R, theta1, theta2, secStat) + SUBROUTINE GetSectionUnitVectors_Rec( DirCos, x, y ) + REAL(ReKi), INTENT( In ) :: DirCos(3,3) ! Element local to global rotation matrix + REAL(ReKi), INTENT( OUT ) :: x(3) ! Section local x unit vector parallel to side A + REAL(ReKi), INTENT( OUT ) :: y(3) ! Section local y unit vector parallel to side B + x = DirCos(1:3,1) + y = DirCos(1:3,2) + END SUBROUTINE GetSectionUnitVectors_Rec + + SUBROUTINE GetSectionFreeSurfaceIntersects_Cyl( pos0, FSPt, k_hat, y_hat, z_hat, n_hat, R, theta1, theta2, secStat) REAL(DbKi), INTENT( In ) :: pos0(3) REAL(DbKi), INTENT( In ) :: FSPt(3) REAL(ReKi), INTENT( In ) :: k_hat(3) @@ -3654,7 +4750,7 @@ SUBROUTINE GetSectionFreeSurfaceIntersects( pos0, FSPt, k_hat, y_hat, z_hat, n_h REAL(DbKi) :: a, b, c, d, d2 REAL(DbKi) :: alpha, beta REAL(DbKi) :: tmp - CHARACTER(*), PARAMETER :: RoutineName = 'GetSectionFreeSurfaceIntersects' + CHARACTER(*), PARAMETER :: RoutineName = 'GetSectionFreeSurfaceIntersects_Cyl' a = R * dot_product(y_hat,n_hat) b = R * dot_product(z_hat,n_hat) @@ -3686,9 +4782,9 @@ SUBROUTINE GetSectionFreeSurfaceIntersects( pos0, FSPt, k_hat, y_hat, z_hat, n_h secStat = 0; END IF - END SUBROUTINE GetSectionFreeSurfaceIntersects + END SUBROUTINE GetSectionFreeSurfaceIntersects_Cyl - SUBROUTINE GetSectionHstLds( origin, pos0, k_hat, y_hat, z_hat, R, dRdl, theta1, theta2, dFdl) + SUBROUTINE GetSectionHstLds_Cyl( origin, pos0, k_hat, y_hat, z_hat, R, dRdl, theta1, theta2, dFdl) REAL(DbKi), INTENT( IN ) :: origin(3) REAL(DbKi), INTENT( IN ) :: pos0(3) @@ -3719,9 +4815,118 @@ SUBROUTINE GetSectionHstLds( origin, pos0, k_hat, y_hat, z_hat, R, dRdl, theta1, dFdl(4:6) = -R**2*dRdl*C2*y_hat + R**2*dRdl*C1*z_hat + CROSS_PRODUCT((pos0-origin),dFdl(1:3)) dFdl = dFdl * p%WaveField%WtrDens * g - END SUBROUTINE GetSectionHstLds + END SUBROUTINE GetSectionHstLds_Cyl + + SUBROUTINE GetSectionHstLds_Rec( origin, pos0, k_hat, x_hat, y_hat, Sa, Sb, dSadl, dSbdl, rFS, nFS, dFdl, secStat) + + REAL(DbKi), INTENT( IN ) :: origin(3) + REAL(DbKi), INTENT( IN ) :: pos0(3) + REAL(DbKi), INTENT( IN ) :: k_hat(3) + REAL(DbKi), INTENT( IN ) :: x_hat(3) + REAL(DbKi), INTENT( IN ) :: y_hat(3) + REAL(DbKi), INTENT( IN ) :: Sa, Sb + REAL(DbKi), INTENT( IN ) :: dSadl, dSbdl + REAL(DbKi), INTENT( IN ) :: rFS(3) + REAL(DbKi), INTENT( IN ) :: nFS(3) + REAL(DbKi), INTENT( OUT ) :: dFdl(6) + INTEGER(IntKi), INTENT( OUT ) :: secStat + + INTEGER(IntKi) :: i, v1, v2, numVInWtr + REAL(DbKi) :: s, s1, s2, sInt, x0, y0, z0, x1, y1, z1, x2, y2, z2 + REAL(DbKi) :: n(3,4), rv(3,4) + REAL(DbKi) :: C(3) + LOGICAL :: vInWtr(4) + + ! Origin point about which moment is computed + x0 = origin(1) + y0 = origin(2) + z0 = origin(3) + + ! Global coordinates of the four vertices of the section + rv(:,1) = pos0 + x_hat * (-0.5*Sa) + y_hat * (-0.5*Sb) + rv(:,2) = pos0 + x_hat * ( 0.5*Sa) + y_hat * (-0.5*Sb) + rv(:,3) = pos0 + x_hat * ( 0.5*Sa) + y_hat * ( 0.5*Sb) + rv(:,4) = pos0 + x_hat * (-0.5*Sa) + y_hat * ( 0.5*Sb) + + ! Unit normal vector of side walls + n(:,1) = y_hat + k_hat * 0.5 * dSbdl + n(:,2) = -x_hat + k_hat * 0.5 * dSadl + n(:,3) = -y_hat + k_hat * 0.5 * dSbdl + n(:,4) = x_hat + k_hat * 0.5 * dSadl + + ! Check for and count vertices in water + numVInWtr = 0 + do i = 1,4 + vInWtr(i) = ( Dot_Product(rv(:,i)-rFS,nFS) <= 0.0 ) + if ( vInWtr(i) ) then + numVInWtr = numVInWtr + 1 + end if + end do + + ! Return section status + if (numVInWtr == 0) then ! Completely dry section + secStat = 0; + else if (numVInWtr == 4) then ! Completely submerged section + secStat = 2; + else ! Partially wetted section that intersects the free surface + secStat = 1; + end if + + ! Compute the hydrostatic force and moment on each of the 4 sides + dFdl = 0.0 + do i = 1,4 + v1 = i + if (i == 4) then + v2 = 1 + else + v2 = i+1 + end if + x1 = rv(1,v1) + y1 = rv(2,v1) + z1 = rv(3,v1) + x2 = rv(1,v2) + y2 = rv(2,v2) + z2 = rv(3,v2) + if ( (i==1) .or. (i==3) ) then + s = Sa + else + s = Sb + end if + if (EqualRealNos(s,0.0_DbKi)) cycle + if ( vInWtr(v1) .and. vInWtr(v2) ) then + ! Side fully submerged + s1 = 0.0 + s2 = s; + else if ( vInWtr(v1) .or. vInWtr(v2) ) then + ! Side partially wetted + sInt = s * DOT_PRODUCT(rFS-rv(:,v1),nFS) / DOT_PRODUCT(rv(:,v2)-rv(:,v1),nFS) + if ( vInWtr(v1) ) then + s1 = 0.0 + s2 = sInt + else + s1 = sInt + s2 = s + end if + else + ! Side fully out of water + s1 = 0.0; + s2 = 0.0; + end if + + dFdl(1:3) = dFdl(1:3) + & + -n(:,i) * ( z1*(s2-s1) + 0.5*(z2-z1)/s*(s2*s2-s1*s1) ) + C(1) = (z2-z1)*(x2-x1)/3.0/(s*s)*(s2**3-s1**3) + 0.5*((z2-z1)*(x1-x0)/s+(x2-x1)*z1/s)*(s2*s2-s1*s1) + z1*(x1-x0)*(s2-s1) + C(2) = (z2-z1)*(y2-y1)/3.0/(s*s)*(s2**3-s1**3) + 0.5*((z2-z1)*(y1-y0)/s+(y2-y1)*z1/s)*(s2*s2-s1*s1) + z1*(y1-y0)*(s2-s1) + C(3) = (z2-z1)*(z2-z1)/3.0/(s*s)*(s2**3-s1**3) + 0.5*((z2-z1)*(z1-z0)/s+(z2-z1)*z1/s)*(s2*s2-s1*s1) + z1*(z1-z0)*(s2-s1) + dFdl(4:6) = dFdl(4:6) - CROSS_PRODUCT(C,n(:,i)) + + end do + + dFdl = dFdl * p%WaveField%WtrDens * g + + END SUBROUTINE GetSectionHstLds_Rec - SUBROUTINE getElementHstLds_Mod2( pos1In, pos2In, FSPtIn, k_hatIn, y_hatIn, z_hatIn, n_hatIn, r1In, r2In, dlIn, F_B1, F_B2, ErrStat, ErrMsg ) + SUBROUTINE getElementHstLds_Mod2_Cyl( pos1In, pos2In, FSPtIn, k_hatIn, y_hatIn, z_hatIn, n_hatIn, r1In, r2In, dlIn, F_B1, F_B2, ErrStat, ErrMsg ) REAL(ReKi), INTENT( IN ) :: pos1In(3) REAL(ReKi), INTENT( IN ) :: pos2In(3) @@ -3741,7 +4946,7 @@ SUBROUTINE getElementHstLds_Mod2( pos1In, pos2In, FSPtIn, k_hatIn, y_hatIn, z_ha REAL(DbKi) :: dFdl1(6), dFdlMid(6), dFdl2(6), F_B(6) REAL(DbKi) :: i, dl, r1, r2, rMid, dRdl, posMid(3), pos1(3), pos2(3), FSPt(3), k_hat(3), y_hat(3), z_hat(3), n_hat(3) INTEGER(IntKi) :: secStat1, secStatMid, secStat2 - CHARACTER(*), PARAMETER :: routineName = "getElementHstLds_Mod2" + CHARACTER(*), PARAMETER :: routineName = "getElementHstLds_Mod2_Cyl" INTEGER(IntKi) :: errStat2 CHARACTER(ErrMsgLen) :: errMsg2 ErrStat = ErrID_None @@ -3775,19 +4980,99 @@ SUBROUTINE getElementHstLds_Mod2( pos1In, pos2In, FSPtIn, k_hatIn, y_hatIn, z_ha END IF ! Section load at node 1 - CALL GetSectionFreeSurfaceIntersects( pos1, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), r1, theta1, theta2, secStat1) - CALL GetSectionHstLds( pos1, pos1, k_hat, y_hat, z_hat, r1, dRdl, theta1, theta2, dFdl1) + CALL GetSectionFreeSurfaceIntersects_Cyl( pos1, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), r1, theta1, theta2, secStat1) + CALL GetSectionHstLds_Cyl( pos1, pos1, k_hat, y_hat, z_hat, r1, dRdl, theta1, theta2, dFdl1) + + ! Section load at midpoint + CALL GetSectionFreeSurfaceIntersects_Cyl( posMid, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), rMid, theta1, theta2, secStatMid) + CALL GetSectionHstLds_Cyl( pos1, posMid, k_hat, y_hat, z_hat, rMid, dRdl, theta1, theta2, dFdlMid) + + ! Section load at node 2 + CALL GetSectionFreeSurfaceIntersects_Cyl( pos2, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), r2, theta1, theta2, secStat2) + CALL GetSectionHstLds_Cyl( pos1, pos2, k_hat, y_hat, z_hat, r2, dRdl, theta1, theta2, dFdl2) + + ! Adaptively refine the load integration over the element + CALL RefineElementHstLds_Cyl(pos1,pos1,posMid,pos2,FSPt,r1,rMid,r2,dl,dRdl,secStat1,secStatMid,secStat2,k_hat,y_hat,z_hat,n_hat,dFdl1,dFdlMid,dFdl2,1,F_B,ErrStat2,ErrMsg2) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + + ! Distribute the hydrostatic load to the two end nodes + F_B1(1:3) = 0.5 * F_B(1:3) + F_B2(1:3) = 0.5 * F_B(1:3) + F_B(4:6) = F_B(4:6) - CROSS_PRODUCT(k_hat*dl,F_B2(1:3)) + F_B1(4:6) = 0.5 * F_B(4:6) + F_B2(4:6) = 0.5 * F_B(4:6) + + END SUBROUTINE getElementHstLds_Mod2_Cyl + + SUBROUTINE getElementHstLds_Mod2_Rec( pos1In, pos2In, FSPtIn, k_hatIn, x_hatIn, y_hatIn, n_hatIn, Sa1In, Sa2In, Sb1In, Sb2In, dlIn, F_B1, F_B2, ErrStat, ErrMsg ) + + REAL(ReKi), INTENT( IN ) :: pos1In(3) + REAL(ReKi), INTENT( IN ) :: pos2In(3) + REAL(ReKi), INTENT( IN ) :: FSPtIn(3) + REAL(ReKi), INTENT( IN ) :: k_hatIn(3) + REAL(ReKi), INTENT( IN ) :: x_hatIn(3) + REAL(ReKi), INTENT( IN ) :: y_hatIn(3) + REAL(ReKi), INTENT( IN ) :: n_hatIn(3) + REAL(ReKi), INTENT( IN ) :: Sa1In, Sb1In + REAL(ReKi), INTENT( IN ) :: Sa2In, Sb2In + REAL(ReKi), INTENT( IN ) :: dlIn + REAL(ReKi), INTENT( OUT ) :: F_B1(6) + REAL(ReKi), INTENT( OUT ) :: F_B2(6) + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if errStat /= ErrID_None + + REAL(DbKi) :: dFdl1(6), dFdlMid(6), dFdl2(6), F_B(6) + REAL(DbKi) :: i, dl, Sa1, Sa2, SaMid, Sb1, Sb2, SbMid, dSadl, dSbdl, posMid(3), pos1(3), pos2(3), FSPt(3), k_hat(3), x_hat(3), y_hat(3), n_hat(3) + INTEGER(IntKi) :: secStat1, secStatMid, secStat2 + CHARACTER(*), PARAMETER :: routineName = "getElementHstLds_Mod2_Rec" + INTEGER(IntKi) :: errStat2 + CHARACTER(ErrMsgLen) :: errMsg2 + ErrStat = ErrID_None + ErrMsg = "" + + pos1 = REAL(pos1In,DbKi) + pos2 = REAL(pos2In,DbKi) + Sa1 = REAL(Sa1In,DbKi) + Sa2 = REAL(Sa2In,DbKi) + Sb1 = REAL(Sb1In,DbKi) + Sb2 = REAL(Sb2In,DbKi) + dl = REAL(dlIn,DbKi) + dSadl = (Sa2-Sa1)/dl + dSbdl = (Sb2-Sb1)/dl + SaMid = 0.5*( Sa1+ Sa2) + SbMid = 0.5*( Sb1+ Sb2) + posMid = 0.5*(pos1In+pos2In) + FSPt = REAL(FSPtIn,DbKi) + k_hat = REAL(k_hatIn,DbKi) + x_hat = REAL(x_hatIn,DbKi) + y_hat = REAL(y_hatIn,DbKi) + n_hat = REAL(n_hatIn,DbKi) + + ! Avoid sections coincident with the SWL + IF ( ABS(k_hat(3)) > 0.999999_ReKi ) THEN ! Vertical member + IF ( EqualRealNos( pos1(3), 0.0_DbKi ) ) THEN + pos1(3) = pos1(3) - 1.0E-6 * dl + END IF + IF ( EqualRealNos( pos2(3), 0.0_DbKi ) ) THEN + pos2(3) = pos2(3) - 1.0E-6 * dl + END IF + IF ( EqualRealNos( posMid(3), 0.0_DbKi ) ) THEN + posMid(3) = posMid(3) - 1.0E-6 * dl + END IF + END IF + + ! Section load at node 1 + CALL GetSectionHstLds_Rec( pos1, pos1, k_hat, x_hat, y_hat, Sa1, Sb1, dSadl, dSbdl, FSPt, n_hat, dFdl1, secStat1) ! Section load at midpoint - CALL GetSectionFreeSurfaceIntersects( posMid, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), rMid, theta1, theta2, secStatMid) - CALL GetSectionHstLds( pos1, posMid, k_hat, y_hat, z_hat, rMid, dRdl, theta1, theta2, dFdlMid) + CALL GetSectionHstLds_Rec( pos1, posMid, k_hat, x_hat, y_hat, SaMid, SbMid, dSadl, dSbdl, FSPt, n_hat, dFdlMid, secStatMid) ! Section load at node 2 - CALL GetSectionFreeSurfaceIntersects( pos2, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), r2, theta1, theta2, secStat2) - CALL GetSectionHstLds( pos1, pos2, k_hat, y_hat, z_hat, r2, dRdl, theta1, theta2, dFdl2) + CALL GetSectionHstLds_Rec( pos1, pos2, k_hat, x_hat, y_hat, Sa2, Sb2, dSadl, dSbdl, FSPt, n_hat, dFdl2, secStat2) ! Adaptively refine the load integration over the element - CALL RefineElementHstLds(pos1,pos1,posMid,pos2,FSPt,r1,rMid,r2,dl,dRdl,secStat1,secStatMid,secStat2,k_hat,y_hat,z_hat,n_hat,dFdl1,dFdlMid,dFdl2,1,F_B,ErrStat2,ErrMsg2) + CALL RefineElementHstLds_Rec(pos1,pos1,posMid,pos2,FSPt,Sa1,SaMid,Sa2,Sb1,SbMid,Sb2,dl,dSadl,dSbdl, & + secStat1,secStatMid,secStat2,k_hat,x_hat,y_hat,n_hat,dFdl1,dFdlMid,dFdl2,1,F_B,ErrStat2,ErrMsg2) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) ! Distribute the hydrostatic load to the two end nodes @@ -3797,9 +5082,9 @@ SUBROUTINE getElementHstLds_Mod2( pos1In, pos2In, FSPtIn, k_hatIn, y_hatIn, z_ha F_B1(4:6) = 0.5 * F_B(4:6) F_B2(4:6) = 0.5 * F_B(4:6) - END SUBROUTINE getElementHstLds_Mod2 + END SUBROUTINE getElementHstLds_Mod2_Rec - RECURSIVE SUBROUTINE RefineElementHstLds( origin, pos1, posMid, pos2, FSPt, r1, rMid, r2, dl, dRdl,secStat1,secStatMid,secStat2, k_hat, y_hat, z_hat, n_hat, dFdl1, dFdlMid, dFdl2, recurLvl, F_B_5pt, ErrStat, ErrMsg) + RECURSIVE SUBROUTINE RefineElementHstLds_Cyl( origin, pos1, posMid, pos2, FSPt, r1, rMid, r2, dl, dRdl,secStat1,secStatMid,secStat2, k_hat, y_hat, z_hat, n_hat, dFdl1, dFdlMid, dFdl2, recurLvl, F_B_5pt, ErrStat, ErrMsg) REAL(DbKi), INTENT( IN ) :: origin(3) REAL(DbKi), INTENT( IN ) :: pos1(3) @@ -3837,7 +5122,7 @@ RECURSIVE SUBROUTINE RefineElementHstLds( origin, pos1, posMid, pos2, FSPt, r1, REAL(DbKi), PARAMETER :: RelTol = 1.0E-6 REAL(DbKi), PARAMETER :: AbsTol = 1.0E-8 INTEGER(IntKi), PARAMETER :: maxRecurLvl = 50 - CHARACTER(*), PARAMETER :: RoutineName = "RefineElementHstLds" + CHARACTER(*), PARAMETER :: RoutineName = "RefineElementHstLds_Cyl" ErrStat = ErrID_None ErrMsg = "" @@ -3861,12 +5146,111 @@ RECURSIVE SUBROUTINE RefineElementHstLds( origin, pos1, posMid, pos2, FSPt, r1, F_B_3pt = (dFdl1 + 4.0*dFdlMid + dFdl2) * dl/6.0 ! Mid point of left section - CALL GetSectionFreeSurfaceIntersects( posMidL, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), rMidL, theta1, theta2, secStatMidL) - CALL GetSectionHstLds( origin, posMidL, k_hat, y_hat, z_hat, rMidL, dRdl, theta1, theta2, dFdlMidL) + CALL GetSectionFreeSurfaceIntersects_Cyl( posMidL, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), rMidL, theta1, theta2, secStatMidL) + CALL GetSectionHstLds_Cyl( origin, posMidL, k_hat, y_hat, z_hat, rMidL, dRdl, theta1, theta2, dFdlMidL) + + ! Mid point of right section + CALL GetSectionFreeSurfaceIntersects_Cyl( posMidR, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), rMidR, theta1, theta2, secStatMidR) + CALL GetSectionHstLds_Cyl( origin, posMidR, k_hat, y_hat, z_hat, rMidR, dRdl, theta1, theta2, dFdlMidR) + + F_B_5pt = (dFdl1 + 4.0*dFdlMidL + 2.0*dFdlMid + 4.0*dFdlMidR + dFdl2) * dl/12.0 + + error = ABS(F_B_3pt - F_B_5pt) + tolMet = .TRUE. + DO i = 1,6 + IF ( error(i) > MAX(RelTol*ABS(F_B_5pt(i)),AbsTol) ) THEN + tolMet = .FALSE. + END IF + END DO + refine = .NOT. tolMet + IF (ABS(secStat1-secStat2)>1) THEN ! (Sub)element bounds the waterplane + refine = .TRUE. ! Keep refining irrespective of tolMet to avoid premature termination + END IF + IF ( recurLvl > maxRecurLvl ) THEN + refine = .FALSE. + IF (.NOT. tolMet) THEN + CALL SetErrStat(ErrID_Warn, 'Tolerance for element hydrostatic load not met after the maximum allowed level of recursion is reached. Consider reducing MDivSize.', ErrStat, ErrMsg, RoutineName ) + ! ELSE + ! Free surface is likely normal to the element. + END IF + END IF + + IF (refine) THEN ! Recursively refine the load integration if tolerance not met + CALL RefineElementHstLds_Cyl(origin,pos1,posMidL,posMid,FSPt,r1,rMidL,rMid,0.5*dl,dRdl,secStat1,secStatMidL,secStatMid,k_hat,y_hat,z_hat,n_hat,dFdl1,dFdlMidL,dFdlMid, recurLvl+1, tmp, ErrStat, ErrMsg) + CALL RefineElementHstLds_Cyl(origin,posMid,posMidR,pos2,FSPt,rMid,rMidR,r2,0.5*dl,dRdl,secStatMid,secStatMidR,secStat2,k_hat,y_hat,z_hat,n_hat,dFdlMid,dFdlMidR,dFdl2, recurLvl+1, F_B_5pt, ErrStat, ErrMsg) + F_B_5pt = F_B_5pt + tmp + END IF + + END SUBROUTINE RefineElementHstLds_Cyl + + RECURSIVE SUBROUTINE RefineElementHstLds_Rec( origin, pos1, posMid, pos2, FSPt, Sa1, SaMid, Sa2, Sb1, SbMid, Sb2, dl, dSadl, dSbdl, & + secStat1, secStatMid, secStat2, k_hat, x_hat, y_hat, n_hat, dFdl1, dFdlMid, dFdl2, recurLvl, F_B_5pt, ErrStat, ErrMsg) + + REAL(DbKi), INTENT( IN ) :: origin(3) + REAL(DbKi), INTENT( IN ) :: pos1(3) + REAL(DbKi), INTENT( IN ) :: posMid(3) + REAL(DbKi), INTENT( IN ) :: pos2(3) + REAL(DbKi), INTENT( IN ) :: FSPt(3) + REAL(DbKi), INTENT( IN ) :: Sa1, Sb1 + REAL(DbKi), INTENT( IN ) :: SaMid, SbMid + REAL(DbKi), INTENT( IN ) :: Sa2, Sb2 + REAL(DbKi), INTENT( IN ) :: dl + REAL(DbKi), INTENT( IN ) :: dSadl, dSbdl + INTEGER(IntKi), INTENT( IN ) :: secStat1 + INTEGER(IntKi), INTENT( IN ) :: secStatMid + INTEGER(IntKi), INTENT( IN ) :: secStat2 + REAL(DbKi), INTENT( IN ) :: k_hat(3) + REAL(DbKi), INTENT( IN ) :: x_hat(3) + REAL(DbKi), INTENT( IN ) :: y_hat(3) + REAL(DbKi), INTENT( IN ) :: n_hat(3) + REAL(DbKi), INTENT( IN ) :: dFdl1(6) + REAL(DbKi), INTENT( IN ) :: dFdlMid(6) + REAL(DbKi), INTENT( IN ) :: dFdl2(6) + INTEGER(IntKi), INTENT( IN ) :: recurLvl + REAL(DbKi), INTENT( OUT ) :: F_B_5pt(6) + INTEGER(IntKi), INTENT( OUT ) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT ) :: ErrMsg ! Error message if errStat /= ErrID_None + + REAL(DbKi) :: posMidL(3), posMidR(3) + REAL(DbKi) :: SaMidL, SbMidL, SaMidR, SbMidR + REAL(DbKi) :: dFdlMidL(6), dFdlMidR(6), F_B_3pt(6) + REAL(DbKi) :: error(6), tmp(6) + LOGICAL :: refine, tolMet + INTEGER(IntKi) :: i + INTEGER(IntKi) :: secStatMidL, secStatMidR + REAL(DbKi), PARAMETER :: RelTol = 1.0E-6 + REAL(DbKi), PARAMETER :: AbsTol = 1.0E-8 + INTEGER(IntKi), PARAMETER :: maxRecurLvl = 50 + CHARACTER(*), PARAMETER :: RoutineName = "RefineElementHstLds_Rec" + + ErrStat = ErrID_None + ErrMsg = "" + + posMidL = 0.5*(pos1+posMid) + posMidR = 0.5*(posMid+pos2) + SaMidL = 0.5*(Sa1+SaMid) + SbMidL = 0.5*(Sb1+SbMid) + SaMidR = 0.5*(SaMid+Sa2) + SbMidR = 0.5*(SbMid+Sb2) + + ! Avoid sections coincident with the SWL + IF ( ABS(k_hat(3)) > 0.999999_ReKi ) THEN ! Vertical member + IF ( EqualRealNos( posMidL(3), 0.0_DbKi ) ) THEN + posMidL(3) = posMidL(3) - 1.0E-6 * dl + END IF + IF ( EqualRealNos( posMidR(3), 0.0_DbKi ) ) THEN + posMidR(3) = posMidR(3) - 1.0E-6 * dl + END IF + END IF + + ! Total hydrostatic load on the element (Simpsons Rule) + F_B_3pt = (dFdl1 + 4.0*dFdlMid + dFdl2) * dl/6.0 + + ! Mid point of left section + CALL GetSectionHstLds_Rec( origin, posMidL, k_hat, x_hat, y_hat, SaMidL, SbMidL, dSadl, dSbdl, FSPt, n_hat, dFdlMidL, secStatMidL) ! Mid point of right section - CALL GetSectionFreeSurfaceIntersects( posMidR, FSPt, REAL(k_hat,ReKi), REAL(y_hat,ReKi), REAL(z_hat,ReKi), REAL(n_hat,ReKi), rMidR, theta1, theta2, secStatMidR) - CALL GetSectionHstLds( origin, posMidR, k_hat, y_hat, z_hat, rMidR, dRdl, theta1, theta2, dFdlMidR) + CALL GetSectionHstLds_Rec( origin, posMidR, k_hat, x_hat, y_hat, SaMidR, SbMidR, dSadl, dSbdl, FSPt, n_hat, dFdlMidR, secStatMidR) F_B_5pt = (dFdl1 + 4.0*dFdlMidL + 2.0*dFdlMid + 4.0*dFdlMidR + dFdl2) * dl/12.0 @@ -3891,14 +5275,16 @@ RECURSIVE SUBROUTINE RefineElementHstLds( origin, pos1, posMid, pos2, FSPt, r1, END IF IF (refine) THEN ! Recursively refine the load integration if tolerance not met - CALL RefineElementHstLds(origin,pos1,posMidL,posMid,FSPt,r1,rMidL,rMid,0.5*dl,dRdl,secStat1,secStatMidL,secStatMid,k_hat,y_hat,z_hat,n_hat,dFdl1,dFdlMidL,dFdlMid, recurLvl+1, tmp, ErrStat, ErrMsg) - CALL RefineElementHstLds(origin,posMid,posMidR,pos2,FSPt,rMid,rMidR,r2,0.5*dl,dRdl,secStatMid,secStatMidR,secStat2,k_hat,y_hat,z_hat,n_hat,dFdlMid,dFdlMidR,dFdl2, recurLvl+1, F_B_5pt, ErrStat, ErrMsg) + CALL RefineElementHstLds_Rec(origin,pos1,posMidL,posMid,FSPt,Sa1,SaMidL,SaMid,Sb1,SbMidL,SbMid,0.5*dl,dSadl,dSbdl, & + secStat1,secStatMidL,secStatMid,k_hat,x_hat,y_hat,n_hat,dFdl1,dFdlMidL,dFdlMid,recurLvl+1,tmp,ErrStat,ErrMsg) + CALL RefineElementHstLds_Rec(origin,posMid,posMidR,pos2,FSPt,SaMid,SaMidR,Sa2,SbMid,SbMidR,Sb2,0.5*dl,dSadl,dSbdl, & + secStatMid,secStatMidR,secStat2,k_hat,x_hat,y_hat,n_hat,dFdlMid,dFdlMidR,dFdl2,recurLvl+1,F_B_5pt,ErrStat,ErrMsg) F_B_5pt = F_B_5pt + tmp END IF - END SUBROUTINE RefineElementHstLds + END SUBROUTINE RefineElementHstLds_Rec - SUBROUTINE GetEndPlateHstLds(pos0, k_hat, y_hat, z_hat, R, theta1, theta2, F) + SUBROUTINE GetEndPlateHstLds_Cyl(pos0, k_hat, y_hat, z_hat, R, theta1, theta2, F) REAL(ReKi), INTENT( IN ) :: pos0(3) REAL(ReKi), INTENT( IN ) :: k_hat(3) @@ -3962,7 +5348,221 @@ SUBROUTINE GetEndPlateHstLds(pos0, k_hat, y_hat, z_hat, R, theta1, theta2, F) END IF F(4:6) = p%WaveField%WtrDens * g * (My*y_hat + Mz*z_hat) - END SUBROUTINE GetEndPlateHstLds + END SUBROUTINE GetEndPlateHstLds_Cyl + + SUBROUTINE GetEndPlateHstLds_Rec(pos0, k_hat, x_hat, y_hat, Sa, Sb, rFS, nFS, F) + + REAL(ReKi), INTENT( IN ) :: pos0(3) + REAL(ReKi), INTENT( IN ) :: k_hat(3) + REAL(ReKi), INTENT( IN ) :: x_hat(3) + REAL(ReKi), INTENT( IN ) :: y_hat(3) + REAL(ReKi), INTENT( IN ) :: Sa, Sb + REAL(ReKi), INTENT( IN ) :: rFS(3) + REAL(ReKi), INTENT( IN ) :: nFS(3) + REAL(ReKi), INTENT( OUT ) :: F(6) + + INTEGER(IntKi) :: i, numVInWtr + REAL(DbKi) :: z0, s1, s2, h1s1, h1s2, h2s1, h2s2 + REAL(DbKi) :: rv(3,4), Ftmp1(6), Ftmp2(6) + LOGICAL :: vInWtr(4) + + z0 = pos0(3) + ! Global coordinates of the four vertices of the section + rv(:,1) = pos0 + x_hat * (-0.5*Sa) + y_hat * (-0.5*Sb) + rv(:,2) = pos0 + x_hat * ( 0.5*Sa) + y_hat * (-0.5*Sb) + rv(:,3) = pos0 + x_hat * ( 0.5*Sa) + y_hat * ( 0.5*Sb) + rv(:,4) = pos0 + x_hat * (-0.5*Sa) + y_hat * ( 0.5*Sb) + + ! Check for and count vertices in water + numVInWtr = 0 + do i = 1,4 + vInWtr(i) = ( Dot_Product(rv(:,i)-rFS,nFS) <= 0.0 ) + if ( vInWtr(i) ) then + numVInWtr = numVInWtr + 1 + end if + end do + + if (numVInWtr == 0) then ! Dry endplate + F = 0.0 + else if (numVInWtr == 1) then ! Only one vertex in water + if (vInWtr(1)) then + ! Sides 4 & 1 intersects the free surface + h2s1 = Sb * ( 0.5 - dot_product(rFS-rv(:,4),nFS)/dot_product(rv(:,1)-rv(:,4),nFS) ) + h2s2 = -0.5*Sb + h1s1 = -0.5*Sb + h1s2 = -0.5*Sb + s1 = -0.5*Sa + s2 = Sa * (-0.5 + dot_product(rFS-rv(:,1),nFS)/dot_product(rv(:,2)-rv(:,1),nFS) ) + else if (vInWtr(2)) then + ! Sides 1 & 2 intersects the free surface + h2s1 = -0.5*Sb + h2s2 = Sb * (-0.5 + dot_product(rFS-rv(:,2),nFS)/dot_product(rv(:,3)-rv(:,2),nFS) ) + h1s1 = -0.5*Sb + h1s2 = -0.5*Sb + s1 = Sa * (-0.5 + dot_product(rFS-rv(:,1),nFS)/dot_product(rv(:,2)-rv(:,1),nFS) ) + s2 = 0.5*Sa + else if (vInWtr(3)) then + ! Sides 2 & 3 intersects the free surface + h2s1 = 0.5*Sb + h2s2 = 0.5*Sb + h1s1 = 0.5*Sb + h1s2 = Sb * (-0.5 + dot_product(rFS-rv(:,2),nFS)/dot_product(rv(:,3)-rv(:,2),nFS) ) + s1 = Sa * ( 0.5 - dot_product(rFS-rv(:,3),nFS)/dot_product(rv(:,4)-rv(:,3),nFS) ) + s2 = 0.5*Sa + else if (vInWtr(4)) then + ! Sides 3 & 4 intersects the free surface + h2s1 = 0.5*Sb + h2s2 = 0.5*Sb + h1s1 = Sb * ( 0.5 - dot_product(rFS-rv(:,4),nFS)/dot_product(rv(:,1)-rv(:,4),nFS) ) + h1s2 = 0.5*Sb + s1 = -0.5*Sa + s2 = Sa * (0.5 - dot_product(rFS-rv(:,3),nFS)/dot_product(rv(:,4)-rv(:,3),nFS) ) + end if + call GetHstLdsOnTrapezoid(REAL(pos0,DbKi),s1,s2,h1s1,h1s2,h2s1,h2s2,REAL(k_hat,DbKi),REAL(x_hat,DbKi),REAL(y_hat,DbKi),Ftmp1) + F = Ftmp1 + else if (numVInWtr == 2) then ! Two neighboring vertices in water + if (vInWtr(1) .and. vInWtr(2)) then + ! Sides 2 & 4 intersects the free surface + ! Side 1 submerged and side 3 dry + h2s1 = Sb * ( 0.5 - dot_product(rFS-rv(:,4),nFS)/dot_product(rv(:,1)-rv(:,4),nFS) ) + h2s2 = Sb * (-0.5 + dot_product(rFS-rv(:,2),nFS)/dot_product(rv(:,3)-rv(:,2),nFS) ) + h1s1 = -0.5*Sb + h1s2 = -0.5*Sb + s1 = -0.5*Sa + s2 = 0.5*Sa + Ftmp2 = 0.0_DbKi + else if (vInWtr(2) .and. vInWtr(3)) then + ! Sides 1 & 3 intersects the free surface + ! Side 2 submerged and side 4 dry + ! Integrate in two pieces + h2s1 = -0.5*Sb + h2s2 = 0.5*Sb + h1s1 = -0.5*Sb + h1s2 = -0.5*Sb + s1 = Sa * (-0.5 + dot_product(rFS-rv(:,1),nFS)/dot_product(rv(:,2)-rv(:,1),nFS) ) + s2 = Sa * (0.5 - dot_product(rFS-rv(:,3),nFS)/dot_product(rv(:,4)-rv(:,3),nFS) ) + call GetHstLdsOnTrapezoid(REAL(pos0,DbKi),s2,0.5_DbKi*Sa,-0.5_DbKi*Sb,-0.5_DbKi*Sb,0.5_DbKi*Sb,0.5_DbKi*Sb,REAL(k_hat,DbKi),REAL(x_hat,DbKi),REAL(y_hat,DbKi),Ftmp2) + else if (vInWtr(3) .and. vInWtr(4)) then + ! Sides 2 & 4 intersects the free surface + ! Side 3 submerged and side 1 dry + h2s1 = 0.5*Sb + h2s2 = 0.5*Sb + h1s1 = Sb * ( 0.5 - dot_product(rFS-rv(:,4),nFS)/dot_product(rv(:,1)-rv(:,4),nFS) ) + h1s2 = Sb * (-0.5 + dot_product(rFS-rv(:,2),nFS)/dot_product(rv(:,3)-rv(:,2),nFS) ) + s1 = -0.5*Sa + s2 = 0.5*Sa + Ftmp2 = 0.0_DbKi + else if (vInWtr(4) .and. vInWtr(1)) then + ! Sides 1 & 3 intersects the free surface + ! Side 4 submerged and side 2 dry + ! Integrate in two pieces + h2s1 = 0.5*Sb + h2s2 = -0.5*Sb + h1s1 = -0.5*Sb + h1s2 = -0.5*Sb + s1 = Sa * ( 0.5 - dot_product(rFS-rv(:,3),nFS)/dot_product(rv(:,4)-rv(:,3),nFS) ) + s2 = Sa * (-0.5 + dot_product(rFS-rv(:,1),nFS)/dot_product(rv(:,2)-rv(:,1),nFS) ) + call GetHstLdsOnTrapezoid(REAL(pos0,DbKi),-0.5_DbKi*Sa,s1,-0.5_DbKi*Sb,-0.5_DbKi*Sb,0.5_DbKi*Sb,0.5_DbKi*Sb,REAL(k_hat,DbKi),REAL(x_hat,DbKi),REAL(y_hat,DbKi),Ftmp2) + end if + call GetHstLdsOnTrapezoid(REAL(pos0,DbKi),s1,s2,h1s1,h1s2,h2s1,h2s2,REAL(k_hat,DbKi),REAL(x_hat,DbKi),REAL(y_hat,DbKi),Ftmp1) + F = Ftmp1 + Ftmp2 + else if (numVInWtr == 3) then ! Only one vertex out of water + if (.not. vInWtr(1)) then + ! Sides 4 & 1 intersects the free surface + h2s1 = Sb * ( 0.5 - dot_product(rFS-rv(:,4),nFS)/dot_product(rv(:,1)-rv(:,4),nFS) ) + h2s2 = -0.5*Sb + h1s1 = -0.5*Sb + h1s2 = -0.5*Sb + s1 = -0.5*Sa; + s2 = Sa * (-0.5 + dot_product(rFS-rv(:,1),nFS)/dot_product(rv(:,2)-rv(:,1),nFS) ) + else if (.not. vInWtr(2)) then + ! Sides 1 & 2 intersects the free surface + h2s1 = -0.5*Sb + h2s2 = Sb * (-0.5 + dot_product(rFS-rv(:,2),nFS)/dot_product(rv(:,3)-rv(:,2),nFS) ) + h1s1 = -0.5*Sb + h1s2 = -0.5*Sb + s1 = Sa * (-0.5 + dot_product(rFS-rv(:,1),nFS)/dot_product(rv(:,2)-rv(:,1),nFS) ) + s2 = 0.5*Sa + else if (.not. vInWtr(3)) then + ! Sides 2 & 3 intersects the free surface + h2s1 = 0.5*Sb + h2s2 = 0.5*Sb + h1s1 = 0.5*Sb + h1s2 = Sb * (-0.5 + dot_product(rFS-rv(:,2),nFS)/dot_product(rv(:,3)-rv(:,2),nFS) ) + s1 = Sa * ( 0.5 - dot_product(rFS-rv(:,3),nFS)/dot_product(rv(:,4)-rv(:,3),nFS) ) + s2 = 0.5*Sa + else if (.not. vInWtr(4)) then + ! Sides 3 & 4 intersects the free surface + h2s1 = 0.5*Sb + h2s2 = 0.5*Sb + h1s1 = Sb * ( 0.5 - dot_product(rFS-rv(:,4),nFS)/dot_product(rv(:,1)-rv(:,4),nFS) ) + h1s2 = 0.5*Sb + s1 = -0.5*Sa + s2 = Sa * ( 0.5 - dot_product(rFS-rv(:,3),nFS)/dot_product(rv(:,4)-rv(:,3),nFS) ) + end if + call GetHstLdsOnTrapezoid(REAL(pos0,DbKi),s1,s2,h1s1,h1s2,h2s1,h2s2,REAL(k_hat,DbKi),REAL(x_hat,DbKi),REAL(y_hat,DbKi),Ftmp1) + F(1:3) = -p%WaveField%WtrDens*g*z0*Sa*Sb*k_hat - Ftmp1(1:3) + F(4:6) = p%WaveField%WtrDens*g*(Sa**3*Sb*x_hat(3)*y_hat-Sa*Sb**3*y_hat(3)*x_hat)/12.0 - Ftmp1(4:6) + else if (numVInWtr == 4) then ! Submerged endplate + F(1:3) = -p%WaveField%WtrDens*g*z0*Sa*Sb*k_hat + F(4:6) = p%WaveField%WtrDens*g*(Sa**3*Sb*x_hat(3)*y_hat-Sa*Sb**3*y_hat(3)*x_hat)/12.0 + end if + + END SUBROUTINE GetEndPlateHstLds_Rec + + SUBROUTINE GetHstLdsOnTrapezoid(pos0, s1, s2, h1s1, h1s2, h2s1, h2s2, k_hat, x_hat, y_hat, F) + REAL(DbKi), INTENT( IN ) :: pos0(3) + REAL(DbKi), INTENT( IN ) :: s1, s2, h1s1, h1s2, h2s1, h2s2 + REAL(DbKi), INTENT( IN ) :: k_hat(3), x_hat(3), y_hat(3) + REAL(DbKi), INTENT( OUT ) :: F(6) + + REAL(DbKi) :: z0 + REAL(DbKi) :: ds, ds2, ds3, ds4 + REAL(DbKi) :: p1, q1, p2, q2 + REAL(DbKi) :: dp, dp2, dp3 + REAL(DbKi) :: dq, dq2, dq3 + REAL(DbKi) :: dpq, dp2q, dpq2, tmp + + if (EqualRealNos(s1,s2)) then + F = 0.0 + return; + end if + + z0 = pos0(3) + ds = s2 -s1 + ds2 = s2**2-s1**2 + ds3 = s2**3-s1**3 + ds4 = s2**4-s1**4 + p1 = (h1s2-h1s1)/ds + q1 = (h1s1*s2-h1s2*s1)/ds + p2 = (h2s2-h2s1)/ds + q2 = (h2s1*s2-h2s2*s1)/ds + dp = p2-p1 + dq = q2-q1 + dp2 = p2**2-p1**2 + dq2 = q2**2-q1**2 + dp3 = p2**3-p1**3 + dq3 = q2**3-q1**3 + dpq = p2*q2-p1*q1 + dp2q = p2**2*q2-p1**2*q1 + dpq2 = p2*q2**2-p1*q1**2 + tmp = 3.0*dp2*ds4+8.0*dpq*ds3+6.0*dq2*ds2 + + F(1:3) = -( 0.5*z0*(dp*ds2+2.0*dq*ds) & + +x_hat(3)/6.0*(2.0*dp*ds3+3.0*dq*ds2) & + +y_hat(3)/6.0*(dp2*ds3+3.0*dpq*ds2+3.0*(q2**2-q1**2)*ds) & + ) * k_hat + + F(4:6) = -( z0/6.0*(dp2*ds3+3.0*dpq*ds2+3.0*dq2*ds) & + +x_hat(3)/24.0*tmp & + +y_hat(3)/12.0*(dp3*ds4+4.0*dp2q*ds3+6.0*dpq2*ds2+4.0*dq3*ds) )*x_hat & + +( z0/6.0*(2.0*dp*ds3+3.0*dq*ds2) & + +x_hat(3)/12.0*(3.0*dp*ds4+4.0*dq*ds3) & + +y_hat(3)/24.0*tmp )*y_hat + + F = p%WaveField%WtrDens * g * F + + END SUBROUTINE GetHstLdsOnTrapezoid SUBROUTINE getElementHstLds_Mod1( Time, pos1, pos2, Zeta1, Zeta2, k_hat, r1, r2, dl, alphaIn, Is1stElement, F_B0, F_B1, F_B2, ErrStat, ErrMsg ) @@ -4128,7 +5728,7 @@ SUBROUTINE YawMember(member, PtfmRefY, ErrStat, ErrMsg) Integer(IntKi), intent( out) :: ErrStat Character(*), intent( out) :: ErrMsg - Real(ReKi) :: k(3) + Real(ReKi) :: k(3), x_hat(3), y_hat(3) Real(ReKi) :: kkt(3,3) Real(ReKi) :: Ak(3,3) Integer(IntKi) :: ErrStat2 @@ -4151,6 +5751,18 @@ SUBROUTINE YawMember(member, PtfmRefY, ErrStat, ErrMsg) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) member%Ak = Ak + IF (member%MSecGeom == MSecGeom_Rec) THEN + + call hiFrameTransform(h2i,PtfmRefY,member%x_hat,x_hat,ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + member%x_hat = x_hat + + call hiFrameTransform(h2i,PtfmRefY,member%y_hat,y_hat,ErrStat2,ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + member%y_hat = y_hat + + END IF + END SUBROUTINE YawMember SUBROUTINE YawJoint(JointNo,PtfmRefY,AM_End,An_End,DP_Const_End,I_MG_End,ErrStat,ErrMsg) @@ -4182,6 +5794,119 @@ SUBROUTINE YawJoint(JointNo,PtfmRefY,AM_End,An_End,DP_Const_End,I_MG_End,ErrStat END SUBROUTINE YawJoint + SUBROUTINE getMemBallastHiPt(member,z_hi, ErrStat, ErrMsg) + ! This subroutine returns the highest point of a member's internal ballast + Type(Morison_MemberType), intent(in ) :: member + Real(ReKi), intent( out) :: z_hi + Integer(IntKi), intent( out) :: ErrStat + Character(*), intent( out) :: ErrMsg + + Integer(IntKi) :: N, elemNo + Real(ReKi) :: CMatrix0(3,3), CMatrix(3,3) + Real(ReKi) :: k_hat(3), x_hat(3), y_hat(3), z_hat(3) + Real(ReKi) :: l, rIn, SaIn, SbIn, z0, pos1(3), pos2(3) + + Character(*), Parameter :: RoutineName = 'getMemBallastHiPt' + + ErrStat = ErrId_None + ErrMsg = "" + + IF (member%memfloodstatus == 0) THEN ! Unflooded member + CALL SetErrStat(ErrId_Fatal," Coding error: getMemBallastHiPt should never be called with an unflooded member with memfloodstatus = 0. ",ErrStat,ErrMsg,RoutineName ) + RETURN + END IF + + N = member%NElements + + IF (member%MSecGeom == MSecGeom_Cyl) THEN + pos1 = m%DispNodePosHst(:,member%NodeIndx(1)) + pos2 = m%DispNodePosHst(:,member%NodeIndx(2)) + k_hat = pos2-pos1 + k_hat = k_hat / SQRT(Dot_Product(k_hat,k_hat)) + CALL GetSectionUnitVectors_Cyl( k_hat, y_hat, z_hat ) + ! Check the starting section + rIn = member%Rin(1) + z_hi = pos1(3) + rIn * z_hat(3) + IF (member%memfloodstatus == 1) THEN ! Fully flooded, check other end + pos1 = m%DispNodePosHst(:,member%NodeIndx(N )) + pos2 = m%DispNodePosHst(:,member%NodeIndx(N+1)) + k_hat = pos2-pos1 + k_hat = k_hat / SQRT(Dot_Product(k_hat,k_hat)) + CALL GetSectionUnitVectors_Cyl( k_hat, y_hat, z_hat ) + ! Check the ending section + rIn = member%Rin(N+1) + z_hi = MAX( pos2(3) + rIn * z_hat(3), z_hi) + ELSE IF (member%memfloodstatus == 2) THEN ! Partially flooded, check the end of the flooded section + elemNo = member%elem_fill + pos1 = m%DispNodePosHst(:,member%NodeIndx(elemNo )) + pos2 = m%DispNodePosHst(:,member%NodeIndx(elemNo+1)) + k_hat = pos2-pos1 + k_hat = k_hat / SQRT(Dot_Product(k_hat,k_hat)) + CALL GetSectionUnitVectors_Cyl( k_hat, y_hat, z_hat ) + pos2 = pos1 + member%h_fill * k_hat ! End of flooded section + l = member%h_fill/member%dl + rIn = member%Rin(elemNo) * (1.0-l) + member%Rin(elemNo+1) * l + z_hi = MAX( pos2(3) + rIn * z_hat(3), z_hi) + END IF + ELSE IF (member%MSecGeom == MSecGeom_Rec) THEN + ! DirCos matrix of undisplaced member + CALL Morison_DirCosMtrx( u%Mesh%Position(:,member%NodeIndx(1 )), u%Mesh%Position(:,member%NodeIndx(N+1)), member%MSpinOrient, CMatrix0 ) + ! Check the vertices of the starting section + pos1 = m%DispNodePosHst(:,member%NodeIndx(1)) + pos2 = m%DispNodePosHst(:,member%NodeIndx(2)) + z0 = pos1(3) + CMatrix = matmul(transpose(u%Mesh%Orientation(:,:,member%NodeIndx(1 ))),CMatrix0) + CALL GetSectionUnitVectors_Rec( CMatrix, x_hat, y_hat ) + SaIn = member%SaIn(1) + SbIn = member%SbIn(1) + z_hi = z0 - 0.5*SaIn*x_hat(3) - 0.5*SbIn*y_hat(3) + z_hi = MAX(z0 + 0.5*SaIn*x_hat(3) - 0.5*SbIn*y_hat(3), z_hi) + z_hi = MAX(z0 + 0.5*SaIn*x_hat(3) + 0.5*SbIn*y_hat(3), z_hi) + z_hi = MAX(z0 - 0.5*SaIn*x_hat(3) + 0.5*SbIn*y_hat(3), z_hi) + IF (member%memfloodstatus == 1) THEN ! Fully flooded, check other end + ! Check the vertices of the ending section + pos1 = m%DispNodePosHst(:,member%NodeIndx(N )) + pos2 = m%DispNodePosHst(:,member%NodeIndx(N+1)) + z0 = pos2(3) + CMatrix = matmul(transpose(u%Mesh%Orientation(:,:,member%NodeIndx(N+1))),CMatrix0) + CALL GetSectionUnitVectors_Rec( CMatrix, x_hat, y_hat ) + SaIn = member%SaIn(N+1) + SbIn = member%SbIn(N+1) + z_hi = MAX(z0 - 0.5*SaIn*x_hat(3) - 0.5*SbIn*y_hat(3), z_hi) + z_hi = MAX(z0 + 0.5*SaIn*x_hat(3) - 0.5*SbIn*y_hat(3), z_hi) + z_hi = MAX(z0 + 0.5*SaIn*x_hat(3) + 0.5*SbIn*y_hat(3), z_hi) + z_hi = MAX(z0 - 0.5*SaIn*x_hat(3) + 0.5*SbIn*y_hat(3), z_hi) + ELSE IF (member%memfloodstatus == 2) THEN ! Partially flooded, check the end of the flooded section + elemNo = member%elem_fill + pos1 = m%DispNodePosHst(:,member%NodeIndx(elemNo )) + pos2 = m%DispNodePosHst(:,member%NodeIndx(elemNo+1)) + if ( member%h_fill>0.5*member%dl ) then + CMatrix = matmul(transpose(u%Mesh%Orientation(:,:,member%NodeIndx(elemNo+1))),CMatrix0) + else + CMatrix = matmul(transpose(u%Mesh%Orientation(:,:,member%NodeIndx(elemNo ))),CMatrix0) + end if + CALL GetSectionUnitVectors_Rec( CMatrix, x_hat, y_hat ) + k_hat = Cross_Product(x_hat,y_hat) + pos2 = pos1 + member%h_fill * k_hat ! End of filled section + z0 = pos2(3) + l = member%h_fill/member%dl + SaIn = member%SaIn(elemNo) * (1.0-l) + member%SaIn(elemNo+1) * l + SbIn = member%SbIn(elemNo) * (1.0-l) + member%SbIn(elemNo+1) * l + z_hi = MAX(z0 - 0.5*SaIn*x_hat(3) - 0.5*SbIn*y_hat(3), z_hi) + z_hi = MAX(z0 + 0.5*SaIn*x_hat(3) - 0.5*SbIn*y_hat(3), z_hi) + z_hi = MAX(z0 + 0.5*SaIn*x_hat(3) + 0.5*SbIn*y_hat(3), z_hi) + z_hi = MAX(z0 - 0.5*SaIn*x_hat(3) + 0.5*SbIn*y_hat(3), z_hi) + END IF + END IF + END SUBROUTINE getMemBallastHiPt + + logical function Failed() + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + Failed = ErrStat >= AbortErrLev + !if (Failed) then + ! call FailCleanup() + !endif + end function Failed END SUBROUTINE Morison_CalcOutput !---------------------------------------------------------------------------------------------------------------------------------- diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt index 5276e6dfa3..a6b4a536a3 100644 --- a/modules/hydrodyn/src/Morison.txt +++ b/modules/hydrodyn/src/Morison.txt @@ -15,6 +15,8 @@ include Registry_NWTC_Library.txt usefrom SeaSt_WaveField.txt # +param Morison/Morison - INTEGER MSecGeom_Cyl - 1 - "MSecGeom = 1 [circular member cross section]" - +param Morison/Morison - INTEGER MSecGeom_Rec - 2 - "MSecGeom = 2 [rectangular member cross section]" - # typedef Morison/Morison Morison_JointType INTEGER JointID - - - "User-specified integer ID for the given joint" - typedef ^ ^ ReKi Position {3} - - "Undisplaced location of the joint in the platform coordinate system" m @@ -23,15 +25,20 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER JointOvrlp - - - "Joint overlap code [Unused" - typedef ^ ^ INTEGER NConnections - - - "Number of members connecting to this joint" - typedef ^ ^ INTEGER ConnectionList {50} - - "List of Members connected to this joint. The member index is what is stored, not the Member ID" - -typedef ^ Morison_MemberPropType INTEGER PropSetID - - - "User-specified integer ID for this group of properties" - +typedef ^ Morison_MemberPropTypeCyl INTEGER PropSetID - - - "User-specified integer ID for this group of properties" - typedef ^ ^ ReKi PropD - - - "Diameter" m typedef ^ ^ ReKi PropThck - - - "Wall thickness" m +typedef ^ Morison_MemberPropTypeRec INTEGER PropSetID - - - "User-specified integer ID for this group of properties" - +typedef ^ ^ ReKi PropA - - - "Length of side A" m +typedef ^ ^ ReKi PropB - - - "Length of side B" m +typedef ^ ^ ReKi PropThck - - - "Wall thickness" m typedef ^ Morison_FilledGroupType INTEGER FillNumM - - - "Number of members in the Fill Group" - typedef ^ ^ INTEGER FillMList {:} - - "List of Member IDs for the members in this fill group" - typedef ^ ^ ReKi FillFSLoc - - - "The free-surface location (in Z) for this fill group" m typedef ^ ^ CHARACTER(80) FillDensChr - - - "String version of the Fill density [can be DEFAULT which sets the fill density to WtrDens]" kg/m^3 typedef ^ ^ ReKi FillDens - - - "Numerical fill density" kg/m^3 -typedef ^ Morison_CoefDpths ReKi Dpth - - - "Depth location for these depth-based hydrodynamic coefs" m +typedef ^ ^ LOGICAL IsOpen - - - "Whether the internal ballast is open to the outside through the open end of members buried in the seabed" - +typedef ^ Morison_CoefDpthsCyl ReKi Dpth - - - "Depth location for these depth-based hydrodynamic coefs" m typedef ^ ^ ReKi DpthCd - - - "Depth-based drag coef" - typedef ^ ^ ReKi DpthCdMG - - - "Depth-based drag coef for marine growth" - typedef ^ ^ ReKi DpthCa - - - "Depth-based Ca" - @@ -47,6 +54,26 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi DpthCb - - - "Simple model hydrostatic/buoyancy load coefficient" - typedef ^ ^ ReKi DpthCbMg - - - "Simple model hydrostatic/buoyancy load coefficient for marine growth" - typedef ^ ^ LOGICAL DpthMCF - - - "Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model" - +typedef ^ Morison_CoefDpthsRec ReKi Dpth - - - "Depth location for these depth-based hydrodynamic coefs" m +typedef ^ ^ ReKi DpthCdA - - - "Depth-based drag coef" - +typedef ^ ^ ReKi DpthCdAMG - - - "Depth-based drag coef for marine growth" - +typedef ^ ^ ReKi DpthCdB - - - "Depth-based drag coef" - +typedef ^ ^ ReKi DpthCdBMG - - - "Depth-based drag coef for marine growth" - +typedef ^ ^ ReKi DpthCaA - - - "Depth-based Ca" - +typedef ^ ^ ReKi DpthCaAMG - - - "Depth-based Ca for marine growth" - +typedef ^ ^ ReKi DpthCaB - - - "Depth-based Ca" - +typedef ^ ^ ReKi DpthCaBMG - - - "Depth-based Ca for marine growth" - +typedef ^ ^ ReKi DpthCp - - - "Depth-based Cp" - +typedef ^ ^ ReKi DpthCpMG - - - "Depth-based Cp for marine growth" - +typedef ^ ^ ReKi DpthAxCd - - - "Depth-based Axial Cd" - +typedef ^ ^ ReKi DpthAxCdMG - - - "Depth-based Axial Cd for marine growth" - +typedef ^ ^ ReKi DpthAxCa - - - "Depth-based Axial Ca" - +typedef ^ ^ ReKi DpthAxCaMG - - - "Depth-based Axial Ca for marine growth" - +typedef ^ ^ ReKi DpthAxCp - - - "Depth-based Axial Cp" - +typedef ^ ^ ReKi DpthAxCpMG - - - "Depth-based Axial Cp for marine growth" - +typedef ^ ^ ReKi DpthCb - - - "Simple model hydrostatic/buoyancy load coefficient" - +typedef ^ ^ ReKi DpthCbMg - - - "Simple model hydrostatic/buoyancy load coefficient for marine growth" - +typedef ^ ^ LOGICAL DpthMCF - - - "Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model" - typedef ^ Morison_AxialCoefType INTEGER AxCoefID - - - "User-supplied integer ID for this set of Axial coefs" - typedef ^ ^ ReKi AxCd - - - "Axial Cd" - typedef ^ ^ ReKi AxCa - - - "Axial Ca" - @@ -65,6 +92,8 @@ typedef ^ ^ INTEGER typedef ^ ^ INTEGER MPropSetID2 - - - "Property set ID for the end of this member" - typedef ^ ^ INTEGER MPropSetID1Indx - - - "Index into the Property table for the start of this member" - typedef ^ ^ INTEGER MPropSetID2Indx - - - "Index into the Property table for the end of this member" - +typedef ^ ^ INTEGER MSecGeom - - - "Member cross section geometry. 1: Circular. 2: Rectangular" - +typedef ^ ^ ReKi MSpinOrient - - - "Member orientation in terms of rotation angle about the member axis" rad typedef ^ ^ ReKi MDivSize - - - "User-specified desired member discretization size for the final element" m typedef ^ ^ INTEGER MCoefMod - - - "Which coef. model is being used for this member [1=simple, 2=depth-based, 3=member-based]" - typedef ^ ^ INTEGER MHstLMod - - - "Which hydrostatic model is being used for this member [1=column-type, 2=ship-type]" - @@ -101,19 +130,36 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi k {3} - - "unit vector of the member's orientation (may be changed to per-element once additional flexibility is accounted for in HydroDyn)" m typedef ^ ^ ReKi kkt {3}{3} - - "matrix of matmul(k_hat, transpose(k_hat)" - typedef ^ ^ ReKi Ak {3}{3} - - "matrix of I - kkt" - +typedef ^ ^ ReKi x_hat {3} - - "unit vector of rectangular member local x-axis aligned with Side A" - +typedef ^ ^ ReKi y_hat {3} - - "unit vector of rectangular member local y-axis aligned with Side B" - typedef ^ ^ ReKi R {:} - - "outer member radius at each node" m typedef ^ ^ ReKi RMG {:} - - "radius at each node including marine growth" m typedef ^ ^ ReKi RMGB {:} - - "radius at each node including marine growth scaled by sqrt(Cb)" m typedef ^ ^ ReKi Rin {:} - - "inner member radius at node, equivalent to radius of water ballast at this node if filled" m +typedef ^ ^ ReKi Sa {:} - - "outer member side A length at each node" m +typedef ^ ^ ReKi SaMG {:} - - "side A length with marine growth at each node" m +typedef ^ ^ ReKi SaMGB {:} - - "side A length with marine growth scaled by sqrt(Cb)" m +typedef ^ ^ ReKi Sain {:} - - "inner member side A length at node, equivalent to width of water ballast at this node if filled" m +typedef ^ ^ ReKi Sb {:} - - "outer member side B length at each node" m +typedef ^ ^ ReKi SbMG {:} - - "side B length with marine growth at each node" m +typedef ^ ^ ReKi SbMGB {:} - - "side B length with marine growth scaled by sqrt(Cb)" m +typedef ^ ^ ReKi Sbin {:} - - "inner member side B length at node, equivalent to width of water ballast at this node if filled" m typedef ^ ^ ReKi tMG {:} - - "Nodal thickness with marine growth (of member at node location)" m typedef ^ ^ ReKi MGdensity {:} - - "Nodal density of marine growth" kg/m^3 typedef ^ ^ ReKi dRdl_mg {:} - - "taper dr/dl of outer surface including marine growth of each element" - typedef ^ ^ ReKi dRdl_mg_b {:} - - "taper dr/dl of outer surface including marine growth of each element with scaling of sqrt(Cb)" - typedef ^ ^ ReKi dRdl_in {:} - - "taper dr/dl of interior surface of each element" - +typedef ^ ^ ReKi dSadl_mg {:} - - "taper dSa/dl of outer surface including marine growth of each element" - +typedef ^ ^ ReKi dSadl_mg_b {:} - - "taper dSa/dl of outer surface including marine growth of each element with scaling of sqrt(Cb)" - +typedef ^ ^ ReKi dSadl_in {:} - - "taper dSa/dl of interior surface of each element" - +typedef ^ ^ ReKi dSbdl_mg {:} - - "taper dSb/dl of outer surface including marine growth of each element" - +typedef ^ ^ ReKi dSbdl_mg_b {:} - - "taper dSb/dl of outer surface including marine growth of each element with scaling of sqrt(Cb)" - +typedef ^ ^ ReKi dSbdl_in {:} - - "taper dSb/dl of interior surface of each element" - typedef ^ ^ ReKi Vinner - - - "Member volume without marine growth" m^3 typedef ^ ^ ReKi Vouter - - - "Member volume including marine growth" m^3 typedef ^ ^ ReKi Vballast - - - "Member ballast volume" m^3 typedef ^ ^ ReKi Vsubmerged - - - "Submerged volume corresponding to portion of Member in the water" m^3 +typedef ^ ^ IntKi elem_fill - - - "Last (partially) filled element of the member" - typedef ^ ^ ReKi l_fill - - - "fill length along member axis from start node 1" m typedef ^ ^ ReKi h_fill - - - "fill length of partially flooded element" m typedef ^ ^ ReKi z_overfill - - - "if member is fully filled, the head height of the fill pressure at the end node N+1. Zero if member is partially filled." m @@ -127,6 +173,10 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi alpha_fb_star {:} - - "load distribution factor for each element after adjusting alpha_fb for node reference depths" - typedef ^ ^ ReKi Cd {:} - - "Member Cd at each node" - typedef ^ ^ ReKi Ca {:} - - "Member Ca at each node" - +typedef ^ ^ ReKi CdA {:} - - "Member Cd normal to side A at each node" - +typedef ^ ^ ReKi CaA {:} - - "Member Ca normal to side A at each node" - +typedef ^ ^ ReKi CdB {:} - - "Member Cd normal to side B at each node" - +typedef ^ ^ ReKi CaB {:} - - "Member Ca normal to side B at each node" - typedef ^ ^ ReKi Cp {:} - - "Member Cp at each node" - typedef ^ ^ ReKi AxCd {:} - - "Member axial Cd at each node" - typedef ^ ^ ReKi AxCa {:} - - "Member axial Ca at each node" - @@ -140,6 +190,10 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi I_lfb_u {:} - - "axial moment of inertia of flooded ballast in upper portion of each element" kg-m^2 typedef ^ ^ ReKi I_rfb_l {:} - - "radial moment of inertia of flooded ballast in lower portion of each element" kg-m^2 typedef ^ ^ ReKi I_rfb_u {:} - - "radial moment of inertia of flooded ballast in upper portion of each element" kg-m^2 +typedef ^ ^ ReKi I_xfb_l {:} - - "element local x-moment of inertia of flooded ballast in lower portion of each element" kg-m^2 +typedef ^ ^ ReKi I_xfb_u {:} - - "element local x-moment of inertia of flooded ballast in upper portion of each element" kg-m^2 +typedef ^ ^ ReKi I_yfb_l {:} - - "element local y-moment of inertia of flooded ballast in lower portion of each element" kg-m^2 +typedef ^ ^ ReKi I_yfb_u {:} - - "element local y-moment of inertia of flooded ballast in upper portion of each element" kg-m^2 typedef ^ ^ ReKi m_mg_l {:} - - "mass of marine growth in lower portion of each element" kg typedef ^ ^ ReKi m_mg_u {:} - - "mass of marine growth in upper portion of each element" kg typedef ^ ^ ReKi h_cmg_l {:} - - "distance to marine growth centroid from node point in lower portion of each element" m @@ -148,20 +202,30 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi I_lmg_u {:} - - "axial moment of inertia of marine growth in upper portion of each element" kg-m^2 typedef ^ ^ ReKi I_rmg_l {:} - - "radial moment of inertia of marine growth in lower portion of each element" kg-m^2 typedef ^ ^ ReKi I_rmg_u {:} - - "radial moment of inertia of flooded ballast in upper portion of each element" kg-m^2 -typedef ^ ^ ReKi Cfl_fb {:} - - "axial force constant due to flooded ballast, for each element" N -typedef ^ ^ ReKi Cfr_fb {:} - - "radial force constant due to flooded ballast, for each element" N -typedef ^ ^ ReKi CM0_fb {:} - - "moment constant due to flooded ballast, for each element about lower node" Nm -typedef ^ ^ ReKi MGvolume - - - "Volume of marine growth material for this member/element" m^3 -typedef ^ ^ ReKi MDivSize - - - "User-requested final element length (actual length may vary from this request)" m -typedef ^ ^ INTEGER MCoefMod - - - "Coefs model for member: 1 = simple, 2 =depth, 3 = member-based " - -typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "If MCoefMod=3, then this is the index for the member's coefs in the master Member Coefs Table" - -typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "If this member is part of a fill group, this is the index into the master fill group table, if not = -1" - -typedef ^ ^ INTEGER MHstLMod - - - "Hydrostatic model for member [1=column-type, 2=ship-type]" - -typedef ^ ^ ReKi FillFSLoc - - - "Z-location of the filled free-surface" m -typedef ^ ^ ReKi FillDens - - - "Filled fluid density" kg/m^3 -typedef ^ ^ LOGICAL PropPot - - - "Is this element/member modeled with potential flow theory T/F" - -typedef ^ ^ LOGICAL PropMCF - - - "Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model" - -typedef ^ ^ LOGICAL Flipped - - - "Was the member flipped in a reordering event? Need to know this to get the correct normal vector to the ends" - +typedef ^ ^ ReKi I_xmg_l {:} - - "element local x-moment of inertia of marine growth in lower portion of each element" kg-m^2 +typedef ^ ^ ReKi I_xmg_u {:} - - "element local x-moment of inertia of marine growth in upper portion of each element" kg-m^2 +typedef ^ ^ ReKi I_ymg_l {:} - - "element local y-moment of inertia of marine growth in lower portion of each element" kg-m^2 +typedef ^ ^ ReKi I_ymg_u {:} - - "element local y-moment of inertia of marine growth in upper portion of each element" kg-m^2 +#typedef ^ ^ ReKi Cfl_fb {:} - - "axial force constant due to flooded ballast, for each element" N +#typedef ^ ^ ReKi Cfr_fb {:} - - "radial force constant due to flooded ballast, for each element" N +#typedef ^ ^ ReKi Cfx_fb {:} - - "element local x-force constant due to flooded ballast, for each element" N +#typedef ^ ^ ReKi Cfy_fb {:} - - "element local y-force constant due to flooded ballast, for each element" N +#typedef ^ ^ ReKi CM0_fb {:} - - "moment constant due to flooded ballast, for each element about lower node" Nm +#typedef ^ ^ ReKi NodeWBallast {:} - - "Internal ballast weight associated with each node" N +#typedef ^ ^ ReKi NodeWhcBallast {:} - - "Internal ballast weight associated with each node times distance from node to ballast CG" Nm +typedef ^ ^ ReKi MGvolume - - - "Volume of marine growth material for this member/element" m^3 +typedef ^ ^ INTEGER MSecGeom - - - "Member cross section geometry. 1: Circular. 2: Rectangular" - +typedef ^ ^ ReKi MSpinOrient - - - "Member orientation in terms of rotation angle about the member axis" rad +typedef ^ ^ ReKi MDivSize - - - "User-requested final element length (actual length may vary from this request)" m +typedef ^ ^ INTEGER MCoefMod - - - "Coefs model for member: 1 = simple, 2 =depth, 3 = member-based " - +typedef ^ ^ INTEGER MmbrCoefIDIndx - - - "If MCoefMod=3, then this is the index for the member's coefs in the master Member Coefs Table" - +typedef ^ ^ INTEGER MmbrFilledIDIndx - - - "If this member is part of a fill group, this is the index into the master fill group table, if not = -1" - +typedef ^ ^ INTEGER MHstLMod - - - "Hydrostatic model for member [1=column-type, 2=ship-type]" - +typedef ^ ^ ReKi FillFSLoc - - - "Z-location of the filled free-surface" m +typedef ^ ^ ReKi FillDens - - - "Filled fluid density" kg/m^3 +typedef ^ ^ LOGICAL PropPot - - - "Is this element/member modeled with potential flow theory T/F" - +typedef ^ ^ LOGICAL PropMCF - - - "Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model" - +typedef ^ ^ LOGICAL Flipped - - - "Was the member flipped in a reordering event? Need to know this to get the correct normal vector to the ends" - # typedef ^ Morison_MemberLoads ReKi F_D {:}{:} - - "Member-based (side-effects) Nodal viscous drag loads at time t" - typedef ^ ^ ReKi F_I {:}{:} - - "Member-based (side-effects) Nodal inertial loads at time t" - @@ -175,36 +239,74 @@ typedef ^ ^ ReKi 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 ^ Morison_CoefMembers INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - -typedef ^ ^ ReKi MemberCd1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCd2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCdMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCdMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCa1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCa2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCaMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCaMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCp1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCd1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCd2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCdMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCdMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCa1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCa2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCaMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCaMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCp1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCp2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCpMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberAxCpMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCb1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCb2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCbMG1 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ ReKi MemberCbMG2 - - - "Member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - -typedef ^ ^ LOGICAL MemberMCF - - - "Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model" - +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)" - +typedef ^ ^ ReKi MemberCd2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdMG1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdMG2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCa1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCa2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaMG1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaMG2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCp1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCp2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCpMG1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCpMG2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCd1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCd2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCdMG1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCdMG2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCa1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCa2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCaMG1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCaMG2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCp1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCp2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCpMG1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCpMG2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCb1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCb2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCbMG1 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCbMG2 - - - "Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ LOGICAL MemberMCF - - - "Flag T/F for whether the cylindrical member is modeled with the MacCamy-Fuchs diffraction model" - +typedef ^ Morison_CoefMembersRec INTEGER MemberID - - - "User-specified integer id for the Member-based coefs" - +typedef ^ ^ ReKi MemberCdA1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdA2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdAMG1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdAMG2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdB1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdB2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdBMG1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCdBMG2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaA1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaA2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaAMG1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaAMG2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaB1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaB2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaBMG1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCaBMG2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCp1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCp2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCpMG1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCpMG2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCd1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCd2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCdMG1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCdMG2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCa1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCa2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCaMG1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCaMG2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCp1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCp2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCpMG1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberAxCpMG2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCb1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCb2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCbMG1 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ ReKi MemberCbMG2 - - - "Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end)" - +typedef ^ ^ LOGICAL MemberMCF - - - "Flag T/F for whether the rectangular member is modeled with the MacCamy-Fuchs diffraction model" - typedef ^ Morison_MGDepthsType ReKi MGDpth - - - "Marine growth depth location for these properties" m typedef ^ ^ ReKi MGThck - - - "Marine growth thickness" m typedef ^ ^ ReKi MGDens - - - "Marine growth density" kg/m^3 @@ -232,27 +334,52 @@ typedef ^ ^ Morison_Joi typedef ^ ^ Morison_NodeType Nodes {:} - - "Array of simulation node (some correspond to user-specified joints, others are created by software)" - typedef ^ ^ INTEGER NAxCoefs - - - "Number of axial Coefs entries in input file table" - typedef ^ ^ Morison_AxialCoefType AxialCoefs {:} - - "List of axial coefs" - -typedef ^ ^ INTEGER NPropSets - - - "Number of member property sets" - -typedef ^ ^ Morison_MemberPropType MPropSets {:} - - "List of Member property sets" - -typedef ^ ^ ReKi SimplCd - - - "Simple model drag coef" - -typedef ^ ^ ReKi SimplCdMG - - - "Simple model drag coef for marine growth" - -typedef ^ ^ ReKi SimplCa - - - "Simple model Ca" - -typedef ^ ^ ReKi SimplCaMG - - - "Simple model Ca for marine growth" - -typedef ^ ^ ReKi SimplCp - - - "Simple model Cp" - -typedef ^ ^ ReKi SimplCpMG - - - "Simple model Cp for marine growth" - -typedef ^ ^ ReKi SimplAxCd - - - "Simple model Axial Cd" - -typedef ^ ^ ReKi SimplAxCdMG - - - "Simple model Axial Cd for marine growth" - -typedef ^ ^ ReKi SimplAxCa - - - "Simple model Axial Ca" - -typedef ^ ^ ReKi SimplAxCaMG - - - "Simple model Axial Ca for marine growth" - -typedef ^ ^ ReKi SimplAxCp - - - "Simple model Axial Cp" - -typedef ^ ^ ReKi SimplAxCpMG - - - "Simple model Axial Cp for marine growth" - -typedef ^ ^ ReKi SimplCb - - - "Simple model hydrostatic/buoyancy load coefficient" - -typedef ^ ^ ReKi SimplCbMg - - - "Simple model hydrostatic/buoyancy load coefficient for marine growth" - -typedef ^ ^ LOGICAL SimplMCF - - - "Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model" - -typedef ^ ^ INTEGER NCoefDpth - - - "" - -typedef ^ ^ Morison_CoefDpths CoefDpths {:} - - "" - -typedef ^ ^ INTEGER NCoefMembers - - - "" - -typedef ^ ^ Morison_CoefMembers CoefMembers {:} - - "" - +typedef ^ ^ INTEGER NPropSetsCyl - - - "Number of cylindrical member property sets" - +typedef ^ ^ Morison_MemberPropTypeCyl MPropSetsCyl {:} - - "List of cylindrical member property sets" - +typedef ^ ^ INTEGER NPropSetsRec - - - "Number of rectangular member property sets" - +typedef ^ ^ Morison_MemberPropTypeRec MPropSetsRec {:} - - "List of rectangular member property sets" - +typedef ^ ^ ReKi SimplCd - - - "Simple model drag coef for cylindrical members" - +typedef ^ ^ ReKi SimplCdMG - - - "Simple model drag coef for cylindrical members with marine growth" - +typedef ^ ^ ReKi SimplCa - - - "Simple model Ca for cylindrical members" - +typedef ^ ^ ReKi SimplCaMG - - - "Simple model Ca for cylindrical members with marine growth" - +typedef ^ ^ ReKi SimplCp - - - "Simple model Cp for cylindrical members" - +typedef ^ ^ ReKi SimplCpMG - - - "Simple model Cp for cylindrical members with marine growth" - +typedef ^ ^ ReKi SimplAxCd - - - "Simple model Axial Cd for cylindrical members" - +typedef ^ ^ ReKi SimplAxCdMG - - - "Simple model Axial Cd for cylindrical members with marine growth" - +typedef ^ ^ ReKi SimplAxCa - - - "Simple model Axial Ca for cylindrical members" - +typedef ^ ^ ReKi SimplAxCaMG - - - "Simple model Axial Ca for cylindrical members with marine growth" - +typedef ^ ^ ReKi SimplAxCp - - - "Simple model Axial Cp for cylindrical members" - +typedef ^ ^ ReKi SimplAxCpMG - - - "Simple model Axial Cp for cylindrical members with marine growth" - +typedef ^ ^ ReKi SimplCb - - - "Simple model hydrostatic/buoyancy load coefficient for cylindrical members" - +typedef ^ ^ ReKi SimplCbMg - - - "Simple model hydrostatic/buoyancy load coefficient for cylindrical members with marine growth" - +typedef ^ ^ LOGICAL SimplMCF - - - "Flag T/F for whether the cylindrical member is modeled with the MacCamy-Fuchs diffraction model" - +typedef ^ ^ ReKi SimplRecCdA - - - "Simple model drag coef for rectangular members normal to side A" - +typedef ^ ^ ReKi SimplRecCdAMG - - - "Simple model drag coef for rectangular members normal to side A with marine growth" - +typedef ^ ^ ReKi SimplRecCdB - - - "Simple model drag coef for rectangular members normal to side B" - +typedef ^ ^ ReKi SimplRecCdBMG - - - "Simple model drag coef for rectangular members normal to side B with marine growth" - +typedef ^ ^ ReKi SimplRecCaA - - - "Simple model Ca for rectangular members normal to side A" - +typedef ^ ^ ReKi SimplRecCaAMG - - - "Simple model Ca for rectangular members normal to side A with marine growth" - +typedef ^ ^ ReKi SimplRecCaB - - - "Simple model Ca for rectangular members normal to side B" - +typedef ^ ^ ReKi SimplRecCaBMG - - - "Simple model Ca for rectangular members normal to side B with marine growth" - +typedef ^ ^ ReKi SimplRecCp - - - "Simple model Cp for rectangular members" - +typedef ^ ^ ReKi SimplRecCpMG - - - "Simple model Cp for rectangular members with marine growth" - +typedef ^ ^ ReKi SimplRecAxCd - - - "Simple model Axial Cd for rectangular members" - +typedef ^ ^ ReKi SimplRecAxCdMG - - - "Simple model Axial Cd for rectangular members with marine growth" - +typedef ^ ^ ReKi SimplRecAxCa - - - "Simple model Axial Ca for rectangular members" - +typedef ^ ^ ReKi SimplRecAxCaMG - - - "Simple model Axial Ca for rectangular members with marine growth" - +typedef ^ ^ ReKi SimplRecAxCp - - - "Simple model Axial Cp for rectangular members" - +typedef ^ ^ ReKi SimplRecAxCpMG - - - "Simple model Axial Cp for rectangular members with marine growth" - +typedef ^ ^ ReKi SimplRecCb - - - "Simple model hydrostatic/buoyancy load coefficient for rectangular members" - +typedef ^ ^ ReKi SimplRecCbMg - - - "Simple model hydrostatic/buoyancy load coefficient for rectangular members with marine growth" - +typedef ^ ^ LOGICAL SimplRecMCF - - - "Flag T/F for whether the rectangular member is modeled with the MacCamy-Fuchs diffraction model" - +typedef ^ ^ INTEGER NCoefDpthCyl - - - "" - +typedef ^ ^ Morison_CoefDpthsCyl CoefDpthsCyl {:} - - "" - +typedef ^ ^ INTEGER NCoefDpthRec - - - "" - +typedef ^ ^ Morison_CoefDpthsRec CoefDpthsRec {:} - - "" - +typedef ^ ^ INTEGER NCoefMembersCyl - - - "" - +typedef ^ ^ Morison_CoefMembersCyl CoefMembersCyl {:} - - "" - +typedef ^ ^ INTEGER NCoefMembersRec - - - "" - +typedef ^ ^ Morison_CoefMembersRec CoefMembersRec {:} - - "" - typedef ^ ^ INTEGER NMembers - - - "Number of user-specified members in the input file" - typedef ^ ^ Morison_MemberInputType InpMembers {:} - - "Array of user-specified members" - typedef ^ ^ INTEGER NFillGroups - - - "" - @@ -322,6 +449,7 @@ typedef ^ ^ ReKi typedef ^ ^ ReKi F_BF_End {:}{:} - - "" - 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 typedef ^ ^ MeshMapType VisMeshMap - - - "Mesh mapping for visualization mesh" - typedef ^ ^ SeaSt_WaveField_MiscVarType WaveField_m - - - "misc var information from the SeaState Interpolation module" - @@ -356,6 +484,8 @@ typedef ^ ^ INTEGER typedef ^ ^ SeaSt_WaveFieldType *WaveField - - - "SeaState wave field" - typedef ^ ^ logical VisMeshes - .false. - "Output visualization meshes" - typedef ^ ^ INTEGER PtfmYMod - - - "Large yaw model" - +typedef ^ ^ INTEGER NFillGroups - - - "" - +typedef ^ ^ Morison_FilledGroupType FilledGroups {:} - - "" - # # # ..... Inputs .................................................................................................................... diff --git a/modules/hydrodyn/src/Morison_Types.f90 b/modules/hydrodyn/src/Morison_Types.f90 index debd48162d..0cbf7b76aa 100644 --- a/modules/hydrodyn/src/Morison_Types.f90 +++ b/modules/hydrodyn/src/Morison_Types.f90 @@ -34,6 +34,8 @@ MODULE Morison_Types USE SeaSt_WaveField_Types USE NWTC_Library IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: MSecGeom_Cyl = 1 ! MSecGeom = 1 [circular member cross section] [-] + INTEGER(IntKi), PUBLIC, PARAMETER :: MSecGeom_Rec = 2 ! MSecGeom = 2 [rectangular member cross section] [-] ! ========= Morison_JointType ======= TYPE, PUBLIC :: Morison_JointType INTEGER(IntKi) :: JointID = 0_IntKi !< User-specified integer ID for the given joint [-] @@ -45,12 +47,20 @@ MODULE Morison_Types INTEGER(IntKi) , DIMENSION(1:50) :: ConnectionList = 0_IntKi !< List of Members connected to this joint. The member index is what is stored, not the Member ID [-] END TYPE Morison_JointType ! ======================= -! ========= Morison_MemberPropType ======= - TYPE, PUBLIC :: Morison_MemberPropType +! ========= Morison_MemberPropTypeCyl ======= + TYPE, PUBLIC :: Morison_MemberPropTypeCyl INTEGER(IntKi) :: PropSetID = 0_IntKi !< User-specified integer ID for this group of properties [-] REAL(ReKi) :: PropD = 0.0_ReKi !< Diameter [m] REAL(ReKi) :: PropThck = 0.0_ReKi !< Wall thickness [m] - END TYPE Morison_MemberPropType + END TYPE Morison_MemberPropTypeCyl +! ======================= +! ========= Morison_MemberPropTypeRec ======= + TYPE, PUBLIC :: Morison_MemberPropTypeRec + INTEGER(IntKi) :: PropSetID = 0_IntKi !< User-specified integer ID for this group of properties [-] + REAL(ReKi) :: PropA = 0.0_ReKi !< Length of side A [m] + REAL(ReKi) :: PropB = 0.0_ReKi !< Length of side B [m] + REAL(ReKi) :: PropThck = 0.0_ReKi !< Wall thickness [m] + END TYPE Morison_MemberPropTypeRec ! ======================= ! ========= Morison_FilledGroupType ======= TYPE, PUBLIC :: Morison_FilledGroupType @@ -59,10 +69,11 @@ MODULE Morison_Types REAL(ReKi) :: FillFSLoc = 0.0_ReKi !< The free-surface location (in Z) for this fill group [m] CHARACTER(80) :: FillDensChr !< String version of the Fill density [can be DEFAULT which sets the fill density to WtrDens] [kg/m^3] REAL(ReKi) :: FillDens = 0.0_ReKi !< Numerical fill density [kg/m^3] + LOGICAL :: IsOpen = .false. !< Whether the internal ballast is open to the outside through the open end of members buried in the seabed [-] END TYPE Morison_FilledGroupType ! ======================= -! ========= Morison_CoefDpths ======= - TYPE, PUBLIC :: Morison_CoefDpths +! ========= Morison_CoefDpthsCyl ======= + TYPE, PUBLIC :: Morison_CoefDpthsCyl REAL(ReKi) :: Dpth = 0.0_ReKi !< Depth location for these depth-based hydrodynamic coefs [m] REAL(ReKi) :: DpthCd = 0.0_ReKi !< Depth-based drag coef [-] REAL(ReKi) :: DpthCdMG = 0.0_ReKi !< Depth-based drag coef for marine growth [-] @@ -79,7 +90,31 @@ MODULE Morison_Types REAL(ReKi) :: DpthCb = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient [-] REAL(ReKi) :: DpthCbMg = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient for marine growth [-] LOGICAL :: DpthMCF = .false. !< Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model [-] - END TYPE Morison_CoefDpths + END TYPE Morison_CoefDpthsCyl +! ======================= +! ========= Morison_CoefDpthsRec ======= + TYPE, PUBLIC :: Morison_CoefDpthsRec + REAL(ReKi) :: Dpth = 0.0_ReKi !< Depth location for these depth-based hydrodynamic coefs [m] + REAL(ReKi) :: DpthCdA = 0.0_ReKi !< Depth-based drag coef [-] + REAL(ReKi) :: DpthCdAMG = 0.0_ReKi !< Depth-based drag coef for marine growth [-] + REAL(ReKi) :: DpthCdB = 0.0_ReKi !< Depth-based drag coef [-] + REAL(ReKi) :: DpthCdBMG = 0.0_ReKi !< Depth-based drag coef for marine growth [-] + REAL(ReKi) :: DpthCaA = 0.0_ReKi !< Depth-based Ca [-] + REAL(ReKi) :: DpthCaAMG = 0.0_ReKi !< Depth-based Ca for marine growth [-] + REAL(ReKi) :: DpthCaB = 0.0_ReKi !< Depth-based Ca [-] + REAL(ReKi) :: DpthCaBMG = 0.0_ReKi !< Depth-based Ca for marine growth [-] + REAL(ReKi) :: DpthCp = 0.0_ReKi !< Depth-based Cp [-] + REAL(ReKi) :: DpthCpMG = 0.0_ReKi !< Depth-based Cp for marine growth [-] + REAL(ReKi) :: DpthAxCd = 0.0_ReKi !< Depth-based Axial Cd [-] + REAL(ReKi) :: DpthAxCdMG = 0.0_ReKi !< Depth-based Axial Cd for marine growth [-] + REAL(ReKi) :: DpthAxCa = 0.0_ReKi !< Depth-based Axial Ca [-] + REAL(ReKi) :: DpthAxCaMG = 0.0_ReKi !< Depth-based Axial Ca for marine growth [-] + REAL(ReKi) :: DpthAxCp = 0.0_ReKi !< Depth-based Axial Cp [-] + REAL(ReKi) :: DpthAxCpMG = 0.0_ReKi !< Depth-based Axial Cp for marine growth [-] + REAL(ReKi) :: DpthCb = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient [-] + REAL(ReKi) :: DpthCbMg = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient for marine growth [-] + LOGICAL :: DpthMCF = .false. !< Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model [-] + END TYPE Morison_CoefDpthsRec ! ======================= ! ========= Morison_AxialCoefType ======= TYPE, PUBLIC :: Morison_AxialCoefType @@ -104,6 +139,8 @@ MODULE Morison_Types INTEGER(IntKi) :: MPropSetID2 = 0_IntKi !< Property set ID for the end of this member [-] INTEGER(IntKi) :: MPropSetID1Indx = 0_IntKi !< Index into the Property table for the start of this member [-] INTEGER(IntKi) :: MPropSetID2Indx = 0_IntKi !< Index into the Property table for the end of this member [-] + INTEGER(IntKi) :: MSecGeom = 0_IntKi !< Member cross section geometry. 1: Circular. 2: Rectangular [-] + REAL(ReKi) :: MSpinOrient = 0.0_ReKi !< Member orientation in terms of rotation angle about the member axis [rad] REAL(ReKi) :: MDivSize = 0.0_ReKi !< User-specified desired member discretization size for the final element [m] INTEGER(IntKi) :: MCoefMod = 0_IntKi !< Which coef. model is being used for this member [1=simple, 2=depth-based, 3=member-based] [-] INTEGER(IntKi) :: MHstLMod = 0_IntKi !< Which hydrostatic model is being used for this member [1=column-type, 2=ship-type] [-] @@ -146,19 +183,36 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(1:3) :: k = 0.0_ReKi !< unit vector of the member's orientation (may be changed to per-element once additional flexibility is accounted for in HydroDyn) [m] REAL(ReKi) , DIMENSION(1:3,1:3) :: kkt = 0.0_ReKi !< matrix of matmul(k_hat, transpose(k_hat) [-] REAL(ReKi) , DIMENSION(1:3,1:3) :: Ak = 0.0_ReKi !< matrix of I - kkt [-] + REAL(ReKi) , DIMENSION(1:3) :: x_hat = 0.0_ReKi !< unit vector of rectangular member local x-axis aligned with Side A [-] + REAL(ReKi) , DIMENSION(1:3) :: y_hat = 0.0_ReKi !< unit vector of rectangular member local y-axis aligned with Side B [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: R !< outer member radius at each node [m] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: RMG !< radius at each node including marine growth [m] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: RMGB !< radius at each node including marine growth scaled by sqrt(Cb) [m] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Rin !< inner member radius at node, equivalent to radius of water ballast at this node if filled [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Sa !< outer member side A length at each node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SaMG !< side A length with marine growth at each node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SaMGB !< side A length with marine growth scaled by sqrt(Cb) [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Sain !< inner member side A length at node, equivalent to width of water ballast at this node if filled [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Sb !< outer member side B length at each node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SbMG !< side B length with marine growth at each node [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: SbMGB !< side B length with marine growth scaled by sqrt(Cb) [m] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Sbin !< inner member side B length at node, equivalent to width of water ballast at this node if filled [m] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: tMG !< Nodal thickness with marine growth (of member at node location) [m] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: MGdensity !< Nodal density of marine growth [kg/m^3] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dRdl_mg !< taper dr/dl of outer surface including marine growth of each element [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dRdl_mg_b !< taper dr/dl of outer surface including marine growth of each element with scaling of sqrt(Cb) [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dRdl_in !< taper dr/dl of interior surface of each element [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dSadl_mg !< taper dSa/dl of outer surface including marine growth of each element [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dSadl_mg_b !< taper dSa/dl of outer surface including marine growth of each element with scaling of sqrt(Cb) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dSadl_in !< taper dSa/dl of interior surface of each element [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dSbdl_mg !< taper dSb/dl of outer surface including marine growth of each element [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dSbdl_mg_b !< taper dSb/dl of outer surface including marine growth of each element with scaling of sqrt(Cb) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: dSbdl_in !< taper dSb/dl of interior surface of each element [-] REAL(ReKi) :: Vinner = 0.0_ReKi !< Member volume without marine growth [m^3] REAL(ReKi) :: Vouter = 0.0_ReKi !< Member volume including marine growth [m^3] REAL(ReKi) :: Vballast = 0.0_ReKi !< Member ballast volume [m^3] REAL(ReKi) :: Vsubmerged = 0.0_ReKi !< Submerged volume corresponding to portion of Member in the water [m^3] + INTEGER(IntKi) :: elem_fill = 0_IntKi !< Last (partially) filled element of the member [-] REAL(ReKi) :: l_fill = 0.0_ReKi !< fill length along member axis from start node 1 [m] REAL(ReKi) :: h_fill = 0.0_ReKi !< fill length of partially flooded element [m] REAL(ReKi) :: z_overfill = 0.0_ReKi !< if member is fully filled, the head height of the fill pressure at the end node N+1. Zero if member is partially filled. [m] @@ -172,6 +226,10 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: alpha_fb_star !< load distribution factor for each element after adjusting alpha_fb for node reference depths [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cd !< Member Cd at each node [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Ca !< Member Ca at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CdA !< Member Cd normal to side A at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CaA !< Member Ca normal to side A at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CdB !< Member Cd normal to side B at each node [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CaB !< Member Ca normal to side B at each node [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cp !< Member Cp at each node [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AxCd !< Member axial Cd at each node [-] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AxCa !< Member axial Ca at each node [-] @@ -185,6 +243,10 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_lfb_u !< axial moment of inertia of flooded ballast in upper portion of each element [kg-m^2] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_rfb_l !< radial moment of inertia of flooded ballast in lower portion of each element [kg-m^2] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_rfb_u !< radial moment of inertia of flooded ballast in upper portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_xfb_l !< element local x-moment of inertia of flooded ballast in lower portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_xfb_u !< element local x-moment of inertia of flooded ballast in upper portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_yfb_l !< element local y-moment of inertia of flooded ballast in lower portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_yfb_u !< element local y-moment of inertia of flooded ballast in upper portion of each element [kg-m^2] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: m_mg_l !< mass of marine growth in lower portion of each element [kg] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: m_mg_u !< mass of marine growth in upper portion of each element [kg] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: h_cmg_l !< distance to marine growth centroid from node point in lower portion of each element [m] @@ -193,10 +255,13 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_lmg_u !< axial moment of inertia of marine growth in upper portion of each element [kg-m^2] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_rmg_l !< radial moment of inertia of marine growth in lower portion of each element [kg-m^2] REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_rmg_u !< radial moment of inertia of flooded ballast in upper portion of each element [kg-m^2] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cfl_fb !< axial force constant due to flooded ballast, for each element [N] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Cfr_fb !< radial force constant due to flooded ballast, for each element [N] - REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: CM0_fb !< moment constant due to flooded ballast, for each element about lower node [Nm] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_xmg_l !< element local x-moment of inertia of marine growth in lower portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_xmg_u !< element local x-moment of inertia of marine growth in upper portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_ymg_l !< element local y-moment of inertia of marine growth in lower portion of each element [kg-m^2] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: I_ymg_u !< element local y-moment of inertia of marine growth in upper portion of each element [kg-m^2] REAL(ReKi) :: MGvolume = 0.0_ReKi !< Volume of marine growth material for this member/element [m^3] + INTEGER(IntKi) :: MSecGeom = 0_IntKi !< Member cross section geometry. 1: Circular. 2: Rectangular [-] + REAL(ReKi) :: MSpinOrient = 0.0_ReKi !< Member orientation in terms of rotation angle about the member axis [rad] REAL(ReKi) :: MDivSize = 0.0_ReKi !< User-requested final element length (actual length may vary from this request) [m] INTEGER(IntKi) :: MCoefMod = 0_IntKi !< Coefs model for member: 1 = simple, 2 =depth, 3 = member-based [-] INTEGER(IntKi) :: MmbrCoefIDIndx = 0_IntKi !< If MCoefMod=3, then this is the index for the member's coefs in the master Member Coefs Table [-] @@ -224,39 +289,81 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_DP !< Lumped dynamic pressure loads at time t, which may not correspond to the WaveTime array of times [-] END TYPE Morison_MemberLoads ! ======================= -! ========= Morison_CoefMembers ======= - TYPE, PUBLIC :: Morison_CoefMembers +! ========= Morison_CoefMembersCyl ======= + TYPE, PUBLIC :: Morison_CoefMembersCyl INTEGER(IntKi) :: MemberID = 0_IntKi !< User-specified integer id for the Member-based coefs [-] - REAL(ReKi) :: MemberCd1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCd2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCdMG1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCdMG2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCa1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCa2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCaMG1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCaMG2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCp1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCp2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCpMG1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCpMG2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCd1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCd2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCdMG1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCdMG2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCa1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCa2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCaMG1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCaMG2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCp1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCp2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCpMG1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberAxCpMG2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCb1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCb2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCbMG1 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - REAL(ReKi) :: MemberCbMG2 = 0.0_ReKi !< Member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] - LOGICAL :: MemberMCF = .false. !< Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model [-] - END TYPE Morison_CoefMembers + REAL(ReKi) :: MemberCd1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCd2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCdMG1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCdMG2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCa1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCa2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaMG1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaMG2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCp1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCp2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCpMG1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCpMG2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCd1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCd2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCdMG1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCdMG2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCa1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCa2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCaMG1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCaMG2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCp1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCp2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCpMG1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCpMG2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCb1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCb2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCbMG1 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCbMG2 = 0.0_ReKi !< Cylindrical member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + LOGICAL :: MemberMCF = .false. !< Flag T/F for whether the cylindrical member is modeled with the MacCamy-Fuchs diffraction model [-] + END TYPE Morison_CoefMembersCyl +! ======================= +! ========= Morison_CoefMembersRec ======= + TYPE, PUBLIC :: Morison_CoefMembersRec + INTEGER(IntKi) :: MemberID = 0_IntKi !< User-specified integer id for the Member-based coefs [-] + REAL(ReKi) :: MemberCdA1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCdA2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCdAMG1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCdAMG2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCdB1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCdB2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCdBMG1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCdBMG2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaA1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaA2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaAMG1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaAMG2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaB1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaB2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaBMG1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCaBMG2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCp1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCp2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCpMG1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCpMG2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCd1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCd2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCdMG1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCdMG2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCa1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCa2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCaMG1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCaMG2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCp1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCp2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCpMG1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberAxCpMG2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCb1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCb2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCbMG1 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + REAL(ReKi) :: MemberCbMG2 = 0.0_ReKi !< Rectangular member-based coefs, see above descriptions for meanings (1 = start, 2=end) [-] + LOGICAL :: MemberMCF = .false. !< Flag T/F for whether the rectangular member is modeled with the MacCamy-Fuchs diffraction model [-] + END TYPE Morison_CoefMembersRec ! ======================= ! ========= Morison_MGDepthsType ======= TYPE, PUBLIC :: Morison_MGDepthsType @@ -295,27 +402,52 @@ MODULE Morison_Types TYPE(Morison_NodeType) , DIMENSION(:), ALLOCATABLE :: Nodes !< Array of simulation node (some correspond to user-specified joints, others are created by software) [-] INTEGER(IntKi) :: NAxCoefs = 0_IntKi !< Number of axial Coefs entries in input file table [-] TYPE(Morison_AxialCoefType) , DIMENSION(:), ALLOCATABLE :: AxialCoefs !< List of axial coefs [-] - INTEGER(IntKi) :: NPropSets = 0_IntKi !< Number of member property sets [-] - TYPE(Morison_MemberPropType) , DIMENSION(:), ALLOCATABLE :: MPropSets !< List of Member property sets [-] - REAL(ReKi) :: SimplCd = 0.0_ReKi !< Simple model drag coef [-] - REAL(ReKi) :: SimplCdMG = 0.0_ReKi !< Simple model drag coef for marine growth [-] - REAL(ReKi) :: SimplCa = 0.0_ReKi !< Simple model Ca [-] - REAL(ReKi) :: SimplCaMG = 0.0_ReKi !< Simple model Ca for marine growth [-] - REAL(ReKi) :: SimplCp = 0.0_ReKi !< Simple model Cp [-] - REAL(ReKi) :: SimplCpMG = 0.0_ReKi !< Simple model Cp for marine growth [-] - REAL(ReKi) :: SimplAxCd = 0.0_ReKi !< Simple model Axial Cd [-] - REAL(ReKi) :: SimplAxCdMG = 0.0_ReKi !< Simple model Axial Cd for marine growth [-] - REAL(ReKi) :: SimplAxCa = 0.0_ReKi !< Simple model Axial Ca [-] - REAL(ReKi) :: SimplAxCaMG = 0.0_ReKi !< Simple model Axial Ca for marine growth [-] - REAL(ReKi) :: SimplAxCp = 0.0_ReKi !< Simple model Axial Cp [-] - REAL(ReKi) :: SimplAxCpMG = 0.0_ReKi !< Simple model Axial Cp for marine growth [-] - REAL(ReKi) :: SimplCb = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient [-] - REAL(ReKi) :: SimplCbMg = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient for marine growth [-] - LOGICAL :: SimplMCF = .false. !< Flag T/F for whether the member is modeled with the MacCamy-Fuchs diffraction model [-] - INTEGER(IntKi) :: NCoefDpth = 0_IntKi !< [-] - TYPE(Morison_CoefDpths) , DIMENSION(:), ALLOCATABLE :: CoefDpths !< [-] - INTEGER(IntKi) :: NCoefMembers = 0_IntKi !< [-] - TYPE(Morison_CoefMembers) , DIMENSION(:), ALLOCATABLE :: CoefMembers !< [-] + INTEGER(IntKi) :: NPropSetsCyl = 0_IntKi !< Number of cylindrical member property sets [-] + TYPE(Morison_MemberPropTypeCyl) , DIMENSION(:), ALLOCATABLE :: MPropSetsCyl !< List of cylindrical member property sets [-] + INTEGER(IntKi) :: NPropSetsRec = 0_IntKi !< Number of rectangular member property sets [-] + TYPE(Morison_MemberPropTypeRec) , DIMENSION(:), ALLOCATABLE :: MPropSetsRec !< List of rectangular member property sets [-] + REAL(ReKi) :: SimplCd = 0.0_ReKi !< Simple model drag coef for cylindrical members [-] + REAL(ReKi) :: SimplCdMG = 0.0_ReKi !< Simple model drag coef for cylindrical members with marine growth [-] + REAL(ReKi) :: SimplCa = 0.0_ReKi !< Simple model Ca for cylindrical members [-] + REAL(ReKi) :: SimplCaMG = 0.0_ReKi !< Simple model Ca for cylindrical members with marine growth [-] + REAL(ReKi) :: SimplCp = 0.0_ReKi !< Simple model Cp for cylindrical members [-] + REAL(ReKi) :: SimplCpMG = 0.0_ReKi !< Simple model Cp for cylindrical members with marine growth [-] + REAL(ReKi) :: SimplAxCd = 0.0_ReKi !< Simple model Axial Cd for cylindrical members [-] + REAL(ReKi) :: SimplAxCdMG = 0.0_ReKi !< Simple model Axial Cd for cylindrical members with marine growth [-] + REAL(ReKi) :: SimplAxCa = 0.0_ReKi !< Simple model Axial Ca for cylindrical members [-] + REAL(ReKi) :: SimplAxCaMG = 0.0_ReKi !< Simple model Axial Ca for cylindrical members with marine growth [-] + REAL(ReKi) :: SimplAxCp = 0.0_ReKi !< Simple model Axial Cp for cylindrical members [-] + REAL(ReKi) :: SimplAxCpMG = 0.0_ReKi !< Simple model Axial Cp for cylindrical members with marine growth [-] + REAL(ReKi) :: SimplCb = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient for cylindrical members [-] + REAL(ReKi) :: SimplCbMg = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient for cylindrical members with marine growth [-] + LOGICAL :: SimplMCF = .false. !< Flag T/F for whether the cylindrical member is modeled with the MacCamy-Fuchs diffraction model [-] + REAL(ReKi) :: SimplRecCdA = 0.0_ReKi !< Simple model drag coef for rectangular members normal to side A [-] + REAL(ReKi) :: SimplRecCdAMG = 0.0_ReKi !< Simple model drag coef for rectangular members normal to side A with marine growth [-] + REAL(ReKi) :: SimplRecCdB = 0.0_ReKi !< Simple model drag coef for rectangular members normal to side B [-] + REAL(ReKi) :: SimplRecCdBMG = 0.0_ReKi !< Simple model drag coef for rectangular members normal to side B with marine growth [-] + REAL(ReKi) :: SimplRecCaA = 0.0_ReKi !< Simple model Ca for rectangular members normal to side A [-] + REAL(ReKi) :: SimplRecCaAMG = 0.0_ReKi !< Simple model Ca for rectangular members normal to side A with marine growth [-] + REAL(ReKi) :: SimplRecCaB = 0.0_ReKi !< Simple model Ca for rectangular members normal to side B [-] + REAL(ReKi) :: SimplRecCaBMG = 0.0_ReKi !< Simple model Ca for rectangular members normal to side B with marine growth [-] + REAL(ReKi) :: SimplRecCp = 0.0_ReKi !< Simple model Cp for rectangular members [-] + REAL(ReKi) :: SimplRecCpMG = 0.0_ReKi !< Simple model Cp for rectangular members with marine growth [-] + REAL(ReKi) :: SimplRecAxCd = 0.0_ReKi !< Simple model Axial Cd for rectangular members [-] + REAL(ReKi) :: SimplRecAxCdMG = 0.0_ReKi !< Simple model Axial Cd for rectangular members with marine growth [-] + REAL(ReKi) :: SimplRecAxCa = 0.0_ReKi !< Simple model Axial Ca for rectangular members [-] + REAL(ReKi) :: SimplRecAxCaMG = 0.0_ReKi !< Simple model Axial Ca for rectangular members with marine growth [-] + REAL(ReKi) :: SimplRecAxCp = 0.0_ReKi !< Simple model Axial Cp for rectangular members [-] + REAL(ReKi) :: SimplRecAxCpMG = 0.0_ReKi !< Simple model Axial Cp for rectangular members with marine growth [-] + REAL(ReKi) :: SimplRecCb = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient for rectangular members [-] + REAL(ReKi) :: SimplRecCbMg = 0.0_ReKi !< Simple model hydrostatic/buoyancy load coefficient for rectangular members with marine growth [-] + LOGICAL :: SimplRecMCF = .false. !< Flag T/F for whether the rectangular member is modeled with the MacCamy-Fuchs diffraction model [-] + INTEGER(IntKi) :: NCoefDpthCyl = 0_IntKi !< [-] + TYPE(Morison_CoefDpthsCyl) , DIMENSION(:), ALLOCATABLE :: CoefDpthsCyl !< [-] + INTEGER(IntKi) :: NCoefDpthRec = 0_IntKi !< [-] + TYPE(Morison_CoefDpthsRec) , DIMENSION(:), ALLOCATABLE :: CoefDpthsRec !< [-] + INTEGER(IntKi) :: NCoefMembersCyl = 0_IntKi !< [-] + TYPE(Morison_CoefMembersCyl) , DIMENSION(:), ALLOCATABLE :: CoefMembersCyl !< [-] + INTEGER(IntKi) :: NCoefMembersRec = 0_IntKi !< [-] + TYPE(Morison_CoefMembersRec) , DIMENSION(:), ALLOCATABLE :: CoefMembersRec !< [-] INTEGER(IntKi) :: NMembers = 0_IntKi !< Number of user-specified members in the input file [-] TYPE(Morison_MemberInputType) , DIMENSION(:), ALLOCATABLE :: InpMembers !< Array of user-specified members [-] INTEGER(IntKi) :: NFillGroups = 0_IntKi !< [-] @@ -385,6 +517,7 @@ MODULE Morison_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_BF_End !< [-] 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] TYPE(MeshMapType) :: VisMeshMap !< Mesh mapping for visualization mesh [-] TYPE(SeaSt_WaveField_MiscVarType) :: WaveField_m !< misc var information from the SeaState Interpolation module [-] END TYPE Morison_MiscVarType @@ -418,6 +551,8 @@ MODULE Morison_Types TYPE(SeaSt_WaveFieldType) , POINTER :: WaveField => NULL() !< SeaState wave field [-] LOGICAL :: VisMeshes = .false. !< Output visualization meshes [-] INTEGER(IntKi) :: PtfmYMod = 0_IntKi !< Large yaw model [-] + INTEGER(IntKi) :: NFillGroups = 0_IntKi !< [-] + TYPE(Morison_FilledGroupType) , DIMENSION(:), ALLOCATABLE :: FilledGroups !< [-] END TYPE Morison_ParameterType ! ======================= ! ========= Morison_InputType ======= @@ -491,33 +626,33 @@ subroutine Morison_UnPackJointType(RF, OutData) call RegUnpack(RF, OutData%ConnectionList); if (RegCheckErr(RF, RoutineName)) return end subroutine -subroutine Morison_CopyMemberPropType(SrcMemberPropTypeData, DstMemberPropTypeData, CtrlCode, ErrStat, ErrMsg) - type(Morison_MemberPropType), intent(in) :: SrcMemberPropTypeData - type(Morison_MemberPropType), intent(inout) :: DstMemberPropTypeData +subroutine Morison_CopyMemberPropTypeCyl(SrcMemberPropTypeCylData, DstMemberPropTypeCylData, CtrlCode, ErrStat, ErrMsg) + type(Morison_MemberPropTypeCyl), intent(in) :: SrcMemberPropTypeCylData + type(Morison_MemberPropTypeCyl), intent(inout) :: DstMemberPropTypeCylData integer(IntKi), intent(in ) :: CtrlCode integer(IntKi), intent( out) :: ErrStat character(*), intent( out) :: ErrMsg - character(*), parameter :: RoutineName = 'Morison_CopyMemberPropType' + character(*), parameter :: RoutineName = 'Morison_CopyMemberPropTypeCyl' ErrStat = ErrID_None ErrMsg = '' - DstMemberPropTypeData%PropSetID = SrcMemberPropTypeData%PropSetID - DstMemberPropTypeData%PropD = SrcMemberPropTypeData%PropD - DstMemberPropTypeData%PropThck = SrcMemberPropTypeData%PropThck + DstMemberPropTypeCylData%PropSetID = SrcMemberPropTypeCylData%PropSetID + DstMemberPropTypeCylData%PropD = SrcMemberPropTypeCylData%PropD + DstMemberPropTypeCylData%PropThck = SrcMemberPropTypeCylData%PropThck end subroutine -subroutine Morison_DestroyMemberPropType(MemberPropTypeData, ErrStat, ErrMsg) - type(Morison_MemberPropType), intent(inout) :: MemberPropTypeData +subroutine Morison_DestroyMemberPropTypeCyl(MemberPropTypeCylData, ErrStat, ErrMsg) + type(Morison_MemberPropTypeCyl), intent(inout) :: MemberPropTypeCylData integer(IntKi), intent( out) :: ErrStat character(*), intent( out) :: ErrMsg - character(*), parameter :: RoutineName = 'Morison_DestroyMemberPropType' + character(*), parameter :: RoutineName = 'Morison_DestroyMemberPropTypeCyl' ErrStat = ErrID_None ErrMsg = '' end subroutine -subroutine Morison_PackMemberPropType(RF, Indata) +subroutine Morison_PackMemberPropTypeCyl(RF, Indata) type(RegFile), intent(inout) :: RF - type(Morison_MemberPropType), intent(in) :: InData - character(*), parameter :: RoutineName = 'Morison_PackMemberPropType' + type(Morison_MemberPropTypeCyl), intent(in) :: InData + character(*), parameter :: RoutineName = 'Morison_PackMemberPropTypeCyl' if (RF%ErrStat >= AbortErrLev) return call RegPack(RF, InData%PropSetID) call RegPack(RF, InData%PropD) @@ -525,16 +660,63 @@ subroutine Morison_PackMemberPropType(RF, Indata) if (RegCheckErr(RF, RoutineName)) return end subroutine -subroutine Morison_UnPackMemberPropType(RF, OutData) +subroutine Morison_UnPackMemberPropTypeCyl(RF, OutData) type(RegFile), intent(inout) :: RF - type(Morison_MemberPropType), intent(inout) :: OutData - character(*), parameter :: RoutineName = 'Morison_UnPackMemberPropType' + type(Morison_MemberPropTypeCyl), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'Morison_UnPackMemberPropTypeCyl' if (RF%ErrStat /= ErrID_None) return call RegUnpack(RF, OutData%PropSetID); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%PropD); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%PropThck); if (RegCheckErr(RF, RoutineName)) return end subroutine +subroutine Morison_CopyMemberPropTypeRec(SrcMemberPropTypeRecData, DstMemberPropTypeRecData, CtrlCode, ErrStat, ErrMsg) + type(Morison_MemberPropTypeRec), intent(in) :: SrcMemberPropTypeRecData + type(Morison_MemberPropTypeRec), intent(inout) :: DstMemberPropTypeRecData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'Morison_CopyMemberPropTypeRec' + ErrStat = ErrID_None + ErrMsg = '' + DstMemberPropTypeRecData%PropSetID = SrcMemberPropTypeRecData%PropSetID + DstMemberPropTypeRecData%PropA = SrcMemberPropTypeRecData%PropA + DstMemberPropTypeRecData%PropB = SrcMemberPropTypeRecData%PropB + DstMemberPropTypeRecData%PropThck = SrcMemberPropTypeRecData%PropThck +end subroutine + +subroutine Morison_DestroyMemberPropTypeRec(MemberPropTypeRecData, ErrStat, ErrMsg) + type(Morison_MemberPropTypeRec), intent(inout) :: MemberPropTypeRecData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'Morison_DestroyMemberPropTypeRec' + ErrStat = ErrID_None + ErrMsg = '' +end subroutine + +subroutine Morison_PackMemberPropTypeRec(RF, Indata) + type(RegFile), intent(inout) :: RF + type(Morison_MemberPropTypeRec), intent(in) :: InData + character(*), parameter :: RoutineName = 'Morison_PackMemberPropTypeRec' + if (RF%ErrStat >= AbortErrLev) return + call RegPack(RF, InData%PropSetID) + call RegPack(RF, InData%PropA) + call RegPack(RF, InData%PropB) + call RegPack(RF, InData%PropThck) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine Morison_UnPackMemberPropTypeRec(RF, OutData) + type(RegFile), intent(inout) :: RF + type(Morison_MemberPropTypeRec), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'Morison_UnPackMemberPropTypeRec' + if (RF%ErrStat /= ErrID_None) return + call RegUnpack(RF, OutData%PropSetID); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%PropA); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%PropB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%PropThck); if (RegCheckErr(RF, RoutineName)) return +end subroutine + subroutine Morison_CopyFilledGroupType(SrcFilledGroupTypeData, DstFilledGroupTypeData, CtrlCode, ErrStat, ErrMsg) type(Morison_FilledGroupType), intent(in) :: SrcFilledGroupTypeData type(Morison_FilledGroupType), intent(inout) :: DstFilledGroupTypeData @@ -562,6 +744,7 @@ subroutine Morison_CopyFilledGroupType(SrcFilledGroupTypeData, DstFilledGroupTyp DstFilledGroupTypeData%FillFSLoc = SrcFilledGroupTypeData%FillFSLoc DstFilledGroupTypeData%FillDensChr = SrcFilledGroupTypeData%FillDensChr DstFilledGroupTypeData%FillDens = SrcFilledGroupTypeData%FillDens + DstFilledGroupTypeData%IsOpen = SrcFilledGroupTypeData%IsOpen end subroutine subroutine Morison_DestroyFilledGroupType(FilledGroupTypeData, ErrStat, ErrMsg) @@ -586,6 +769,7 @@ subroutine Morison_PackFilledGroupType(RF, Indata) call RegPack(RF, InData%FillFSLoc) call RegPack(RF, InData%FillDensChr) call RegPack(RF, InData%FillDens) + call RegPack(RF, InData%IsOpen) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -602,48 +786,49 @@ subroutine Morison_UnPackFilledGroupType(RF, OutData) call RegUnpack(RF, OutData%FillFSLoc); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%FillDensChr); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%FillDens); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%IsOpen); if (RegCheckErr(RF, RoutineName)) return end subroutine -subroutine Morison_CopyCoefDpths(SrcCoefDpthsData, DstCoefDpthsData, CtrlCode, ErrStat, ErrMsg) - type(Morison_CoefDpths), intent(in) :: SrcCoefDpthsData - type(Morison_CoefDpths), intent(inout) :: DstCoefDpthsData +subroutine Morison_CopyCoefDpthsCyl(SrcCoefDpthsCylData, DstCoefDpthsCylData, CtrlCode, ErrStat, ErrMsg) + type(Morison_CoefDpthsCyl), intent(in) :: SrcCoefDpthsCylData + type(Morison_CoefDpthsCyl), intent(inout) :: DstCoefDpthsCylData integer(IntKi), intent(in ) :: CtrlCode integer(IntKi), intent( out) :: ErrStat character(*), intent( out) :: ErrMsg - character(*), parameter :: RoutineName = 'Morison_CopyCoefDpths' + character(*), parameter :: RoutineName = 'Morison_CopyCoefDpthsCyl' ErrStat = ErrID_None ErrMsg = '' - DstCoefDpthsData%Dpth = SrcCoefDpthsData%Dpth - DstCoefDpthsData%DpthCd = SrcCoefDpthsData%DpthCd - DstCoefDpthsData%DpthCdMG = SrcCoefDpthsData%DpthCdMG - DstCoefDpthsData%DpthCa = SrcCoefDpthsData%DpthCa - DstCoefDpthsData%DpthCaMG = SrcCoefDpthsData%DpthCaMG - DstCoefDpthsData%DpthCp = SrcCoefDpthsData%DpthCp - DstCoefDpthsData%DpthCpMG = SrcCoefDpthsData%DpthCpMG - DstCoefDpthsData%DpthAxCd = SrcCoefDpthsData%DpthAxCd - DstCoefDpthsData%DpthAxCdMG = SrcCoefDpthsData%DpthAxCdMG - DstCoefDpthsData%DpthAxCa = SrcCoefDpthsData%DpthAxCa - DstCoefDpthsData%DpthAxCaMG = SrcCoefDpthsData%DpthAxCaMG - DstCoefDpthsData%DpthAxCp = SrcCoefDpthsData%DpthAxCp - DstCoefDpthsData%DpthAxCpMG = SrcCoefDpthsData%DpthAxCpMG - DstCoefDpthsData%DpthCb = SrcCoefDpthsData%DpthCb - DstCoefDpthsData%DpthCbMg = SrcCoefDpthsData%DpthCbMg - DstCoefDpthsData%DpthMCF = SrcCoefDpthsData%DpthMCF + DstCoefDpthsCylData%Dpth = SrcCoefDpthsCylData%Dpth + DstCoefDpthsCylData%DpthCd = SrcCoefDpthsCylData%DpthCd + DstCoefDpthsCylData%DpthCdMG = SrcCoefDpthsCylData%DpthCdMG + DstCoefDpthsCylData%DpthCa = SrcCoefDpthsCylData%DpthCa + DstCoefDpthsCylData%DpthCaMG = SrcCoefDpthsCylData%DpthCaMG + DstCoefDpthsCylData%DpthCp = SrcCoefDpthsCylData%DpthCp + DstCoefDpthsCylData%DpthCpMG = SrcCoefDpthsCylData%DpthCpMG + DstCoefDpthsCylData%DpthAxCd = SrcCoefDpthsCylData%DpthAxCd + DstCoefDpthsCylData%DpthAxCdMG = SrcCoefDpthsCylData%DpthAxCdMG + DstCoefDpthsCylData%DpthAxCa = SrcCoefDpthsCylData%DpthAxCa + DstCoefDpthsCylData%DpthAxCaMG = SrcCoefDpthsCylData%DpthAxCaMG + DstCoefDpthsCylData%DpthAxCp = SrcCoefDpthsCylData%DpthAxCp + DstCoefDpthsCylData%DpthAxCpMG = SrcCoefDpthsCylData%DpthAxCpMG + DstCoefDpthsCylData%DpthCb = SrcCoefDpthsCylData%DpthCb + DstCoefDpthsCylData%DpthCbMg = SrcCoefDpthsCylData%DpthCbMg + DstCoefDpthsCylData%DpthMCF = SrcCoefDpthsCylData%DpthMCF end subroutine -subroutine Morison_DestroyCoefDpths(CoefDpthsData, ErrStat, ErrMsg) - type(Morison_CoefDpths), intent(inout) :: CoefDpthsData +subroutine Morison_DestroyCoefDpthsCyl(CoefDpthsCylData, ErrStat, ErrMsg) + type(Morison_CoefDpthsCyl), intent(inout) :: CoefDpthsCylData integer(IntKi), intent( out) :: ErrStat character(*), intent( out) :: ErrMsg - character(*), parameter :: RoutineName = 'Morison_DestroyCoefDpths' + character(*), parameter :: RoutineName = 'Morison_DestroyCoefDpthsCyl' ErrStat = ErrID_None ErrMsg = '' end subroutine -subroutine Morison_PackCoefDpths(RF, Indata) +subroutine Morison_PackCoefDpthsCyl(RF, Indata) type(RegFile), intent(inout) :: RF - type(Morison_CoefDpths), intent(in) :: InData - character(*), parameter :: RoutineName = 'Morison_PackCoefDpths' + type(Morison_CoefDpthsCyl), intent(in) :: InData + character(*), parameter :: RoutineName = 'Morison_PackCoefDpthsCyl' if (RF%ErrStat >= AbortErrLev) return call RegPack(RF, InData%Dpth) call RegPack(RF, InData%DpthCd) @@ -664,10 +849,10 @@ subroutine Morison_PackCoefDpths(RF, Indata) if (RegCheckErr(RF, RoutineName)) return end subroutine -subroutine Morison_UnPackCoefDpths(RF, OutData) +subroutine Morison_UnPackCoefDpthsCyl(RF, OutData) type(RegFile), intent(inout) :: RF - type(Morison_CoefDpths), intent(inout) :: OutData - character(*), parameter :: RoutineName = 'Morison_UnPackCoefDpths' + type(Morison_CoefDpthsCyl), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'Morison_UnPackCoefDpthsCyl' if (RF%ErrStat /= ErrID_None) return call RegUnpack(RF, OutData%Dpth); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%DpthCd); if (RegCheckErr(RF, RoutineName)) return @@ -687,6 +872,101 @@ subroutine Morison_UnPackCoefDpths(RF, OutData) call RegUnpack(RF, OutData%DpthMCF); if (RegCheckErr(RF, RoutineName)) return end subroutine +subroutine Morison_CopyCoefDpthsRec(SrcCoefDpthsRecData, DstCoefDpthsRecData, CtrlCode, ErrStat, ErrMsg) + type(Morison_CoefDpthsRec), intent(in) :: SrcCoefDpthsRecData + type(Morison_CoefDpthsRec), intent(inout) :: DstCoefDpthsRecData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'Morison_CopyCoefDpthsRec' + ErrStat = ErrID_None + ErrMsg = '' + DstCoefDpthsRecData%Dpth = SrcCoefDpthsRecData%Dpth + DstCoefDpthsRecData%DpthCdA = SrcCoefDpthsRecData%DpthCdA + DstCoefDpthsRecData%DpthCdAMG = SrcCoefDpthsRecData%DpthCdAMG + DstCoefDpthsRecData%DpthCdB = SrcCoefDpthsRecData%DpthCdB + DstCoefDpthsRecData%DpthCdBMG = SrcCoefDpthsRecData%DpthCdBMG + DstCoefDpthsRecData%DpthCaA = SrcCoefDpthsRecData%DpthCaA + DstCoefDpthsRecData%DpthCaAMG = SrcCoefDpthsRecData%DpthCaAMG + DstCoefDpthsRecData%DpthCaB = SrcCoefDpthsRecData%DpthCaB + DstCoefDpthsRecData%DpthCaBMG = SrcCoefDpthsRecData%DpthCaBMG + DstCoefDpthsRecData%DpthCp = SrcCoefDpthsRecData%DpthCp + DstCoefDpthsRecData%DpthCpMG = SrcCoefDpthsRecData%DpthCpMG + DstCoefDpthsRecData%DpthAxCd = SrcCoefDpthsRecData%DpthAxCd + DstCoefDpthsRecData%DpthAxCdMG = SrcCoefDpthsRecData%DpthAxCdMG + DstCoefDpthsRecData%DpthAxCa = SrcCoefDpthsRecData%DpthAxCa + DstCoefDpthsRecData%DpthAxCaMG = SrcCoefDpthsRecData%DpthAxCaMG + DstCoefDpthsRecData%DpthAxCp = SrcCoefDpthsRecData%DpthAxCp + DstCoefDpthsRecData%DpthAxCpMG = SrcCoefDpthsRecData%DpthAxCpMG + DstCoefDpthsRecData%DpthCb = SrcCoefDpthsRecData%DpthCb + DstCoefDpthsRecData%DpthCbMg = SrcCoefDpthsRecData%DpthCbMg + DstCoefDpthsRecData%DpthMCF = SrcCoefDpthsRecData%DpthMCF +end subroutine + +subroutine Morison_DestroyCoefDpthsRec(CoefDpthsRecData, ErrStat, ErrMsg) + type(Morison_CoefDpthsRec), intent(inout) :: CoefDpthsRecData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'Morison_DestroyCoefDpthsRec' + ErrStat = ErrID_None + ErrMsg = '' +end subroutine + +subroutine Morison_PackCoefDpthsRec(RF, Indata) + type(RegFile), intent(inout) :: RF + type(Morison_CoefDpthsRec), intent(in) :: InData + character(*), parameter :: RoutineName = 'Morison_PackCoefDpthsRec' + if (RF%ErrStat >= AbortErrLev) return + call RegPack(RF, InData%Dpth) + call RegPack(RF, InData%DpthCdA) + call RegPack(RF, InData%DpthCdAMG) + call RegPack(RF, InData%DpthCdB) + call RegPack(RF, InData%DpthCdBMG) + call RegPack(RF, InData%DpthCaA) + call RegPack(RF, InData%DpthCaAMG) + call RegPack(RF, InData%DpthCaB) + call RegPack(RF, InData%DpthCaBMG) + call RegPack(RF, InData%DpthCp) + call RegPack(RF, InData%DpthCpMG) + call RegPack(RF, InData%DpthAxCd) + call RegPack(RF, InData%DpthAxCdMG) + call RegPack(RF, InData%DpthAxCa) + call RegPack(RF, InData%DpthAxCaMG) + call RegPack(RF, InData%DpthAxCp) + call RegPack(RF, InData%DpthAxCpMG) + call RegPack(RF, InData%DpthCb) + call RegPack(RF, InData%DpthCbMg) + call RegPack(RF, InData%DpthMCF) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine Morison_UnPackCoefDpthsRec(RF, OutData) + type(RegFile), intent(inout) :: RF + type(Morison_CoefDpthsRec), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'Morison_UnPackCoefDpthsRec' + if (RF%ErrStat /= ErrID_None) return + call RegUnpack(RF, OutData%Dpth); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCdA); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCdAMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCdB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCdBMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCaA); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCaAMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCaB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCaBMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCp); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCpMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthAxCd); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthAxCdMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthAxCa); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthAxCaMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthAxCp); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthAxCpMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCb); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthCbMg); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%DpthMCF); if (RegCheckErr(RF, RoutineName)) return +end subroutine + subroutine Morison_CopyAxialCoefType(SrcAxialCoefTypeData, DstAxialCoefTypeData, CtrlCode, ErrStat, ErrMsg) type(Morison_AxialCoefType), intent(in) :: SrcAxialCoefTypeData type(Morison_AxialCoefType), intent(inout) :: DstAxialCoefTypeData @@ -775,6 +1055,8 @@ subroutine Morison_CopyMemberInputType(SrcMemberInputTypeData, DstMemberInputTyp DstMemberInputTypeData%MPropSetID2 = SrcMemberInputTypeData%MPropSetID2 DstMemberInputTypeData%MPropSetID1Indx = SrcMemberInputTypeData%MPropSetID1Indx DstMemberInputTypeData%MPropSetID2Indx = SrcMemberInputTypeData%MPropSetID2Indx + DstMemberInputTypeData%MSecGeom = SrcMemberInputTypeData%MSecGeom + DstMemberInputTypeData%MSpinOrient = SrcMemberInputTypeData%MSpinOrient DstMemberInputTypeData%MDivSize = SrcMemberInputTypeData%MDivSize DstMemberInputTypeData%MCoefMod = SrcMemberInputTypeData%MCoefMod DstMemberInputTypeData%MHstLMod = SrcMemberInputTypeData%MHstLMod @@ -814,6 +1096,8 @@ subroutine Morison_PackMemberInputType(RF, Indata) call RegPack(RF, InData%MPropSetID2) call RegPack(RF, InData%MPropSetID1Indx) call RegPack(RF, InData%MPropSetID2Indx) + call RegPack(RF, InData%MSecGeom) + call RegPack(RF, InData%MSpinOrient) call RegPack(RF, InData%MDivSize) call RegPack(RF, InData%MCoefMod) call RegPack(RF, InData%MHstLMod) @@ -845,6 +1129,8 @@ subroutine Morison_UnPackMemberInputType(RF, OutData) call RegUnpack(RF, OutData%MPropSetID2); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MPropSetID1Indx); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MPropSetID2Indx); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MSecGeom); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MSpinOrient); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MDivSize); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MCoefMod); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MHstLMod); if (RegCheckErr(RF, RoutineName)) return @@ -968,6 +1254,8 @@ subroutine Morison_CopyMemberType(SrcMemberTypeData, DstMemberTypeData, CtrlCode DstMemberTypeData%k = SrcMemberTypeData%k DstMemberTypeData%kkt = SrcMemberTypeData%kkt DstMemberTypeData%Ak = SrcMemberTypeData%Ak + DstMemberTypeData%x_hat = SrcMemberTypeData%x_hat + DstMemberTypeData%y_hat = SrcMemberTypeData%y_hat if (allocated(SrcMemberTypeData%R)) then LB(1:1) = lbound(SrcMemberTypeData%R) UB(1:1) = ubound(SrcMemberTypeData%R) @@ -1016,6 +1304,102 @@ subroutine Morison_CopyMemberType(SrcMemberTypeData, DstMemberTypeData, CtrlCode end if DstMemberTypeData%Rin = SrcMemberTypeData%Rin end if + if (allocated(SrcMemberTypeData%Sa)) then + LB(1:1) = lbound(SrcMemberTypeData%Sa) + UB(1:1) = ubound(SrcMemberTypeData%Sa) + if (.not. allocated(DstMemberTypeData%Sa)) then + allocate(DstMemberTypeData%Sa(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Sa.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%Sa = SrcMemberTypeData%Sa + end if + if (allocated(SrcMemberTypeData%SaMG)) then + LB(1:1) = lbound(SrcMemberTypeData%SaMG) + UB(1:1) = ubound(SrcMemberTypeData%SaMG) + if (.not. allocated(DstMemberTypeData%SaMG)) then + allocate(DstMemberTypeData%SaMG(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%SaMG.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%SaMG = SrcMemberTypeData%SaMG + end if + if (allocated(SrcMemberTypeData%SaMGB)) then + LB(1:1) = lbound(SrcMemberTypeData%SaMGB) + UB(1:1) = ubound(SrcMemberTypeData%SaMGB) + if (.not. allocated(DstMemberTypeData%SaMGB)) then + allocate(DstMemberTypeData%SaMGB(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%SaMGB.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%SaMGB = SrcMemberTypeData%SaMGB + end if + if (allocated(SrcMemberTypeData%Sain)) then + LB(1:1) = lbound(SrcMemberTypeData%Sain) + UB(1:1) = ubound(SrcMemberTypeData%Sain) + if (.not. allocated(DstMemberTypeData%Sain)) then + allocate(DstMemberTypeData%Sain(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Sain.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%Sain = SrcMemberTypeData%Sain + end if + if (allocated(SrcMemberTypeData%Sb)) then + LB(1:1) = lbound(SrcMemberTypeData%Sb) + UB(1:1) = ubound(SrcMemberTypeData%Sb) + if (.not. allocated(DstMemberTypeData%Sb)) then + allocate(DstMemberTypeData%Sb(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Sb.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%Sb = SrcMemberTypeData%Sb + end if + if (allocated(SrcMemberTypeData%SbMG)) then + LB(1:1) = lbound(SrcMemberTypeData%SbMG) + UB(1:1) = ubound(SrcMemberTypeData%SbMG) + if (.not. allocated(DstMemberTypeData%SbMG)) then + allocate(DstMemberTypeData%SbMG(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%SbMG.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%SbMG = SrcMemberTypeData%SbMG + end if + if (allocated(SrcMemberTypeData%SbMGB)) then + LB(1:1) = lbound(SrcMemberTypeData%SbMGB) + UB(1:1) = ubound(SrcMemberTypeData%SbMGB) + if (.not. allocated(DstMemberTypeData%SbMGB)) then + allocate(DstMemberTypeData%SbMGB(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%SbMGB.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%SbMGB = SrcMemberTypeData%SbMGB + end if + if (allocated(SrcMemberTypeData%Sbin)) then + LB(1:1) = lbound(SrcMemberTypeData%Sbin) + UB(1:1) = ubound(SrcMemberTypeData%Sbin) + if (.not. allocated(DstMemberTypeData%Sbin)) then + allocate(DstMemberTypeData%Sbin(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Sbin.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%Sbin = SrcMemberTypeData%Sbin + end if if (allocated(SrcMemberTypeData%tMG)) then LB(1:1) = lbound(SrcMemberTypeData%tMG) UB(1:1) = ubound(SrcMemberTypeData%tMG) @@ -1076,10 +1460,83 @@ subroutine Morison_CopyMemberType(SrcMemberTypeData, DstMemberTypeData, CtrlCode end if DstMemberTypeData%dRdl_in = SrcMemberTypeData%dRdl_in end if + if (allocated(SrcMemberTypeData%dSadl_mg)) then + LB(1:1) = lbound(SrcMemberTypeData%dSadl_mg) + UB(1:1) = ubound(SrcMemberTypeData%dSadl_mg) + if (.not. allocated(DstMemberTypeData%dSadl_mg)) then + allocate(DstMemberTypeData%dSadl_mg(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%dSadl_mg.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%dSadl_mg = SrcMemberTypeData%dSadl_mg + end if + if (allocated(SrcMemberTypeData%dSadl_mg_b)) then + LB(1:1) = lbound(SrcMemberTypeData%dSadl_mg_b) + UB(1:1) = ubound(SrcMemberTypeData%dSadl_mg_b) + if (.not. allocated(DstMemberTypeData%dSadl_mg_b)) then + allocate(DstMemberTypeData%dSadl_mg_b(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%dSadl_mg_b.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%dSadl_mg_b = SrcMemberTypeData%dSadl_mg_b + end if + if (allocated(SrcMemberTypeData%dSadl_in)) then + LB(1:1) = lbound(SrcMemberTypeData%dSadl_in) + UB(1:1) = ubound(SrcMemberTypeData%dSadl_in) + if (.not. allocated(DstMemberTypeData%dSadl_in)) then + allocate(DstMemberTypeData%dSadl_in(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%dSadl_in.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%dSadl_in = SrcMemberTypeData%dSadl_in + end if + if (allocated(SrcMemberTypeData%dSbdl_mg)) then + LB(1:1) = lbound(SrcMemberTypeData%dSbdl_mg) + UB(1:1) = ubound(SrcMemberTypeData%dSbdl_mg) + if (.not. allocated(DstMemberTypeData%dSbdl_mg)) then + allocate(DstMemberTypeData%dSbdl_mg(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%dSbdl_mg.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%dSbdl_mg = SrcMemberTypeData%dSbdl_mg + end if + if (allocated(SrcMemberTypeData%dSbdl_mg_b)) then + LB(1:1) = lbound(SrcMemberTypeData%dSbdl_mg_b) + UB(1:1) = ubound(SrcMemberTypeData%dSbdl_mg_b) + if (.not. allocated(DstMemberTypeData%dSbdl_mg_b)) then + allocate(DstMemberTypeData%dSbdl_mg_b(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%dSbdl_mg_b.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%dSbdl_mg_b = SrcMemberTypeData%dSbdl_mg_b + end if + if (allocated(SrcMemberTypeData%dSbdl_in)) then + LB(1:1) = lbound(SrcMemberTypeData%dSbdl_in) + UB(1:1) = ubound(SrcMemberTypeData%dSbdl_in) + if (.not. allocated(DstMemberTypeData%dSbdl_in)) then + allocate(DstMemberTypeData%dSbdl_in(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%dSbdl_in.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%dSbdl_in = SrcMemberTypeData%dSbdl_in + end if DstMemberTypeData%Vinner = SrcMemberTypeData%Vinner DstMemberTypeData%Vouter = SrcMemberTypeData%Vouter DstMemberTypeData%Vballast = SrcMemberTypeData%Vballast DstMemberTypeData%Vsubmerged = SrcMemberTypeData%Vsubmerged + DstMemberTypeData%elem_fill = SrcMemberTypeData%elem_fill DstMemberTypeData%l_fill = SrcMemberTypeData%l_fill DstMemberTypeData%h_fill = SrcMemberTypeData%h_fill DstMemberTypeData%z_overfill = SrcMemberTypeData%z_overfill @@ -1159,6 +1616,54 @@ subroutine Morison_CopyMemberType(SrcMemberTypeData, DstMemberTypeData, CtrlCode end if DstMemberTypeData%Ca = SrcMemberTypeData%Ca end if + if (allocated(SrcMemberTypeData%CdA)) then + LB(1:1) = lbound(SrcMemberTypeData%CdA) + UB(1:1) = ubound(SrcMemberTypeData%CdA) + if (.not. allocated(DstMemberTypeData%CdA)) then + allocate(DstMemberTypeData%CdA(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%CdA.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%CdA = SrcMemberTypeData%CdA + end if + if (allocated(SrcMemberTypeData%CaA)) then + LB(1:1) = lbound(SrcMemberTypeData%CaA) + UB(1:1) = ubound(SrcMemberTypeData%CaA) + if (.not. allocated(DstMemberTypeData%CaA)) then + allocate(DstMemberTypeData%CaA(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%CaA.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%CaA = SrcMemberTypeData%CaA + end if + if (allocated(SrcMemberTypeData%CdB)) then + LB(1:1) = lbound(SrcMemberTypeData%CdB) + UB(1:1) = ubound(SrcMemberTypeData%CdB) + if (.not. allocated(DstMemberTypeData%CdB)) then + allocate(DstMemberTypeData%CdB(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%CdB.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%CdB = SrcMemberTypeData%CdB + end if + if (allocated(SrcMemberTypeData%CaB)) then + LB(1:1) = lbound(SrcMemberTypeData%CaB) + UB(1:1) = ubound(SrcMemberTypeData%CaB) + if (.not. allocated(DstMemberTypeData%CaB)) then + allocate(DstMemberTypeData%CaB(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%CaB.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%CaB = SrcMemberTypeData%CaB + end if if (allocated(SrcMemberTypeData%Cp)) then LB(1:1) = lbound(SrcMemberTypeData%Cp) UB(1:1) = ubound(SrcMemberTypeData%Cp) @@ -1315,6 +1820,54 @@ subroutine Morison_CopyMemberType(SrcMemberTypeData, DstMemberTypeData, CtrlCode end if DstMemberTypeData%I_rfb_u = SrcMemberTypeData%I_rfb_u end if + if (allocated(SrcMemberTypeData%I_xfb_l)) then + LB(1:1) = lbound(SrcMemberTypeData%I_xfb_l) + UB(1:1) = ubound(SrcMemberTypeData%I_xfb_l) + if (.not. allocated(DstMemberTypeData%I_xfb_l)) then + allocate(DstMemberTypeData%I_xfb_l(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_xfb_l.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%I_xfb_l = SrcMemberTypeData%I_xfb_l + end if + if (allocated(SrcMemberTypeData%I_xfb_u)) then + LB(1:1) = lbound(SrcMemberTypeData%I_xfb_u) + UB(1:1) = ubound(SrcMemberTypeData%I_xfb_u) + if (.not. allocated(DstMemberTypeData%I_xfb_u)) then + allocate(DstMemberTypeData%I_xfb_u(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_xfb_u.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%I_xfb_u = SrcMemberTypeData%I_xfb_u + end if + if (allocated(SrcMemberTypeData%I_yfb_l)) then + LB(1:1) = lbound(SrcMemberTypeData%I_yfb_l) + UB(1:1) = ubound(SrcMemberTypeData%I_yfb_l) + if (.not. allocated(DstMemberTypeData%I_yfb_l)) then + allocate(DstMemberTypeData%I_yfb_l(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_yfb_l.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%I_yfb_l = SrcMemberTypeData%I_yfb_l + end if + if (allocated(SrcMemberTypeData%I_yfb_u)) then + LB(1:1) = lbound(SrcMemberTypeData%I_yfb_u) + UB(1:1) = ubound(SrcMemberTypeData%I_yfb_u) + if (.not. allocated(DstMemberTypeData%I_yfb_u)) then + allocate(DstMemberTypeData%I_yfb_u(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_yfb_u.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%I_yfb_u = SrcMemberTypeData%I_yfb_u + end if if (allocated(SrcMemberTypeData%m_mg_l)) then LB(1:1) = lbound(SrcMemberTypeData%m_mg_l) UB(1:1) = ubound(SrcMemberTypeData%m_mg_l) @@ -1411,43 +1964,57 @@ subroutine Morison_CopyMemberType(SrcMemberTypeData, DstMemberTypeData, CtrlCode end if DstMemberTypeData%I_rmg_u = SrcMemberTypeData%I_rmg_u end if - if (allocated(SrcMemberTypeData%Cfl_fb)) then - LB(1:1) = lbound(SrcMemberTypeData%Cfl_fb) - UB(1:1) = ubound(SrcMemberTypeData%Cfl_fb) - if (.not. allocated(DstMemberTypeData%Cfl_fb)) then - allocate(DstMemberTypeData%Cfl_fb(LB(1):UB(1)), stat=ErrStat2) + if (allocated(SrcMemberTypeData%I_xmg_l)) then + LB(1:1) = lbound(SrcMemberTypeData%I_xmg_l) + UB(1:1) = ubound(SrcMemberTypeData%I_xmg_l) + if (.not. allocated(DstMemberTypeData%I_xmg_l)) then + allocate(DstMemberTypeData%I_xmg_l(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_xmg_l.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMemberTypeData%I_xmg_l = SrcMemberTypeData%I_xmg_l + end if + if (allocated(SrcMemberTypeData%I_xmg_u)) then + LB(1:1) = lbound(SrcMemberTypeData%I_xmg_u) + UB(1:1) = ubound(SrcMemberTypeData%I_xmg_u) + if (.not. allocated(DstMemberTypeData%I_xmg_u)) then + allocate(DstMemberTypeData%I_xmg_u(LB(1):UB(1)), stat=ErrStat2) if (ErrStat2 /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Cfl_fb.', ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_xmg_u.', ErrStat, ErrMsg, RoutineName) return end if end if - DstMemberTypeData%Cfl_fb = SrcMemberTypeData%Cfl_fb + DstMemberTypeData%I_xmg_u = SrcMemberTypeData%I_xmg_u end if - if (allocated(SrcMemberTypeData%Cfr_fb)) then - LB(1:1) = lbound(SrcMemberTypeData%Cfr_fb) - UB(1:1) = ubound(SrcMemberTypeData%Cfr_fb) - if (.not. allocated(DstMemberTypeData%Cfr_fb)) then - allocate(DstMemberTypeData%Cfr_fb(LB(1):UB(1)), stat=ErrStat2) + if (allocated(SrcMemberTypeData%I_ymg_l)) then + LB(1:1) = lbound(SrcMemberTypeData%I_ymg_l) + UB(1:1) = ubound(SrcMemberTypeData%I_ymg_l) + if (.not. allocated(DstMemberTypeData%I_ymg_l)) then + allocate(DstMemberTypeData%I_ymg_l(LB(1):UB(1)), stat=ErrStat2) if (ErrStat2 /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%Cfr_fb.', ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_ymg_l.', ErrStat, ErrMsg, RoutineName) return end if end if - DstMemberTypeData%Cfr_fb = SrcMemberTypeData%Cfr_fb + DstMemberTypeData%I_ymg_l = SrcMemberTypeData%I_ymg_l end if - if (allocated(SrcMemberTypeData%CM0_fb)) then - LB(1:1) = lbound(SrcMemberTypeData%CM0_fb) - UB(1:1) = ubound(SrcMemberTypeData%CM0_fb) - if (.not. allocated(DstMemberTypeData%CM0_fb)) then - allocate(DstMemberTypeData%CM0_fb(LB(1):UB(1)), stat=ErrStat2) + if (allocated(SrcMemberTypeData%I_ymg_u)) then + LB(1:1) = lbound(SrcMemberTypeData%I_ymg_u) + UB(1:1) = ubound(SrcMemberTypeData%I_ymg_u) + if (.not. allocated(DstMemberTypeData%I_ymg_u)) then + allocate(DstMemberTypeData%I_ymg_u(LB(1):UB(1)), stat=ErrStat2) if (ErrStat2 /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%CM0_fb.', ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating DstMemberTypeData%I_ymg_u.', ErrStat, ErrMsg, RoutineName) return end if end if - DstMemberTypeData%CM0_fb = SrcMemberTypeData%CM0_fb + DstMemberTypeData%I_ymg_u = SrcMemberTypeData%I_ymg_u end if DstMemberTypeData%MGvolume = SrcMemberTypeData%MGvolume + DstMemberTypeData%MSecGeom = SrcMemberTypeData%MSecGeom + DstMemberTypeData%MSpinOrient = SrcMemberTypeData%MSpinOrient DstMemberTypeData%MDivSize = SrcMemberTypeData%MDivSize DstMemberTypeData%MCoefMod = SrcMemberTypeData%MCoefMod DstMemberTypeData%MmbrCoefIDIndx = SrcMemberTypeData%MmbrCoefIDIndx @@ -1482,6 +2049,30 @@ subroutine Morison_DestroyMemberType(MemberTypeData, ErrStat, ErrMsg) if (allocated(MemberTypeData%Rin)) then deallocate(MemberTypeData%Rin) end if + if (allocated(MemberTypeData%Sa)) then + deallocate(MemberTypeData%Sa) + end if + if (allocated(MemberTypeData%SaMG)) then + deallocate(MemberTypeData%SaMG) + end if + if (allocated(MemberTypeData%SaMGB)) then + deallocate(MemberTypeData%SaMGB) + end if + if (allocated(MemberTypeData%Sain)) then + deallocate(MemberTypeData%Sain) + end if + if (allocated(MemberTypeData%Sb)) then + deallocate(MemberTypeData%Sb) + end if + if (allocated(MemberTypeData%SbMG)) then + deallocate(MemberTypeData%SbMG) + end if + if (allocated(MemberTypeData%SbMGB)) then + deallocate(MemberTypeData%SbMGB) + end if + if (allocated(MemberTypeData%Sbin)) then + deallocate(MemberTypeData%Sbin) + end if if (allocated(MemberTypeData%tMG)) then deallocate(MemberTypeData%tMG) end if @@ -1497,6 +2088,24 @@ subroutine Morison_DestroyMemberType(MemberTypeData, ErrStat, ErrMsg) if (allocated(MemberTypeData%dRdl_in)) then deallocate(MemberTypeData%dRdl_in) end if + if (allocated(MemberTypeData%dSadl_mg)) then + deallocate(MemberTypeData%dSadl_mg) + end if + if (allocated(MemberTypeData%dSadl_mg_b)) then + deallocate(MemberTypeData%dSadl_mg_b) + end if + if (allocated(MemberTypeData%dSadl_in)) then + deallocate(MemberTypeData%dSadl_in) + end if + if (allocated(MemberTypeData%dSbdl_mg)) then + deallocate(MemberTypeData%dSbdl_mg) + end if + if (allocated(MemberTypeData%dSbdl_mg_b)) then + deallocate(MemberTypeData%dSbdl_mg_b) + end if + if (allocated(MemberTypeData%dSbdl_in)) then + deallocate(MemberTypeData%dSbdl_in) + end if if (allocated(MemberTypeData%floodstatus)) then deallocate(MemberTypeData%floodstatus) end if @@ -1515,6 +2124,18 @@ subroutine Morison_DestroyMemberType(MemberTypeData, ErrStat, ErrMsg) if (allocated(MemberTypeData%Ca)) then deallocate(MemberTypeData%Ca) end if + if (allocated(MemberTypeData%CdA)) then + deallocate(MemberTypeData%CdA) + end if + if (allocated(MemberTypeData%CaA)) then + deallocate(MemberTypeData%CaA) + end if + if (allocated(MemberTypeData%CdB)) then + deallocate(MemberTypeData%CdB) + end if + if (allocated(MemberTypeData%CaB)) then + deallocate(MemberTypeData%CaB) + end if if (allocated(MemberTypeData%Cp)) then deallocate(MemberTypeData%Cp) end if @@ -1554,6 +2175,18 @@ subroutine Morison_DestroyMemberType(MemberTypeData, ErrStat, ErrMsg) if (allocated(MemberTypeData%I_rfb_u)) then deallocate(MemberTypeData%I_rfb_u) end if + if (allocated(MemberTypeData%I_xfb_l)) then + deallocate(MemberTypeData%I_xfb_l) + end if + if (allocated(MemberTypeData%I_xfb_u)) then + deallocate(MemberTypeData%I_xfb_u) + end if + if (allocated(MemberTypeData%I_yfb_l)) then + deallocate(MemberTypeData%I_yfb_l) + end if + if (allocated(MemberTypeData%I_yfb_u)) then + deallocate(MemberTypeData%I_yfb_u) + end if if (allocated(MemberTypeData%m_mg_l)) then deallocate(MemberTypeData%m_mg_l) end if @@ -1578,14 +2211,17 @@ subroutine Morison_DestroyMemberType(MemberTypeData, ErrStat, ErrMsg) if (allocated(MemberTypeData%I_rmg_u)) then deallocate(MemberTypeData%I_rmg_u) end if - if (allocated(MemberTypeData%Cfl_fb)) then - deallocate(MemberTypeData%Cfl_fb) + if (allocated(MemberTypeData%I_xmg_l)) then + deallocate(MemberTypeData%I_xmg_l) + end if + if (allocated(MemberTypeData%I_xmg_u)) then + deallocate(MemberTypeData%I_xmg_u) end if - if (allocated(MemberTypeData%Cfr_fb)) then - deallocate(MemberTypeData%Cfr_fb) + if (allocated(MemberTypeData%I_ymg_l)) then + deallocate(MemberTypeData%I_ymg_l) end if - if (allocated(MemberTypeData%CM0_fb)) then - deallocate(MemberTypeData%CM0_fb) + if (allocated(MemberTypeData%I_ymg_u)) then + deallocate(MemberTypeData%I_ymg_u) end if end subroutine @@ -1603,19 +2239,36 @@ subroutine Morison_PackMemberType(RF, Indata) call RegPack(RF, InData%k) call RegPack(RF, InData%kkt) call RegPack(RF, InData%Ak) + call RegPack(RF, InData%x_hat) + call RegPack(RF, InData%y_hat) call RegPackAlloc(RF, InData%R) call RegPackAlloc(RF, InData%RMG) call RegPackAlloc(RF, InData%RMGB) call RegPackAlloc(RF, InData%Rin) + call RegPackAlloc(RF, InData%Sa) + call RegPackAlloc(RF, InData%SaMG) + call RegPackAlloc(RF, InData%SaMGB) + call RegPackAlloc(RF, InData%Sain) + call RegPackAlloc(RF, InData%Sb) + call RegPackAlloc(RF, InData%SbMG) + call RegPackAlloc(RF, InData%SbMGB) + call RegPackAlloc(RF, InData%Sbin) call RegPackAlloc(RF, InData%tMG) call RegPackAlloc(RF, InData%MGdensity) call RegPackAlloc(RF, InData%dRdl_mg) call RegPackAlloc(RF, InData%dRdl_mg_b) call RegPackAlloc(RF, InData%dRdl_in) + call RegPackAlloc(RF, InData%dSadl_mg) + call RegPackAlloc(RF, InData%dSadl_mg_b) + call RegPackAlloc(RF, InData%dSadl_in) + call RegPackAlloc(RF, InData%dSbdl_mg) + call RegPackAlloc(RF, InData%dSbdl_mg_b) + call RegPackAlloc(RF, InData%dSbdl_in) call RegPack(RF, InData%Vinner) call RegPack(RF, InData%Vouter) call RegPack(RF, InData%Vballast) call RegPack(RF, InData%Vsubmerged) + call RegPack(RF, InData%elem_fill) call RegPack(RF, InData%l_fill) call RegPack(RF, InData%h_fill) call RegPack(RF, InData%z_overfill) @@ -1629,6 +2282,10 @@ subroutine Morison_PackMemberType(RF, Indata) call RegPackAlloc(RF, InData%alpha_fb_star) call RegPackAlloc(RF, InData%Cd) call RegPackAlloc(RF, InData%Ca) + call RegPackAlloc(RF, InData%CdA) + call RegPackAlloc(RF, InData%CaA) + call RegPackAlloc(RF, InData%CdB) + call RegPackAlloc(RF, InData%CaB) call RegPackAlloc(RF, InData%Cp) call RegPackAlloc(RF, InData%AxCd) call RegPackAlloc(RF, InData%AxCa) @@ -1642,6 +2299,10 @@ subroutine Morison_PackMemberType(RF, Indata) call RegPackAlloc(RF, InData%I_lfb_u) call RegPackAlloc(RF, InData%I_rfb_l) call RegPackAlloc(RF, InData%I_rfb_u) + call RegPackAlloc(RF, InData%I_xfb_l) + call RegPackAlloc(RF, InData%I_xfb_u) + call RegPackAlloc(RF, InData%I_yfb_l) + call RegPackAlloc(RF, InData%I_yfb_u) call RegPackAlloc(RF, InData%m_mg_l) call RegPackAlloc(RF, InData%m_mg_u) call RegPackAlloc(RF, InData%h_cmg_l) @@ -1650,10 +2311,13 @@ subroutine Morison_PackMemberType(RF, Indata) call RegPackAlloc(RF, InData%I_lmg_u) call RegPackAlloc(RF, InData%I_rmg_l) call RegPackAlloc(RF, InData%I_rmg_u) - call RegPackAlloc(RF, InData%Cfl_fb) - call RegPackAlloc(RF, InData%Cfr_fb) - call RegPackAlloc(RF, InData%CM0_fb) + call RegPackAlloc(RF, InData%I_xmg_l) + call RegPackAlloc(RF, InData%I_xmg_u) + call RegPackAlloc(RF, InData%I_ymg_l) + call RegPackAlloc(RF, InData%I_ymg_u) call RegPack(RF, InData%MGvolume) + call RegPack(RF, InData%MSecGeom) + call RegPack(RF, InData%MSpinOrient) call RegPack(RF, InData%MDivSize) call RegPack(RF, InData%MCoefMod) call RegPack(RF, InData%MmbrCoefIDIndx) @@ -1684,19 +2348,36 @@ subroutine Morison_UnPackMemberType(RF, OutData) call RegUnpack(RF, OutData%k); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%kkt); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Ak); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%x_hat); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%y_hat); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%R); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%RMG); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%RMGB); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Rin); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%Sa); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%SaMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%SaMGB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%Sain); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%Sb); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%SbMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%SbMGB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%Sbin); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%tMG); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%MGdensity); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%dRdl_mg); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%dRdl_mg_b); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%dRdl_in); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%dSadl_mg); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%dSadl_mg_b); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%dSadl_in); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%dSbdl_mg); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%dSbdl_mg_b); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%dSbdl_in); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Vinner); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Vouter); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Vballast); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Vsubmerged); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%elem_fill); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%l_fill); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%h_fill); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%z_overfill); if (RegCheckErr(RF, RoutineName)) return @@ -1710,6 +2391,10 @@ subroutine Morison_UnPackMemberType(RF, OutData) call RegUnpackAlloc(RF, OutData%alpha_fb_star); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Cd); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Ca); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%CdA); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%CaA); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%CdB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%CaB); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Cp); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%AxCd); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%AxCa); if (RegCheckErr(RF, RoutineName)) return @@ -1723,6 +2408,10 @@ subroutine Morison_UnPackMemberType(RF, OutData) call RegUnpackAlloc(RF, OutData%I_lfb_u); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%I_rfb_l); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%I_rfb_u); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%I_xfb_l); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%I_xfb_u); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%I_yfb_l); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%I_yfb_u); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%m_mg_l); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%m_mg_u); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%h_cmg_l); if (RegCheckErr(RF, RoutineName)) return @@ -1731,10 +2420,13 @@ subroutine Morison_UnPackMemberType(RF, OutData) call RegUnpackAlloc(RF, OutData%I_lmg_u); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%I_rmg_l); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%I_rmg_u); if (RegCheckErr(RF, RoutineName)) return - call RegUnpackAlloc(RF, OutData%Cfl_fb); if (RegCheckErr(RF, RoutineName)) return - call RegUnpackAlloc(RF, OutData%Cfr_fb); if (RegCheckErr(RF, RoutineName)) return - call RegUnpackAlloc(RF, OutData%CM0_fb); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%I_xmg_l); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%I_xmg_u); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%I_ymg_l); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%I_ymg_u); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MGvolume); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MSecGeom); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MSpinOrient); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MDivSize); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MCoefMod); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MmbrCoefIDIndx); if (RegCheckErr(RF, RoutineName)) return @@ -1974,60 +2666,60 @@ subroutine Morison_UnPackMemberLoads(RF, OutData) call RegUnpackAlloc(RF, OutData%F_DP); if (RegCheckErr(RF, RoutineName)) return end subroutine -subroutine Morison_CopyCoefMembers(SrcCoefMembersData, DstCoefMembersData, CtrlCode, ErrStat, ErrMsg) - type(Morison_CoefMembers), intent(in) :: SrcCoefMembersData - type(Morison_CoefMembers), intent(inout) :: DstCoefMembersData +subroutine Morison_CopyCoefMembersCyl(SrcCoefMembersCylData, DstCoefMembersCylData, CtrlCode, ErrStat, ErrMsg) + type(Morison_CoefMembersCyl), intent(in) :: SrcCoefMembersCylData + type(Morison_CoefMembersCyl), intent(inout) :: DstCoefMembersCylData integer(IntKi), intent(in ) :: CtrlCode integer(IntKi), intent( out) :: ErrStat character(*), intent( out) :: ErrMsg - character(*), parameter :: RoutineName = 'Morison_CopyCoefMembers' + character(*), parameter :: RoutineName = 'Morison_CopyCoefMembersCyl' ErrStat = ErrID_None ErrMsg = '' - DstCoefMembersData%MemberID = SrcCoefMembersData%MemberID - DstCoefMembersData%MemberCd1 = SrcCoefMembersData%MemberCd1 - DstCoefMembersData%MemberCd2 = SrcCoefMembersData%MemberCd2 - DstCoefMembersData%MemberCdMG1 = SrcCoefMembersData%MemberCdMG1 - DstCoefMembersData%MemberCdMG2 = SrcCoefMembersData%MemberCdMG2 - DstCoefMembersData%MemberCa1 = SrcCoefMembersData%MemberCa1 - DstCoefMembersData%MemberCa2 = SrcCoefMembersData%MemberCa2 - DstCoefMembersData%MemberCaMG1 = SrcCoefMembersData%MemberCaMG1 - DstCoefMembersData%MemberCaMG2 = SrcCoefMembersData%MemberCaMG2 - DstCoefMembersData%MemberCp1 = SrcCoefMembersData%MemberCp1 - DstCoefMembersData%MemberCp2 = SrcCoefMembersData%MemberCp2 - DstCoefMembersData%MemberCpMG1 = SrcCoefMembersData%MemberCpMG1 - DstCoefMembersData%MemberCpMG2 = SrcCoefMembersData%MemberCpMG2 - DstCoefMembersData%MemberAxCd1 = SrcCoefMembersData%MemberAxCd1 - DstCoefMembersData%MemberAxCd2 = SrcCoefMembersData%MemberAxCd2 - DstCoefMembersData%MemberAxCdMG1 = SrcCoefMembersData%MemberAxCdMG1 - DstCoefMembersData%MemberAxCdMG2 = SrcCoefMembersData%MemberAxCdMG2 - DstCoefMembersData%MemberAxCa1 = SrcCoefMembersData%MemberAxCa1 - DstCoefMembersData%MemberAxCa2 = SrcCoefMembersData%MemberAxCa2 - DstCoefMembersData%MemberAxCaMG1 = SrcCoefMembersData%MemberAxCaMG1 - DstCoefMembersData%MemberAxCaMG2 = SrcCoefMembersData%MemberAxCaMG2 - DstCoefMembersData%MemberAxCp1 = SrcCoefMembersData%MemberAxCp1 - DstCoefMembersData%MemberAxCp2 = SrcCoefMembersData%MemberAxCp2 - DstCoefMembersData%MemberAxCpMG1 = SrcCoefMembersData%MemberAxCpMG1 - DstCoefMembersData%MemberAxCpMG2 = SrcCoefMembersData%MemberAxCpMG2 - DstCoefMembersData%MemberCb1 = SrcCoefMembersData%MemberCb1 - DstCoefMembersData%MemberCb2 = SrcCoefMembersData%MemberCb2 - DstCoefMembersData%MemberCbMG1 = SrcCoefMembersData%MemberCbMG1 - DstCoefMembersData%MemberCbMG2 = SrcCoefMembersData%MemberCbMG2 - DstCoefMembersData%MemberMCF = SrcCoefMembersData%MemberMCF + DstCoefMembersCylData%MemberID = SrcCoefMembersCylData%MemberID + DstCoefMembersCylData%MemberCd1 = SrcCoefMembersCylData%MemberCd1 + DstCoefMembersCylData%MemberCd2 = SrcCoefMembersCylData%MemberCd2 + DstCoefMembersCylData%MemberCdMG1 = SrcCoefMembersCylData%MemberCdMG1 + DstCoefMembersCylData%MemberCdMG2 = SrcCoefMembersCylData%MemberCdMG2 + DstCoefMembersCylData%MemberCa1 = SrcCoefMembersCylData%MemberCa1 + DstCoefMembersCylData%MemberCa2 = SrcCoefMembersCylData%MemberCa2 + DstCoefMembersCylData%MemberCaMG1 = SrcCoefMembersCylData%MemberCaMG1 + DstCoefMembersCylData%MemberCaMG2 = SrcCoefMembersCylData%MemberCaMG2 + DstCoefMembersCylData%MemberCp1 = SrcCoefMembersCylData%MemberCp1 + DstCoefMembersCylData%MemberCp2 = SrcCoefMembersCylData%MemberCp2 + DstCoefMembersCylData%MemberCpMG1 = SrcCoefMembersCylData%MemberCpMG1 + DstCoefMembersCylData%MemberCpMG2 = SrcCoefMembersCylData%MemberCpMG2 + DstCoefMembersCylData%MemberAxCd1 = SrcCoefMembersCylData%MemberAxCd1 + DstCoefMembersCylData%MemberAxCd2 = SrcCoefMembersCylData%MemberAxCd2 + DstCoefMembersCylData%MemberAxCdMG1 = SrcCoefMembersCylData%MemberAxCdMG1 + DstCoefMembersCylData%MemberAxCdMG2 = SrcCoefMembersCylData%MemberAxCdMG2 + DstCoefMembersCylData%MemberAxCa1 = SrcCoefMembersCylData%MemberAxCa1 + DstCoefMembersCylData%MemberAxCa2 = SrcCoefMembersCylData%MemberAxCa2 + DstCoefMembersCylData%MemberAxCaMG1 = SrcCoefMembersCylData%MemberAxCaMG1 + DstCoefMembersCylData%MemberAxCaMG2 = SrcCoefMembersCylData%MemberAxCaMG2 + DstCoefMembersCylData%MemberAxCp1 = SrcCoefMembersCylData%MemberAxCp1 + DstCoefMembersCylData%MemberAxCp2 = SrcCoefMembersCylData%MemberAxCp2 + DstCoefMembersCylData%MemberAxCpMG1 = SrcCoefMembersCylData%MemberAxCpMG1 + DstCoefMembersCylData%MemberAxCpMG2 = SrcCoefMembersCylData%MemberAxCpMG2 + DstCoefMembersCylData%MemberCb1 = SrcCoefMembersCylData%MemberCb1 + DstCoefMembersCylData%MemberCb2 = SrcCoefMembersCylData%MemberCb2 + DstCoefMembersCylData%MemberCbMG1 = SrcCoefMembersCylData%MemberCbMG1 + DstCoefMembersCylData%MemberCbMG2 = SrcCoefMembersCylData%MemberCbMG2 + DstCoefMembersCylData%MemberMCF = SrcCoefMembersCylData%MemberMCF end subroutine -subroutine Morison_DestroyCoefMembers(CoefMembersData, ErrStat, ErrMsg) - type(Morison_CoefMembers), intent(inout) :: CoefMembersData +subroutine Morison_DestroyCoefMembersCyl(CoefMembersCylData, ErrStat, ErrMsg) + type(Morison_CoefMembersCyl), intent(inout) :: CoefMembersCylData integer(IntKi), intent( out) :: ErrStat character(*), intent( out) :: ErrMsg - character(*), parameter :: RoutineName = 'Morison_DestroyCoefMembers' + character(*), parameter :: RoutineName = 'Morison_DestroyCoefMembersCyl' ErrStat = ErrID_None ErrMsg = '' end subroutine -subroutine Morison_PackCoefMembers(RF, Indata) +subroutine Morison_PackCoefMembersCyl(RF, Indata) type(RegFile), intent(inout) :: RF - type(Morison_CoefMembers), intent(in) :: InData - character(*), parameter :: RoutineName = 'Morison_PackCoefMembers' + type(Morison_CoefMembersCyl), intent(in) :: InData + character(*), parameter :: RoutineName = 'Morison_PackCoefMembersCyl' if (RF%ErrStat >= AbortErrLev) return call RegPack(RF, InData%MemberID) call RegPack(RF, InData%MemberCd1) @@ -2062,10 +2754,10 @@ subroutine Morison_PackCoefMembers(RF, Indata) if (RegCheckErr(RF, RoutineName)) return end subroutine -subroutine Morison_UnPackCoefMembers(RF, OutData) +subroutine Morison_UnPackCoefMembersCyl(RF, OutData) type(RegFile), intent(inout) :: RF - type(Morison_CoefMembers), intent(inout) :: OutData - character(*), parameter :: RoutineName = 'Morison_UnPackCoefMembers' + type(Morison_CoefMembersCyl), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'Morison_UnPackCoefMembersCyl' if (RF%ErrStat /= ErrID_None) return call RegUnpack(RF, OutData%MemberID); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%MemberCd1); if (RegCheckErr(RF, RoutineName)) return @@ -2099,6 +2791,155 @@ subroutine Morison_UnPackCoefMembers(RF, OutData) call RegUnpack(RF, OutData%MemberMCF); if (RegCheckErr(RF, RoutineName)) return end subroutine +subroutine Morison_CopyCoefMembersRec(SrcCoefMembersRecData, DstCoefMembersRecData, CtrlCode, ErrStat, ErrMsg) + type(Morison_CoefMembersRec), intent(in) :: SrcCoefMembersRecData + type(Morison_CoefMembersRec), intent(inout) :: DstCoefMembersRecData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'Morison_CopyCoefMembersRec' + ErrStat = ErrID_None + ErrMsg = '' + DstCoefMembersRecData%MemberID = SrcCoefMembersRecData%MemberID + DstCoefMembersRecData%MemberCdA1 = SrcCoefMembersRecData%MemberCdA1 + DstCoefMembersRecData%MemberCdA2 = SrcCoefMembersRecData%MemberCdA2 + DstCoefMembersRecData%MemberCdAMG1 = SrcCoefMembersRecData%MemberCdAMG1 + DstCoefMembersRecData%MemberCdAMG2 = SrcCoefMembersRecData%MemberCdAMG2 + DstCoefMembersRecData%MemberCdB1 = SrcCoefMembersRecData%MemberCdB1 + DstCoefMembersRecData%MemberCdB2 = SrcCoefMembersRecData%MemberCdB2 + DstCoefMembersRecData%MemberCdBMG1 = SrcCoefMembersRecData%MemberCdBMG1 + DstCoefMembersRecData%MemberCdBMG2 = SrcCoefMembersRecData%MemberCdBMG2 + DstCoefMembersRecData%MemberCaA1 = SrcCoefMembersRecData%MemberCaA1 + DstCoefMembersRecData%MemberCaA2 = SrcCoefMembersRecData%MemberCaA2 + DstCoefMembersRecData%MemberCaAMG1 = SrcCoefMembersRecData%MemberCaAMG1 + DstCoefMembersRecData%MemberCaAMG2 = SrcCoefMembersRecData%MemberCaAMG2 + DstCoefMembersRecData%MemberCaB1 = SrcCoefMembersRecData%MemberCaB1 + DstCoefMembersRecData%MemberCaB2 = SrcCoefMembersRecData%MemberCaB2 + DstCoefMembersRecData%MemberCaBMG1 = SrcCoefMembersRecData%MemberCaBMG1 + DstCoefMembersRecData%MemberCaBMG2 = SrcCoefMembersRecData%MemberCaBMG2 + DstCoefMembersRecData%MemberCp1 = SrcCoefMembersRecData%MemberCp1 + DstCoefMembersRecData%MemberCp2 = SrcCoefMembersRecData%MemberCp2 + DstCoefMembersRecData%MemberCpMG1 = SrcCoefMembersRecData%MemberCpMG1 + DstCoefMembersRecData%MemberCpMG2 = SrcCoefMembersRecData%MemberCpMG2 + DstCoefMembersRecData%MemberAxCd1 = SrcCoefMembersRecData%MemberAxCd1 + DstCoefMembersRecData%MemberAxCd2 = SrcCoefMembersRecData%MemberAxCd2 + DstCoefMembersRecData%MemberAxCdMG1 = SrcCoefMembersRecData%MemberAxCdMG1 + DstCoefMembersRecData%MemberAxCdMG2 = SrcCoefMembersRecData%MemberAxCdMG2 + DstCoefMembersRecData%MemberAxCa1 = SrcCoefMembersRecData%MemberAxCa1 + DstCoefMembersRecData%MemberAxCa2 = SrcCoefMembersRecData%MemberAxCa2 + DstCoefMembersRecData%MemberAxCaMG1 = SrcCoefMembersRecData%MemberAxCaMG1 + DstCoefMembersRecData%MemberAxCaMG2 = SrcCoefMembersRecData%MemberAxCaMG2 + DstCoefMembersRecData%MemberAxCp1 = SrcCoefMembersRecData%MemberAxCp1 + DstCoefMembersRecData%MemberAxCp2 = SrcCoefMembersRecData%MemberAxCp2 + DstCoefMembersRecData%MemberAxCpMG1 = SrcCoefMembersRecData%MemberAxCpMG1 + DstCoefMembersRecData%MemberAxCpMG2 = SrcCoefMembersRecData%MemberAxCpMG2 + DstCoefMembersRecData%MemberCb1 = SrcCoefMembersRecData%MemberCb1 + DstCoefMembersRecData%MemberCb2 = SrcCoefMembersRecData%MemberCb2 + DstCoefMembersRecData%MemberCbMG1 = SrcCoefMembersRecData%MemberCbMG1 + DstCoefMembersRecData%MemberCbMG2 = SrcCoefMembersRecData%MemberCbMG2 + DstCoefMembersRecData%MemberMCF = SrcCoefMembersRecData%MemberMCF +end subroutine + +subroutine Morison_DestroyCoefMembersRec(CoefMembersRecData, ErrStat, ErrMsg) + type(Morison_CoefMembersRec), intent(inout) :: CoefMembersRecData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'Morison_DestroyCoefMembersRec' + ErrStat = ErrID_None + ErrMsg = '' +end subroutine + +subroutine Morison_PackCoefMembersRec(RF, Indata) + type(RegFile), intent(inout) :: RF + type(Morison_CoefMembersRec), intent(in) :: InData + character(*), parameter :: RoutineName = 'Morison_PackCoefMembersRec' + if (RF%ErrStat >= AbortErrLev) return + call RegPack(RF, InData%MemberID) + call RegPack(RF, InData%MemberCdA1) + call RegPack(RF, InData%MemberCdA2) + call RegPack(RF, InData%MemberCdAMG1) + call RegPack(RF, InData%MemberCdAMG2) + call RegPack(RF, InData%MemberCdB1) + call RegPack(RF, InData%MemberCdB2) + call RegPack(RF, InData%MemberCdBMG1) + call RegPack(RF, InData%MemberCdBMG2) + call RegPack(RF, InData%MemberCaA1) + call RegPack(RF, InData%MemberCaA2) + call RegPack(RF, InData%MemberCaAMG1) + call RegPack(RF, InData%MemberCaAMG2) + call RegPack(RF, InData%MemberCaB1) + call RegPack(RF, InData%MemberCaB2) + call RegPack(RF, InData%MemberCaBMG1) + call RegPack(RF, InData%MemberCaBMG2) + call RegPack(RF, InData%MemberCp1) + call RegPack(RF, InData%MemberCp2) + call RegPack(RF, InData%MemberCpMG1) + call RegPack(RF, InData%MemberCpMG2) + call RegPack(RF, InData%MemberAxCd1) + call RegPack(RF, InData%MemberAxCd2) + call RegPack(RF, InData%MemberAxCdMG1) + call RegPack(RF, InData%MemberAxCdMG2) + call RegPack(RF, InData%MemberAxCa1) + call RegPack(RF, InData%MemberAxCa2) + call RegPack(RF, InData%MemberAxCaMG1) + call RegPack(RF, InData%MemberAxCaMG2) + call RegPack(RF, InData%MemberAxCp1) + call RegPack(RF, InData%MemberAxCp2) + call RegPack(RF, InData%MemberAxCpMG1) + call RegPack(RF, InData%MemberAxCpMG2) + call RegPack(RF, InData%MemberCb1) + call RegPack(RF, InData%MemberCb2) + call RegPack(RF, InData%MemberCbMG1) + call RegPack(RF, InData%MemberCbMG2) + call RegPack(RF, InData%MemberMCF) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine Morison_UnPackCoefMembersRec(RF, OutData) + type(RegFile), intent(inout) :: RF + type(Morison_CoefMembersRec), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'Morison_UnPackCoefMembersRec' + if (RF%ErrStat /= ErrID_None) return + call RegUnpack(RF, OutData%MemberID); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCdA1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCdA2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCdAMG1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCdAMG2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCdB1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCdB2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCdBMG1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCdBMG2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCaA1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCaA2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCaAMG1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCaAMG2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCaB1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCaB2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCaBMG1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCaBMG2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCp1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCp2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCpMG1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCpMG2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCd1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCd2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCdMG1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCdMG2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCa1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCa2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCaMG1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCaMG2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCp1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCp2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCpMG1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberAxCpMG2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCb1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCb2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCbMG1); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberCbMG2); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%MemberMCF); if (RegCheckErr(RF, RoutineName)) return +end subroutine + subroutine Morison_CopyMGDepthsType(SrcMGDepthsTypeData, DstMGDepthsTypeData, CtrlCode, ErrStat, ErrMsg) type(Morison_MGDepthsType), intent(in) :: SrcMGDepthsTypeData type(Morison_MGDepthsType), intent(inout) :: DstMGDepthsTypeData @@ -2402,19 +3243,36 @@ subroutine Morison_CopyInitInput(SrcInitInputData, DstInitInputData, CtrlCode, E if (ErrStat >= AbortErrLev) return end do end if - DstInitInputData%NPropSets = SrcInitInputData%NPropSets - if (allocated(SrcInitInputData%MPropSets)) then - LB(1:1) = lbound(SrcInitInputData%MPropSets) - UB(1:1) = ubound(SrcInitInputData%MPropSets) - if (.not. allocated(DstInitInputData%MPropSets)) then - allocate(DstInitInputData%MPropSets(LB(1):UB(1)), stat=ErrStat2) + DstInitInputData%NPropSetsCyl = SrcInitInputData%NPropSetsCyl + if (allocated(SrcInitInputData%MPropSetsCyl)) then + LB(1:1) = lbound(SrcInitInputData%MPropSetsCyl) + UB(1:1) = ubound(SrcInitInputData%MPropSetsCyl) + if (.not. allocated(DstInitInputData%MPropSetsCyl)) then + allocate(DstInitInputData%MPropSetsCyl(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%MPropSetsCyl.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + do i1 = LB(1), UB(1) + call Morison_CopyMemberPropTypeCyl(SrcInitInputData%MPropSetsCyl(i1), DstInitInputData%MPropSetsCyl(i1), CtrlCode, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end do + end if + DstInitInputData%NPropSetsRec = SrcInitInputData%NPropSetsRec + if (allocated(SrcInitInputData%MPropSetsRec)) then + LB(1:1) = lbound(SrcInitInputData%MPropSetsRec) + UB(1:1) = ubound(SrcInitInputData%MPropSetsRec) + if (.not. allocated(DstInitInputData%MPropSetsRec)) then + allocate(DstInitInputData%MPropSetsRec(LB(1):UB(1)), stat=ErrStat2) if (ErrStat2 /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%MPropSets.', ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%MPropSetsRec.', ErrStat, ErrMsg, RoutineName) return end if end if do i1 = LB(1), UB(1) - call Morison_CopyMemberPropType(SrcInitInputData%MPropSets(i1), DstInitInputData%MPropSets(i1), CtrlCode, ErrStat2, ErrMsg2) + call Morison_CopyMemberPropTypeRec(SrcInitInputData%MPropSetsRec(i1), DstInitInputData%MPropSetsRec(i1), CtrlCode, ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return end do @@ -2434,36 +3292,89 @@ subroutine Morison_CopyInitInput(SrcInitInputData, DstInitInputData, CtrlCode, E DstInitInputData%SimplCb = SrcInitInputData%SimplCb DstInitInputData%SimplCbMg = SrcInitInputData%SimplCbMg DstInitInputData%SimplMCF = SrcInitInputData%SimplMCF - DstInitInputData%NCoefDpth = SrcInitInputData%NCoefDpth - if (allocated(SrcInitInputData%CoefDpths)) then - LB(1:1) = lbound(SrcInitInputData%CoefDpths) - UB(1:1) = ubound(SrcInitInputData%CoefDpths) - if (.not. allocated(DstInitInputData%CoefDpths)) then - allocate(DstInitInputData%CoefDpths(LB(1):UB(1)), stat=ErrStat2) + DstInitInputData%SimplRecCdA = SrcInitInputData%SimplRecCdA + DstInitInputData%SimplRecCdAMG = SrcInitInputData%SimplRecCdAMG + DstInitInputData%SimplRecCdB = SrcInitInputData%SimplRecCdB + DstInitInputData%SimplRecCdBMG = SrcInitInputData%SimplRecCdBMG + DstInitInputData%SimplRecCaA = SrcInitInputData%SimplRecCaA + DstInitInputData%SimplRecCaAMG = SrcInitInputData%SimplRecCaAMG + DstInitInputData%SimplRecCaB = SrcInitInputData%SimplRecCaB + DstInitInputData%SimplRecCaBMG = SrcInitInputData%SimplRecCaBMG + DstInitInputData%SimplRecCp = SrcInitInputData%SimplRecCp + DstInitInputData%SimplRecCpMG = SrcInitInputData%SimplRecCpMG + DstInitInputData%SimplRecAxCd = SrcInitInputData%SimplRecAxCd + DstInitInputData%SimplRecAxCdMG = SrcInitInputData%SimplRecAxCdMG + DstInitInputData%SimplRecAxCa = SrcInitInputData%SimplRecAxCa + DstInitInputData%SimplRecAxCaMG = SrcInitInputData%SimplRecAxCaMG + DstInitInputData%SimplRecAxCp = SrcInitInputData%SimplRecAxCp + DstInitInputData%SimplRecAxCpMG = SrcInitInputData%SimplRecAxCpMG + DstInitInputData%SimplRecCb = SrcInitInputData%SimplRecCb + DstInitInputData%SimplRecCbMg = SrcInitInputData%SimplRecCbMg + DstInitInputData%SimplRecMCF = SrcInitInputData%SimplRecMCF + DstInitInputData%NCoefDpthCyl = SrcInitInputData%NCoefDpthCyl + if (allocated(SrcInitInputData%CoefDpthsCyl)) then + LB(1:1) = lbound(SrcInitInputData%CoefDpthsCyl) + UB(1:1) = ubound(SrcInitInputData%CoefDpthsCyl) + if (.not. allocated(DstInitInputData%CoefDpthsCyl)) then + allocate(DstInitInputData%CoefDpthsCyl(LB(1):UB(1)), stat=ErrStat2) if (ErrStat2 /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CoefDpths.', ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CoefDpthsCyl.', ErrStat, ErrMsg, RoutineName) return end if end if do i1 = LB(1), UB(1) - call Morison_CopyCoefDpths(SrcInitInputData%CoefDpths(i1), DstInitInputData%CoefDpths(i1), CtrlCode, ErrStat2, ErrMsg2) + call Morison_CopyCoefDpthsCyl(SrcInitInputData%CoefDpthsCyl(i1), DstInitInputData%CoefDpthsCyl(i1), CtrlCode, ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return end do end if - DstInitInputData%NCoefMembers = SrcInitInputData%NCoefMembers - if (allocated(SrcInitInputData%CoefMembers)) then - LB(1:1) = lbound(SrcInitInputData%CoefMembers) - UB(1:1) = ubound(SrcInitInputData%CoefMembers) - if (.not. allocated(DstInitInputData%CoefMembers)) then - allocate(DstInitInputData%CoefMembers(LB(1):UB(1)), stat=ErrStat2) + DstInitInputData%NCoefDpthRec = SrcInitInputData%NCoefDpthRec + if (allocated(SrcInitInputData%CoefDpthsRec)) then + LB(1:1) = lbound(SrcInitInputData%CoefDpthsRec) + UB(1:1) = ubound(SrcInitInputData%CoefDpthsRec) + if (.not. allocated(DstInitInputData%CoefDpthsRec)) then + allocate(DstInitInputData%CoefDpthsRec(LB(1):UB(1)), stat=ErrStat2) if (ErrStat2 /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CoefMembers.', ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CoefDpthsRec.', ErrStat, ErrMsg, RoutineName) return end if end if do i1 = LB(1), UB(1) - call Morison_CopyCoefMembers(SrcInitInputData%CoefMembers(i1), DstInitInputData%CoefMembers(i1), CtrlCode, ErrStat2, ErrMsg2) + call Morison_CopyCoefDpthsRec(SrcInitInputData%CoefDpthsRec(i1), DstInitInputData%CoefDpthsRec(i1), CtrlCode, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end do + end if + DstInitInputData%NCoefMembersCyl = SrcInitInputData%NCoefMembersCyl + if (allocated(SrcInitInputData%CoefMembersCyl)) then + LB(1:1) = lbound(SrcInitInputData%CoefMembersCyl) + UB(1:1) = ubound(SrcInitInputData%CoefMembersCyl) + if (.not. allocated(DstInitInputData%CoefMembersCyl)) then + allocate(DstInitInputData%CoefMembersCyl(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CoefMembersCyl.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + do i1 = LB(1), UB(1) + call Morison_CopyCoefMembersCyl(SrcInitInputData%CoefMembersCyl(i1), DstInitInputData%CoefMembersCyl(i1), CtrlCode, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end do + end if + DstInitInputData%NCoefMembersRec = SrcInitInputData%NCoefMembersRec + if (allocated(SrcInitInputData%CoefMembersRec)) then + LB(1:1) = lbound(SrcInitInputData%CoefMembersRec) + UB(1:1) = ubound(SrcInitInputData%CoefMembersRec) + if (.not. allocated(DstInitInputData%CoefMembersRec)) then + allocate(DstInitInputData%CoefMembersRec(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CoefMembersRec.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + do i1 = LB(1), UB(1) + call Morison_CopyCoefMembersRec(SrcInitInputData%CoefMembersRec(i1), DstInitInputData%CoefMembersRec(i1), CtrlCode, ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return end do @@ -2612,32 +3523,59 @@ subroutine Morison_DestroyInitInput(InitInputData, ErrStat, ErrMsg) end do deallocate(InitInputData%AxialCoefs) end if - if (allocated(InitInputData%MPropSets)) then - LB(1:1) = lbound(InitInputData%MPropSets) - UB(1:1) = ubound(InitInputData%MPropSets) + if (allocated(InitInputData%MPropSetsCyl)) then + LB(1:1) = lbound(InitInputData%MPropSetsCyl) + UB(1:1) = ubound(InitInputData%MPropSetsCyl) + do i1 = LB(1), UB(1) + call Morison_DestroyMemberPropTypeCyl(InitInputData%MPropSetsCyl(i1), ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end do + deallocate(InitInputData%MPropSetsCyl) + end if + if (allocated(InitInputData%MPropSetsRec)) then + LB(1:1) = lbound(InitInputData%MPropSetsRec) + UB(1:1) = ubound(InitInputData%MPropSetsRec) + do i1 = LB(1), UB(1) + call Morison_DestroyMemberPropTypeRec(InitInputData%MPropSetsRec(i1), ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end do + deallocate(InitInputData%MPropSetsRec) + end if + if (allocated(InitInputData%CoefDpthsCyl)) then + LB(1:1) = lbound(InitInputData%CoefDpthsCyl) + UB(1:1) = ubound(InitInputData%CoefDpthsCyl) do i1 = LB(1), UB(1) - call Morison_DestroyMemberPropType(InitInputData%MPropSets(i1), ErrStat2, ErrMsg2) + call Morison_DestroyCoefDpthsCyl(InitInputData%CoefDpthsCyl(i1), ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) end do - deallocate(InitInputData%MPropSets) + deallocate(InitInputData%CoefDpthsCyl) end if - if (allocated(InitInputData%CoefDpths)) then - LB(1:1) = lbound(InitInputData%CoefDpths) - UB(1:1) = ubound(InitInputData%CoefDpths) + if (allocated(InitInputData%CoefDpthsRec)) then + LB(1:1) = lbound(InitInputData%CoefDpthsRec) + UB(1:1) = ubound(InitInputData%CoefDpthsRec) do i1 = LB(1), UB(1) - call Morison_DestroyCoefDpths(InitInputData%CoefDpths(i1), ErrStat2, ErrMsg2) + call Morison_DestroyCoefDpthsRec(InitInputData%CoefDpthsRec(i1), ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) end do - deallocate(InitInputData%CoefDpths) + deallocate(InitInputData%CoefDpthsRec) end if - if (allocated(InitInputData%CoefMembers)) then - LB(1:1) = lbound(InitInputData%CoefMembers) - UB(1:1) = ubound(InitInputData%CoefMembers) + if (allocated(InitInputData%CoefMembersCyl)) then + LB(1:1) = lbound(InitInputData%CoefMembersCyl) + UB(1:1) = ubound(InitInputData%CoefMembersCyl) do i1 = LB(1), UB(1) - call Morison_DestroyCoefMembers(InitInputData%CoefMembers(i1), ErrStat2, ErrMsg2) + call Morison_DestroyCoefMembersCyl(InitInputData%CoefMembersCyl(i1), ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) end do - deallocate(InitInputData%CoefMembers) + deallocate(InitInputData%CoefMembersCyl) + end if + if (allocated(InitInputData%CoefMembersRec)) then + LB(1:1) = lbound(InitInputData%CoefMembersRec) + UB(1:1) = ubound(InitInputData%CoefMembersRec) + do i1 = LB(1), UB(1) + call Morison_DestroyCoefMembersRec(InitInputData%CoefMembersRec(i1), ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end do + deallocate(InitInputData%CoefMembersRec) end if if (allocated(InitInputData%InpMembers)) then LB(1:1) = lbound(InitInputData%InpMembers) @@ -2731,14 +3669,24 @@ subroutine Morison_PackInitInput(RF, Indata) call Morison_PackAxialCoefType(RF, InData%AxialCoefs(i1)) end do end if - call RegPack(RF, InData%NPropSets) - call RegPack(RF, allocated(InData%MPropSets)) - if (allocated(InData%MPropSets)) then - call RegPackBounds(RF, 1, lbound(InData%MPropSets), ubound(InData%MPropSets)) - LB(1:1) = lbound(InData%MPropSets) - UB(1:1) = ubound(InData%MPropSets) + call RegPack(RF, InData%NPropSetsCyl) + call RegPack(RF, allocated(InData%MPropSetsCyl)) + if (allocated(InData%MPropSetsCyl)) then + call RegPackBounds(RF, 1, lbound(InData%MPropSetsCyl), ubound(InData%MPropSetsCyl)) + LB(1:1) = lbound(InData%MPropSetsCyl) + UB(1:1) = ubound(InData%MPropSetsCyl) + do i1 = LB(1), UB(1) + call Morison_PackMemberPropTypeCyl(RF, InData%MPropSetsCyl(i1)) + end do + end if + call RegPack(RF, InData%NPropSetsRec) + call RegPack(RF, allocated(InData%MPropSetsRec)) + if (allocated(InData%MPropSetsRec)) then + call RegPackBounds(RF, 1, lbound(InData%MPropSetsRec), ubound(InData%MPropSetsRec)) + LB(1:1) = lbound(InData%MPropSetsRec) + UB(1:1) = ubound(InData%MPropSetsRec) do i1 = LB(1), UB(1) - call Morison_PackMemberPropType(RF, InData%MPropSets(i1)) + call Morison_PackMemberPropTypeRec(RF, InData%MPropSetsRec(i1)) end do end if call RegPack(RF, InData%SimplCd) @@ -2756,24 +3704,63 @@ subroutine Morison_PackInitInput(RF, Indata) call RegPack(RF, InData%SimplCb) call RegPack(RF, InData%SimplCbMg) call RegPack(RF, InData%SimplMCF) - call RegPack(RF, InData%NCoefDpth) - call RegPack(RF, allocated(InData%CoefDpths)) - if (allocated(InData%CoefDpths)) then - call RegPackBounds(RF, 1, lbound(InData%CoefDpths), ubound(InData%CoefDpths)) - LB(1:1) = lbound(InData%CoefDpths) - UB(1:1) = ubound(InData%CoefDpths) + call RegPack(RF, InData%SimplRecCdA) + call RegPack(RF, InData%SimplRecCdAMG) + call RegPack(RF, InData%SimplRecCdB) + call RegPack(RF, InData%SimplRecCdBMG) + call RegPack(RF, InData%SimplRecCaA) + call RegPack(RF, InData%SimplRecCaAMG) + call RegPack(RF, InData%SimplRecCaB) + call RegPack(RF, InData%SimplRecCaBMG) + call RegPack(RF, InData%SimplRecCp) + call RegPack(RF, InData%SimplRecCpMG) + call RegPack(RF, InData%SimplRecAxCd) + call RegPack(RF, InData%SimplRecAxCdMG) + call RegPack(RF, InData%SimplRecAxCa) + call RegPack(RF, InData%SimplRecAxCaMG) + call RegPack(RF, InData%SimplRecAxCp) + call RegPack(RF, InData%SimplRecAxCpMG) + call RegPack(RF, InData%SimplRecCb) + call RegPack(RF, InData%SimplRecCbMg) + call RegPack(RF, InData%SimplRecMCF) + call RegPack(RF, InData%NCoefDpthCyl) + call RegPack(RF, allocated(InData%CoefDpthsCyl)) + if (allocated(InData%CoefDpthsCyl)) then + call RegPackBounds(RF, 1, lbound(InData%CoefDpthsCyl), ubound(InData%CoefDpthsCyl)) + LB(1:1) = lbound(InData%CoefDpthsCyl) + UB(1:1) = ubound(InData%CoefDpthsCyl) + do i1 = LB(1), UB(1) + call Morison_PackCoefDpthsCyl(RF, InData%CoefDpthsCyl(i1)) + end do + end if + call RegPack(RF, InData%NCoefDpthRec) + call RegPack(RF, allocated(InData%CoefDpthsRec)) + if (allocated(InData%CoefDpthsRec)) then + call RegPackBounds(RF, 1, lbound(InData%CoefDpthsRec), ubound(InData%CoefDpthsRec)) + LB(1:1) = lbound(InData%CoefDpthsRec) + UB(1:1) = ubound(InData%CoefDpthsRec) + do i1 = LB(1), UB(1) + call Morison_PackCoefDpthsRec(RF, InData%CoefDpthsRec(i1)) + end do + end if + call RegPack(RF, InData%NCoefMembersCyl) + call RegPack(RF, allocated(InData%CoefMembersCyl)) + if (allocated(InData%CoefMembersCyl)) then + call RegPackBounds(RF, 1, lbound(InData%CoefMembersCyl), ubound(InData%CoefMembersCyl)) + LB(1:1) = lbound(InData%CoefMembersCyl) + UB(1:1) = ubound(InData%CoefMembersCyl) do i1 = LB(1), UB(1) - call Morison_PackCoefDpths(RF, InData%CoefDpths(i1)) + call Morison_PackCoefMembersCyl(RF, InData%CoefMembersCyl(i1)) end do end if - call RegPack(RF, InData%NCoefMembers) - call RegPack(RF, allocated(InData%CoefMembers)) - if (allocated(InData%CoefMembers)) then - call RegPackBounds(RF, 1, lbound(InData%CoefMembers), ubound(InData%CoefMembers)) - LB(1:1) = lbound(InData%CoefMembers) - UB(1:1) = ubound(InData%CoefMembers) + call RegPack(RF, InData%NCoefMembersRec) + call RegPack(RF, allocated(InData%CoefMembersRec)) + if (allocated(InData%CoefMembersRec)) then + call RegPackBounds(RF, 1, lbound(InData%CoefMembersRec), ubound(InData%CoefMembersRec)) + LB(1:1) = lbound(InData%CoefMembersRec) + UB(1:1) = ubound(InData%CoefMembersRec) do i1 = LB(1), UB(1) - call Morison_PackCoefMembers(RF, InData%CoefMembers(i1)) + call Morison_PackCoefMembersRec(RF, InData%CoefMembersRec(i1)) end do end if call RegPack(RF, InData%NMembers) @@ -2899,18 +3886,32 @@ subroutine Morison_UnPackInitInput(RF, OutData) call Morison_UnpackAxialCoefType(RF, OutData%AxialCoefs(i1)) ! AxialCoefs end do end if - call RegUnpack(RF, OutData%NPropSets); if (RegCheckErr(RF, RoutineName)) return - if (allocated(OutData%MPropSets)) deallocate(OutData%MPropSets) + call RegUnpack(RF, OutData%NPropSetsCyl); if (RegCheckErr(RF, RoutineName)) return + if (allocated(OutData%MPropSetsCyl)) deallocate(OutData%MPropSetsCyl) + call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return + if (IsAllocAssoc) then + call RegUnpackBounds(RF, 1, LB, UB); if (RegCheckErr(RF, RoutineName)) return + allocate(OutData%MPropSetsCyl(LB(1):UB(1)),stat=stat) + if (stat /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating OutData%MPropSetsCyl.', RF%ErrStat, RF%ErrMsg, RoutineName) + return + end if + do i1 = LB(1), UB(1) + call Morison_UnpackMemberPropTypeCyl(RF, OutData%MPropSetsCyl(i1)) ! MPropSetsCyl + end do + end if + call RegUnpack(RF, OutData%NPropSetsRec); if (RegCheckErr(RF, RoutineName)) return + if (allocated(OutData%MPropSetsRec)) deallocate(OutData%MPropSetsRec) call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return if (IsAllocAssoc) then call RegUnpackBounds(RF, 1, LB, UB); if (RegCheckErr(RF, RoutineName)) return - allocate(OutData%MPropSets(LB(1):UB(1)),stat=stat) + allocate(OutData%MPropSetsRec(LB(1):UB(1)),stat=stat) if (stat /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating OutData%MPropSets.', RF%ErrStat, RF%ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating OutData%MPropSetsRec.', RF%ErrStat, RF%ErrMsg, RoutineName) return end if do i1 = LB(1), UB(1) - call Morison_UnpackMemberPropType(RF, OutData%MPropSets(i1)) ! MPropSets + call Morison_UnpackMemberPropTypeRec(RF, OutData%MPropSetsRec(i1)) ! MPropSetsRec end do end if call RegUnpack(RF, OutData%SimplCd); if (RegCheckErr(RF, RoutineName)) return @@ -2928,32 +3929,79 @@ subroutine Morison_UnPackInitInput(RF, OutData) call RegUnpack(RF, OutData%SimplCb); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%SimplCbMg); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%SimplMCF); if (RegCheckErr(RF, RoutineName)) return - call RegUnpack(RF, OutData%NCoefDpth); if (RegCheckErr(RF, RoutineName)) return - if (allocated(OutData%CoefDpths)) deallocate(OutData%CoefDpths) + call RegUnpack(RF, OutData%SimplRecCdA); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCdAMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCdB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCdBMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCaA); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCaAMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCaB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCaBMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCp); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCpMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecAxCd); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecAxCdMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecAxCa); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecAxCaMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecAxCp); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecAxCpMG); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCb); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecCbMg); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%SimplRecMCF); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%NCoefDpthCyl); if (RegCheckErr(RF, RoutineName)) return + if (allocated(OutData%CoefDpthsCyl)) deallocate(OutData%CoefDpthsCyl) call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return if (IsAllocAssoc) then call RegUnpackBounds(RF, 1, LB, UB); if (RegCheckErr(RF, RoutineName)) return - allocate(OutData%CoefDpths(LB(1):UB(1)),stat=stat) + allocate(OutData%CoefDpthsCyl(LB(1):UB(1)),stat=stat) if (stat /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoefDpths.', RF%ErrStat, RF%ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoefDpthsCyl.', RF%ErrStat, RF%ErrMsg, RoutineName) return end if do i1 = LB(1), UB(1) - call Morison_UnpackCoefDpths(RF, OutData%CoefDpths(i1)) ! CoefDpths + call Morison_UnpackCoefDpthsCyl(RF, OutData%CoefDpthsCyl(i1)) ! CoefDpthsCyl end do end if - call RegUnpack(RF, OutData%NCoefMembers); if (RegCheckErr(RF, RoutineName)) return - if (allocated(OutData%CoefMembers)) deallocate(OutData%CoefMembers) + call RegUnpack(RF, OutData%NCoefDpthRec); if (RegCheckErr(RF, RoutineName)) return + if (allocated(OutData%CoefDpthsRec)) deallocate(OutData%CoefDpthsRec) call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return if (IsAllocAssoc) then call RegUnpackBounds(RF, 1, LB, UB); if (RegCheckErr(RF, RoutineName)) return - allocate(OutData%CoefMembers(LB(1):UB(1)),stat=stat) + allocate(OutData%CoefDpthsRec(LB(1):UB(1)),stat=stat) if (stat /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoefMembers.', RF%ErrStat, RF%ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoefDpthsRec.', RF%ErrStat, RF%ErrMsg, RoutineName) return end if do i1 = LB(1), UB(1) - call Morison_UnpackCoefMembers(RF, OutData%CoefMembers(i1)) ! CoefMembers + call Morison_UnpackCoefDpthsRec(RF, OutData%CoefDpthsRec(i1)) ! CoefDpthsRec + end do + end if + call RegUnpack(RF, OutData%NCoefMembersCyl); if (RegCheckErr(RF, RoutineName)) return + if (allocated(OutData%CoefMembersCyl)) deallocate(OutData%CoefMembersCyl) + call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return + if (IsAllocAssoc) then + call RegUnpackBounds(RF, 1, LB, UB); if (RegCheckErr(RF, RoutineName)) return + allocate(OutData%CoefMembersCyl(LB(1):UB(1)),stat=stat) + if (stat /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoefMembersCyl.', RF%ErrStat, RF%ErrMsg, RoutineName) + return + end if + do i1 = LB(1), UB(1) + call Morison_UnpackCoefMembersCyl(RF, OutData%CoefMembersCyl(i1)) ! CoefMembersCyl + end do + end if + call RegUnpack(RF, OutData%NCoefMembersRec); if (RegCheckErr(RF, RoutineName)) return + if (allocated(OutData%CoefMembersRec)) deallocate(OutData%CoefMembersRec) + call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return + if (IsAllocAssoc) then + call RegUnpackBounds(RF, 1, LB, UB); if (RegCheckErr(RF, RoutineName)) return + allocate(OutData%CoefMembersRec(LB(1):UB(1)),stat=stat) + if (stat /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoefMembersRec.', RF%ErrStat, RF%ErrMsg, RoutineName) + return + end if + do i1 = LB(1), UB(1) + call Morison_UnpackCoefMembersRec(RF, OutData%CoefMembersRec(i1)) ! CoefMembersRec end do end if call RegUnpack(RF, OutData%NMembers); if (RegCheckErr(RF, RoutineName)) return @@ -3572,6 +4620,18 @@ subroutine Morison_CopyMisc(SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg) end if DstMiscData%V_rel_n_HiPass = SrcMiscData%V_rel_n_HiPass end if + if (allocated(SrcMiscData%zFillGroup)) then + LB(1:1) = lbound(SrcMiscData%zFillGroup) + UB(1:1) = ubound(SrcMiscData%zFillGroup) + if (.not. allocated(DstMiscData%zFillGroup)) then + allocate(DstMiscData%zFillGroup(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%zFillGroup.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMiscData%zFillGroup = SrcMiscData%zFillGroup + end if call NWTC_Library_CopyMeshMapType(SrcMiscData%VisMeshMap, DstMiscData%VisMeshMap, CtrlCode, ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -3657,6 +4717,9 @@ subroutine Morison_DestroyMisc(MiscData, ErrStat, ErrMsg) if (allocated(MiscData%V_rel_n_HiPass)) then deallocate(MiscData%V_rel_n_HiPass) end if + if (allocated(MiscData%zFillGroup)) then + deallocate(MiscData%zFillGroup) + end if call NWTC_Library_DestroyMeshMapType(MiscData%VisMeshMap, ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) call SeaSt_WaveField_DestroyMisc(MiscData%WaveField_m, ErrStat2, ErrMsg2) @@ -3698,6 +4761,7 @@ subroutine Morison_PackMisc(RF, Indata) call RegPackAlloc(RF, InData%F_BF_End) call RegPackAlloc(RF, InData%V_rel_n) call RegPackAlloc(RF, InData%V_rel_n_HiPass) + call RegPackAlloc(RF, InData%zFillGroup) call NWTC_Library_PackMeshMapType(RF, InData%VisMeshMap) call SeaSt_WaveField_PackMisc(RF, InData%WaveField_m) if (RegCheckErr(RF, RoutineName)) return @@ -3744,6 +4808,7 @@ subroutine Morison_UnPackMisc(RF, OutData) call RegUnpackAlloc(RF, OutData%F_BF_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 call NWTC_Library_UnpackMeshMapType(RF, OutData%VisMeshMap) ! VisMeshMap call SeaSt_WaveField_UnpackMisc(RF, OutData%WaveField_m) ! WaveField_m end subroutine @@ -3958,6 +5023,23 @@ subroutine Morison_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrM DstParamData%WaveField => SrcParamData%WaveField DstParamData%VisMeshes = SrcParamData%VisMeshes DstParamData%PtfmYMod = SrcParamData%PtfmYMod + DstParamData%NFillGroups = SrcParamData%NFillGroups + if (allocated(SrcParamData%FilledGroups)) then + LB(1:1) = lbound(SrcParamData%FilledGroups) + UB(1:1) = ubound(SrcParamData%FilledGroups) + if (.not. allocated(DstParamData%FilledGroups)) then + allocate(DstParamData%FilledGroups(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%FilledGroups.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + do i1 = LB(1), UB(1) + call Morison_CopyFilledGroupType(SrcParamData%FilledGroups(i1), DstParamData%FilledGroups(i1), CtrlCode, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end do + end if end subroutine subroutine Morison_DestroyParam(ParamData, ErrStat, ErrMsg) @@ -4038,6 +5120,15 @@ subroutine Morison_DestroyParam(ParamData, ErrStat, ErrMsg) deallocate(ParamData%OutParam) end if nullify(ParamData%WaveField) + if (allocated(ParamData%FilledGroups)) then + LB(1:1) = lbound(ParamData%FilledGroups) + UB(1:1) = ubound(ParamData%FilledGroups) + do i1 = LB(1), UB(1) + call Morison_DestroyFilledGroupType(ParamData%FilledGroups(i1), ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end do + deallocate(ParamData%FilledGroups) + end if end subroutine subroutine Morison_PackParam(RF, Indata) @@ -4113,6 +5204,16 @@ subroutine Morison_PackParam(RF, Indata) end if call RegPack(RF, InData%VisMeshes) call RegPack(RF, InData%PtfmYMod) + call RegPack(RF, InData%NFillGroups) + call RegPack(RF, allocated(InData%FilledGroups)) + if (allocated(InData%FilledGroups)) then + call RegPackBounds(RF, 1, lbound(InData%FilledGroups), ubound(InData%FilledGroups)) + LB(1:1) = lbound(InData%FilledGroups) + UB(1:1) = ubound(InData%FilledGroups) + do i1 = LB(1), UB(1) + call Morison_PackFilledGroupType(RF, InData%FilledGroups(i1)) + end do + end if if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -4219,6 +5320,20 @@ subroutine Morison_UnPackParam(RF, OutData) end if call RegUnpack(RF, OutData%VisMeshes); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%PtfmYMod); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%NFillGroups); if (RegCheckErr(RF, RoutineName)) return + if (allocated(OutData%FilledGroups)) deallocate(OutData%FilledGroups) + call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return + if (IsAllocAssoc) then + call RegUnpackBounds(RF, 1, LB, UB); if (RegCheckErr(RF, RoutineName)) return + allocate(OutData%FilledGroups(LB(1):UB(1)),stat=stat) + if (stat /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating OutData%FilledGroups.', RF%ErrStat, RF%ErrMsg, RoutineName) + return + end if + do i1 = LB(1), UB(1) + call Morison_UnpackFilledGroupType(RF, OutData%FilledGroups(i1)) ! FilledGroups + end do + end if end subroutine subroutine Morison_CopyInput(SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg) diff --git a/modules/subdyn/src/FEM.f90 b/modules/subdyn/src/FEM.f90 index d193d421f8..3e5d6113d2 100644 --- a/modules/subdyn/src/FEM.f90 +++ b/modules/subdyn/src/FEM.f90 @@ -951,14 +951,16 @@ END SUBROUTINE GetRigidTransformation !! !! bjj: note that this is the transpose of what is normally considered the Direction Cosine Matrix !! in the FAST framework. -SUBROUTINE GetDirCos(P1, P2, eType, DirCos, L_out, ErrStat, ErrMsg) +SUBROUTINE GetDirCos(P1, P2, spin, eType, DirCos, L_out, ErrStat, ErrMsg) REAL(ReKi) , INTENT(IN ) :: P1(3), P2(3) ! (x,y,z) global positions of two nodes making up an element + REAL(ReKi) , INTENT(IN ) :: spin ! Spin angle about member axis INTEGER(IntKi), INTENT(IN ) :: eType ! element type (1:beam circ., 2:cable, 3:rigid, 4:beam arb., 5:spring) REAL(FEKi) , INTENT( OUT) :: DirCos(3, 3) ! calculated direction cosine matrix REAL(ReKi) , INTENT( OUT) :: L_out ! length of element INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None REAL(FEKi) :: Dx, Dy, Dz, Dxy,L! distances between nodes + REAL(FEKi) :: RSpin(3, 3) ! Spin rotation matrix about member axis (for rectangular members) ErrMsg = "" ErrStat = ErrID_None @@ -1005,6 +1007,13 @@ SUBROUTINE GetDirCos(P1, P2, eType, DirCos, L_out, ErrStat, ErrMsg) DirCos(3, 2) = -Dxy/L DirCos(3, 3) = +Dz/L ENDIF + IF ( eType==-1 .or. eType==1 .or. eType==4 ) THEN ! All beam types + ! Right multiply the spin matrix + RSpin(1,:) = (/COS(spin),-SIN(spin), 0.0/) + RSpin(2,:) = (/SIN(spin), COS(spin), 0.0/) + RSpin(3,:) = (/ 0.0, 0.0, 1.0/) + DirCos = MATMUL(DirCos,RSpin) + END IF L_out= real(L, ReKi) END SUBROUTINE GetDirCos diff --git a/modules/subdyn/src/SD_FEM.f90 b/modules/subdyn/src/SD_FEM.f90 index 27e72964b0..c72f30e425 100644 --- a/modules/subdyn/src/SD_FEM.f90 +++ b/modules/subdyn/src/SD_FEM.f90 @@ -33,8 +33,9 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: ReactCol = 7 ! Number of columns in reaction matrix (JointID,ItfTDxss,ItfTDYss,ItfTDZss,ItfRDXss,ItfRDYss,ItfRDZss) INTEGER(IntKi), PARAMETER :: MaxNodesPerElem = 2 ! Maximum number of nodes per element (currently 2) INTEGER(IntKi), PARAMETER :: MembersCol = MaxNodesPerElem + 3+1+1 ! Number of columns in Members (MemberID,MJointID1,MJointID2,MPropSetID1,MPropSetID2,COSMID) - INTEGER(IntKi), PARAMETER :: PropSetsBCol = 6 ! Number of columns in PropSets (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs - INTEGER(IntKi), PARAMETER :: PropSetsXCol = 10 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0) + INTEGER(IntKi), PARAMETER :: PropSetsBCCol = 6 ! Number of columns in PropSets of circular beam sections (PropSetID,YoungE,ShearG,MatDens,XsecD,XsecT) !bjj: this really doesn't need to store k, does it? or is this supposed to be an ID, in which case we shouldn't be storing k (except new property sets), we should be storing IDs + INTEGER(IntKi), PARAMETER :: PropSetsBRCol = 7 ! Number of columns in PropSets of rectangular beam sections (PropSetID,YoungE,ShearG,MatDens,XsecSa,XsecSb,XsecT) + INTEGER(IntKi), PARAMETER :: PropSetsXCol = 11 ! Number of columns in XPropSets (PropSetID,YoungE,ShearG,MatDens,XsecA,XsecAsx,XsecAsy,XsecJxx,XsecJyy,XsecJ0,XsecJt) INTEGER(IntKi), PARAMETER :: PropSetsCCol = 5 ! Number of columns in CablePropSet (PropSetID, EA, MatDens, T0) INTEGER(IntKi), PARAMETER :: PropSetsRCol = 2 ! Number of columns in RigidPropSet (PropSetID, MatDens) INTEGER(IntKi), PARAMETER :: PropSetsSCol = 22 ! Number of columns in SpringPropSet (PropSetID, k11, k12, k13, k14, k15, k16, k22, k23, k24, k25, k26, k33, k34, k35, k36, k44, k45, k46, k55, k56, k66) @@ -58,6 +59,7 @@ MODULE SD_FEM ! ID for member types INTEGER(IntKi), PARAMETER :: idMemberBeamCirc = 1 + INTEGER(IntKi), PARAMETER :: idMemberBeamRect = -1 INTEGER(IntKi), PARAMETER :: idMemberCable = 2 INTEGER(IntKi), PARAMETER :: idMemberRigid = 3 INTEGER(IntKi), PARAMETER :: idMemberBeamArb = 4 @@ -79,7 +81,7 @@ MODULE SD_FEM INTEGER(IntKi), PARAMETER :: idGuyanDamp_66 = 2 INTEGER(IntKi) :: idGuyanDamp_Valid(3) = (/idGuyanDamp_None, idGuyanDamp_Rayleigh, idGuyanDamp_66 /) - INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCol,PropSetsXCol,COSMsCol,CMassCol) + INTEGER(IntKi), PARAMETER :: SDMaxInpCols = MAX(JointsCol,InterfCol,MembersCol,PropSetsBCCol,PropSetsBRCol,PropSetsXCol,PropSetsSCol,COSMsCol,CMassCol) ! Output Formats INTEGER(IntKi), PARAMETER :: idOutputFormatNone = 0 @@ -306,6 +308,7 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) ! TODO See if Elems is actually used elsewhere CALL AllocAry(p%Elems ,Init%NElem,MembersCol ,'p%Elems' ,ErrStat2,ErrMsg2); if(Failed())return + CALL AllocAry(p%ElemSpin ,Init%NElem ,'p%ElemSpin' ,ErrStat2,ErrMsg2); if(Failed())return CALL AllocAry(Init%Nodes ,p%nNodes ,JointsCol ,'Init%Nodes' ,ErrStat2,ErrMsg2); if(Failed())return CALL AllocAry(p%NodeID2JointID,p%nNodes ,'p%NodeID2JointID',ErrStat2,ErrMsg2); if(Failed())return @@ -386,13 +389,16 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) if (mType==idMemberBeamCirc) then sType='Member circular cross-section property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSetsB(:,1), Init%Members(iMem, n) ) + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsBC(:,1), Init%Members(iMem, n) ) + else if (mType==idMemberBeamRect) then + sType='Member rectangular cross-section property' + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsBR(:,1), Init%Members(iMem, n) ) else if (mType==idMemberCable) then sType='Cable property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSetsC(:,1), Init%Members(iMem, n) ) + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsC(:,1), Init%Members(iMem, n) ) else if (mType==idMemberRigid) then sType='Rigid property' - p%Elems(iMem,n) = FINDLOCI(Init%PropSetsR(:,1), Init%Members(iMem, n) ) + p%Elems(iMem,n) = FINDLOCI(Init%PropSetsR(:,1), Init%Members(iMem, n) ) else if (mType==idMemberBeamArb) then sType='Member arbitrary cross-section property' p%Elems(iMem,n) = FINDLOCI(Init%PropSetsX(:,1), Init%Members(iMem, n) ) @@ -405,25 +411,34 @@ SUBROUTINE SD_ReIndex_CreateNodesAndElems(Init,p, ErrStat, ErrMsg) STOP end if ! Test that the two properties match for non-beam - if (mType/=idMemberBeamCirc) then + if (mType/=idMemberBeamCirc .and. mType/=idMemberBeamRect) then if (Init%Members(iMem, iMProp)/=Init%Members(iMem, iMProp+1)) then - ! NOTE: for non circular beams, we could just check that E, rho, G are the same for both properties + ! NOTE: for beams, we could just check that E, rho, G are the same for both properties call Fatal('Property IDs should be the same at both joints for arbitrary beams, rigid links, cables, and springs. Check member with ID: '//TRIM(Num2LStr(Init%Members(iMem,1)))) return endif endif if (p%Elems(iMem,n)<=0) then - CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//', the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the'//trim(sType)//' table!') + CALL Fatal('For MemberID '//TRIM(Num2LStr(Init%Members(iMem,1)))//', the PropSetID'//TRIM(Num2LStr(n-3))//' is not in the '//trim(sType)//' table!') return endif END DO !n, loop through property ids ! Column 6: member type p%Elems(iMem, iMType) = Init%Members(iMem, iMType) ! - ! Column 7: member type - - if (p%Elems(iMem, iMDirCosID)/=-1) then + ! Column 7: User DirCos matrix ID + if (Init%Members(iMem, iMDirCosID)/=-1) then p%Elems(iMem, iMDirCosID) = FINDLOCI(Init%COSMs(:,1), Init%Members(iMem, iMDirCosID) ) + if (p%Elems(iMem, iMDirCosID) < 0) then + CALL Fatal('Members table: line '//TRIM(Num2LStr(iMem))//' refers to COSMID '//trim(Num2LStr(Init%Members(iMem, iMDirCosID)))//' which is not in the MEMBER COSINE MATRICES list!') + return + end if + else + p%Elems(iMem, iMDirCosID) = -1 endif + ! Member spin angle + if (mType==idMemberBeamCirc .or. mType==idMemberBeamRect .or. mType==idMemberBeamArb) then + p%ElemSpin(iMem) = Init%MemberSpin(iMem) + end if END DO !iMem, loop through members @@ -452,14 +467,15 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) INTEGER :: I, J, Node1, Node2, Prop1, Prop2 INTEGER :: NNE ! number of nodes per element INTEGER :: MaxNProp - REAL(ReKi), ALLOCATABLE :: TempProps(:, :) - REAL(ReKi), ALLOCATABLE :: TempPropsX(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsBC(:, :) + REAL(ReKi), ALLOCATABLE :: TempPropsBR(:, :) INTEGER, ALLOCATABLE :: TempMembers(:, :) - INTEGER :: knode, kelem, kprop, nprop + REAL(ReKi), ALLOCATABLE :: TempMemSpin(:) + INTEGER :: knode, kelem, kpropBC, kpropBR, nprop INTEGER :: iDirCos - REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dt, d1, d2, t1, t2 + REAL(ReKi) :: x1, y1, z1, x2, y2, z2, dx, dy, dz, dd, dSa, dSb, dt, d1, d2, Sa1, Sa2, Sb1, Sb2, t1, t2, spin LOGICAL :: CreateNewProp - INTEGER(IntKi) :: nMemberCable, nMemberRigid, nMemberSpring, nMemberBeamCirc, nMemberBeamArb !< Number of members per type + INTEGER(IntKi) :: nMemberCable, nMemberRigid, nMemberSpring, nMemberBeamCirc, nMemberBeamRect, nMemberBeamArb !< Number of members per type INTEGER(IntKi) :: eType !< Element Type INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -475,17 +491,18 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! --- Total number of element nMemberBeamCirc = count(Init%Members(:,iMType) == idMemberBeamCirc) + nMemberBeamRect = count(Init%Members(:,iMType) == idMemberBeamRect) nMemberCable = count(Init%Members(:,iMType) == idMemberCable) nMemberRigid = count(Init%Members(:,iMType) == idMemberRigid) nMemberBeamArb = count(Init%Members(:,iMType) == idMemberBeamArb) nMemberSpring = count(Init%Members(:,iMType) == idMemberSpring) - Init%NElem = (nMemberBeamCirc + nMemberBeamArb)*Init%NDiv + nMemberCable + nMemberRigid + nMemberSpring ! NOTE: only Beams are divided - IF ( (nMemberBeamCirc+nMemberRigid+nMemberCable+nMemberBeamArb+nMemberSpring) /= size(Init%Members,1)) then + Init%NElem = (nMemberBeamCirc + nMemberBeamRect + nMemberBeamArb)*Init%NDiv + nMemberCable + nMemberRigid + nMemberSpring ! NOTE: only Beams are divided + IF ( (nMemberBeamCirc+nMemberBeamRect+nMemberRigid+nMemberCable+nMemberBeamArb+nMemberSpring) /= size(Init%Members,1)) then CALL Fatal(' Member list contains an element which is not a beam, a cable, a rigid link or a spring'); return ENDIF ! Total number of nodes - Depends on division and number of nodes per element - p%nNodes = Init%NJoints + ( Init%NDiv - 1 )*(nMemberBeamCirc) ! TODO add nMemberBeamArb when support for division provided + p%nNodes = Init%NJoints + ( Init%NDiv - 1 )*(nMemberBeamCirc+nMemberBeamRect+nMemberBeamArb) ! check the number of interior modes IF ( p%nDOFM > 6*(p%nNodes - p%nNodes_I - p%nNodes_C) ) THEN @@ -493,7 +510,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDIF ! TODO replace this with an integer list! - CALL AllocAry(Init%MemberNodes,p%NMembers, Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different + CALL AllocAry(Init%MemberNodes,p%NMembers,Init%NDiv+1,'Init%MemberNodes',ErrStat2, ErrMsg2); if(Failed()) return ! for two-node element only, otherwise the number of nodes in one element is different ! --- Reindexing JointsID and MembersID into Nodes and Elems arrays ! NOTE: need NNode and NElem @@ -514,10 +531,17 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) endif if (eType==idMemberBeamCirc) then - if ( ( .not. EqualRealNos(Init%PropSetsB(Prop1, 2),Init%PropSetsB(Prop2, 2) ) ) & - .or. ( .not. EqualRealNos(Init%PropSetsB(Prop1, 3),Init%PropSetsB(Prop2, 3) ) ) & - .or. ( .not. EqualRealNos(Init%PropSetsB(Prop1, 4),Init%PropSetsB(Prop2, 4) ) ) ) then - call Fatal(' Material E, G and rho in a member must be the same (See member at position '//trim(num2lstr(I))//' in member list)') + if ( ( .not. EqualRealNos(Init%PropSetsBC(Prop1, 2),Init%PropSetsBC(Prop2, 2) ) ) & + .or. ( .not. EqualRealNos(Init%PropSetsBC(Prop1, 3),Init%PropSetsBC(Prop2, 3) ) ) & + .or. ( .not. EqualRealNos(Init%PropSetsBC(Prop1, 4),Init%PropSetsBC(Prop2, 4) ) ) ) then + call Fatal(' Material E, G and rho in a beam member must be the same (See member at position '//trim(num2lstr(I))//' in member list)') + return + endif + else if (eType==idMemberBeamRect) then + if ( ( .not. EqualRealNos(Init%PropSetsBR(Prop1, 2),Init%PropSetsBR(Prop2, 2) ) ) & + .or. ( .not. EqualRealNos(Init%PropSetsBR(Prop1, 3),Init%PropSetsBR(Prop2, 3) ) ) & + .or. ( .not. EqualRealNos(Init%PropSetsBR(Prop1, 4),Init%PropSetsBR(Prop2, 4) ) ) ) then + call Fatal(' Material E, G and rho in a beam member must be the same (See member at position '//trim(num2lstr(I))//' in member list)') return endif else if (eType==idMemberBeamArb) then @@ -534,13 +558,14 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) endif ! is beam enddo - Init%MemberNodes = 0 ! --- Setting up MemberNodes (And Elems, Props, Nodes if divisions) if (Init%NDiv==1) then ! NDiv = 1 Init%MemberNodes(1:p%NMembers, 1:2) = p%Elems(1:Init%NElem, 2:3) - Init%NPropB = Init%NPropSetsB + Init%NPropBC = Init%NPropSetsBC + Init%NPropBR = Init%NPropSetsBR + Init%NPropX = Init%NPropSetsX else if (Init%NDiv > 1) then @@ -552,19 +577,26 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ! Initialize Temp arrays that will contain user inputs + input from the subdivided members ! We don't know how many properties will be needed, so allocated to size MaxNProp ! TODO add Init%NPropSetsX and use PropSetXCol in the future or allocate a new TempProps - MaxNProp = Init%NPropSetsB + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) - CALL AllocAry(TempMembers, p%NMembers, MembersCol , 'TempMembers', ErrStat2, ErrMsg2); if(Failed()) return - CALL AllocAry(TempProps, MaxNProp, PropSetsBCol,'TempProps', ErrStat2, ErrMsg2); if(Failed()) return - TempProps = -9999. - TempProps(1:Init%NPropSetsB, :) = Init%PropSetsB - TempMembers = p%Elems(1:p%NMembers,:) + MaxNProp = Init%NPropSetsBC + Init%NPropSetsBR + Init%NPropSetsX + Init%NElem*NNE ! Maximum possible number of property sets (temp): This is property set per element node, for all elements (bjj, added Init%NPropSets to account for possibility of entering many unused prop sets) + CALL AllocAry(TempMembers, p%NMembers, MembersCol , 'TempMembers', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(TempMemSpin, p%NMembers, 'TempMemSpin', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(TempPropsBC, MaxNProp, PropSetsBCCol,'TempPropsBC', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(TempPropsBR, MaxNProp, PropSetsBRCol,'TempPropsBR', ErrStat2, ErrMsg2); if(Failed()) return + TempPropsBC = -9999. + TempPropsBR = -9999. + TempPropsBC(1:Init%NPropSetsBC,:) = Init%PropSetsBC + TempPropsBR(1:Init%NPropSetsBR,:) = Init%PropSetsBR + TempMembers = p%Elems(1:p%NMembers,:) + TempMemSpin = p%ElemSpin(1:p%NMembers) - p%Elems(:,:) = -9999. ! Reinitialized. Elements will be ordered by member subdivisions (see setNewElem) + p%Elems(:,:) = -9999. ! Reinitialized. Elements will be ordered by member subdivisions (see setNewElem) + p%ElemSpin(:) = 0. kelem = 0 knode = Init%NJoints - kprop = Init%NPropSetsB + kpropBC = Init%NPropSetsBC + kpropBR = Init%NPropSetsBR DO I = 1, p%NMembers !the first p%NMembers rows of p%Elems contain the element information ! Member data @@ -574,6 +606,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Prop2 = TempMembers(I, iMProp+1) eType = TempMembers(I, iMType ) iDirCos = TempMembers(I, iMDirCosID) + spin = TempMemSpin(I) if (eType==idMemberRigid .OR. eType==idMemberCable .OR. eType==idMemberSpring) then ! --- Cables, rigid links and springs are not subdivided and have same prop at nodes @@ -581,7 +614,7 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) Init%MemberNodes(I, 1) = Node1 Init%MemberNodes(I, 2) = Node2 kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, Node2, eType, Prop1, Prop1, p, iDirCos) + CALL SetNewElem(kelem, Node1, Node2, eType, Prop1, Prop1, p, iDirCos, spin) cycle endif @@ -603,11 +636,11 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) if (eType == idMemberBeamCirc) then - d1 = TempProps(Prop1, 5) - t1 = TempProps(Prop1, 6) + d1 = TempPropsBC(Prop1, 5) + t1 = TempPropsBC(Prop1, 6) - d2 = TempProps(Prop2, 5) - t2 = TempProps(Prop2, 6) + d2 = TempPropsBC(Prop2, 5) + t2 = TempPropsBC(Prop2, 6) dd = ( d2 - d1 )/Init%NDiv dt = ( t2 - t1 )/Init%NDiv @@ -616,59 +649,91 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) CreateNewProp = .NOT. ( EqualRealNos( dd , 0.0_ReKi ) .AND. EqualRealNos( dt , 0.0_ReKi ) ) + else if (eType == idMemberBeamRect) then + + Sa1 = TempPropsBR(Prop1, 5) + Sb1 = TempPropsBR(Prop1, 6) + t1 = TempPropsBR(Prop1, 7) + + Sa2 = TempPropsBR(Prop2, 5) + Sb2 = TempPropsBR(Prop2, 6) + t2 = TempPropsBR(Prop2, 7) + + dSa = ( Sa2 - Sa1 )/Init%NDiv + dSb = ( Sb2 - Sb1 )/Init%NDiv + dt = ( t2 - t1 )/Init%NDiv + + ! If dSa, dSb, and dt are all 0, no interpolation is needed, and we can use the same property set for new nodes/elements. otherwise we'll have to create new properties for each new node + + CreateNewProp = .NOT. ( EqualRealNos( dSa , 0.0_ReKi ) .AND. EqualRealNos( dSb , 0.0_ReKi ) .AND. EqualRealNos( dt , 0.0_ReKi ) ) + elseif (eType == idMemberBeamArb) then - + CreateNewProp = .FALSE. - CALL WrScr('[WARNING] Members with non-circular cross-sections are currently not divided (member at position '//TRIM(Num2LStr(I))//' ).') - + ! CALL WrScr('[WARNING] Members with non-circular cross-sections are currently not divided (member at position '//TRIM(Num2LStr(I))//' ).') + endif ! node connect to Node1 knode = knode + 1 Init%MemberNodes(I, 2) = knode CALL SetNewNode(knode, x1+dx, y1+dy, z1+dz, Init); if (ErrStat>ErrID_None) return; - - IF ( CreateNewProp ) THEN - ! create a new property set - kprop = kprop + 1 - ! k, E1, G1, rho1, d, t, - CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), TempProps(Prop1, 4), d1+dd, t1+dt, TempProps) - kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, eType, Prop1, kprop, p, iDirCos); if (ErrStat>ErrID_None) return; - nprop = kprop + IF ( CreateNewProp ) THEN + IF ( eType == idMemberBeamCirc ) THEN + ! create a new property set + kpropBC = kpropBC + 1 + ! k, E1, G1, rho1, d, t + CALL SetNewPropBC(kpropBC, TempPropsBC(Prop1, 2), TempPropsBC(Prop1, 3), TempPropsBC(Prop1, 4), d1+dd, t1+dt, TempPropsBC) + nprop = kpropBC + ELSE IF ( eType == idMemberBeamRect ) THEN + ! create a new property set + kpropBR = kpropBR + 1 + ! k, E1, G1, rho1, Sa, Sb, t + CALL SetNewPropBR(kpropBR, TempPropsBR(Prop1, 2), TempPropsBR(Prop1, 3), TempPropsBR(Prop1, 4), Sa1+dSa, Sb1+dSb, t1+dt, TempPropsBR) + nprop = kpropBR + END IF ELSE - kelem = kelem + 1 - CALL SetNewElem(kelem, Node1, knode, eType, Prop1, Prop1, p, iDirCos); if (ErrStat>ErrID_None) return; - nprop = Prop1 + nprop = Prop1 ENDIF + kelem = kelem + 1 + CALL SetNewElem(kelem, Node1, knode, eType, Prop1, nprop, p, iDirCos, spin); if (ErrStat>ErrID_None) return; ! interior nodes DO J = 2, (Init%NDiv-1) knode = knode + 1 Init%MemberNodes(I, J+1) = knode - CALL SetNewNode(knode, x1 + J*dx, y1 + J*dy, z1 + J*dz, Init) ! Set Init%Nodes(knode,:) - - IF ( CreateNewProp ) THEN - ! create a new property set - kprop = kprop + 1 - ! k, E1, G1, rho1, d, t - CALL SetNewProp(kprop, TempProps(Prop1, 2), TempProps(Prop1, 3), Init%PropSetsB(Prop1, 4), d1 + J*dd, t1 + J*dt, TempProps) - kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kprop, p, iDirCos); if (ErrStat>ErrID_None) return; - nprop = kprop + IF ( CreateNewProp ) THEN + IF ( eType == idMemberBeamCirc ) THEN + ! create a new property set + kpropBC = kpropBC + 1 + ! k, E1, G1, rho1, d, t + CALL SetNewPropBC(kpropBC, TempPropsBC(Prop1, 2), TempPropsBC(Prop1, 3), Init%PropSetsBC(Prop1, 4), d1 + J*dd, t1 + J*dt, TempPropsBC) + kelem = kelem + 1 + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kpropBC, p, iDirCos, spin); if (ErrStat>ErrID_None) return; + nprop = kpropBC + ELSE IF ( eType == idMemberBeamRect ) THEN + ! create a new property set + kpropBR = kpropBR + 1 + ! k, E1, G1, rho1, Sa, Sb, t + CALL SetNewPropBR(kpropBR, TempPropsBR(Prop1, 2), TempPropsBR(Prop1, 3), Init%PropSetsBR(Prop1, 4), Sa1 + J*dSa, Sb1 + J*dSb, t1 + J*dt, TempPropsBR) + kelem = kelem + 1 + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, kpropBR, p, iDirCos, spin); if (ErrStat>ErrID_None) return; + nprop = kpropBR + END IF ELSE kelem = kelem + 1 - CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p, iDirCos); if (ErrStat>ErrID_None) return; + CALL SetNewElem(kelem, knode-1, knode, eType, nprop, nprop, p, iDirCos, spin); if (ErrStat>ErrID_None) return; ENDIF ENDDO ! the element connect to Node2 kelem = kelem + 1 - CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p, iDirCos); if (ErrStat>ErrID_None) return; + CALL SetNewElem(kelem, knode, Node2, eType, nprop, Prop2, p, iDirCos, spin); if (ErrStat>ErrID_None) return; ENDDO ! loop over all members ! - Init%NPropB = kprop + Init%NPropBC = kpropBC + Init%NPropBR = kpropBR if(knode/=size(Init%Nodes,1)) then call Fatal('Implementation error. Number of nodes wrongly estimated.');return endif @@ -679,12 +744,15 @@ SUBROUTINE SD_Discrt(Init,p, ErrStat, ErrMsg) ENDIF ! if NDiv is greater than 1 ! set the props in Init - CALL AllocAry(Init%PropsB, Init%NPropB, PropSetsBCol, 'Init%PropsBeams', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%PropsBC, Init%NPropBC, PropSetsBCCol, 'Init%PropsBC', ErrStat2, ErrMsg2); if(Failed()) return + CALL AllocAry(Init%PropsBR, Init%NPropBR, PropSetsBRCol, 'Init%PropsBR', ErrStat2, ErrMsg2); if(Failed()) return if (Init%NDiv==1) then - Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = Init%PropSetsB(1:Init%NPropB, 1:PropSetsBCol) + Init%PropsBC(1:Init%NPropBC, 1:PropSetsBCCol) = Init%PropSetsBC(1:Init%NPropBC, 1:PropSetsBCCol) + Init%PropsBR(1:Init%NPropBR, 1:PropSetsBRCol) = Init%PropSetsBR(1:Init%NPropBR, 1:PropSetsBRCol) else if (Init%NDiv>1) then - Init%PropsB(1:Init%NPropB, 1:PropSetsBCol) = TempProps(1:Init%NPropB, 1:PropSetsBCol) + Init%PropsBC(1:Init%NPropBC, 1:PropSetsBCCol) = TempPropsBC(1:Init%NPropBC, 1:PropSetsBCCol) + Init%PropsBR(1:Init%NPropBR, 1:PropSetsBRCol) = TempPropsBR(1:Init%NPropBR, 1:PropSetsBRCol) endif ! --- Cables, rigid link and spring properties (these cannot be subdivided, so direct copy of inputs) @@ -715,8 +783,10 @@ END SUBROUTINE Fatal SUBROUTINE CleanUp_Discrt() ! deallocate temp matrices - IF (ALLOCATED(TempProps)) DEALLOCATE(TempProps) + IF (ALLOCATED(TempPropsBC)) DEALLOCATE(TempPropsBC) + IF (ALLOCATED(TempPropsBR)) DEALLOCATE(TempPropsBR) IF (ALLOCATED(TempMembers)) DEALLOCATE(TempMembers) + IF (ALLOCATED(TempMemSpin)) DEALLOCATE(TempMemSpin) END SUBROUTINE CleanUp_Discrt !> Set properties of node k @@ -739,7 +809,7 @@ SUBROUTINE SetNewNode(k, x, y, z, Init) END SUBROUTINE SetNewNode !> Set properties of element k - SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p, iDirCos) + SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p, iDirCos, spin) INTEGER, INTENT(IN ) :: k INTEGER, INTENT(IN ) :: n1 INTEGER, INTENT(IN ) :: n2 @@ -747,6 +817,7 @@ SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p, iDirCos) INTEGER, INTENT(IN ) :: p1 INTEGER, INTENT(IN ) :: p2 INTEGER, INTENT(IN ) :: iDirCos + REAL(ReKi), INTENT(IN ) :: spin TYPE(SD_ParameterType), INTENT(INOUT) :: p if (k>size(p%Elems,1)) then call Fatal('Implementation Error. Attempt to add more element than space allocated.'); @@ -758,11 +829,12 @@ SUBROUTINE SetNewElem(k, n1, n2, etype, p1, p2, p, iDirCos) p%Elems(k, iMProp ) = p1 p%Elems(k, iMProp+1) = p2 p%Elems(k, iMType) = eType - p%Elems(k, iMDirCosID) = iDirCos + p%Elems(k, iMDirCosID) = iDirCos + p%ElemSpin(k) = spin END SUBROUTINE SetNewElem !> Set material properties of element k, NOTE: this is only for a beam - SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) + SUBROUTINE SetNewPropBC(k, E, G, rho, d, t, TempProps) INTEGER , INTENT(IN) :: k REAL(ReKi), INTENT(IN) :: E, G, rho, d, t REAL(ReKi), INTENT(INOUT):: TempProps(:, :) @@ -776,7 +848,24 @@ SUBROUTINE SetNewProp(k, E, G, rho, d, t, TempProps) TempProps(k, 4) = rho TempProps(k, 5) = d TempProps(k, 6) = t - END SUBROUTINE SetNewProp + END SUBROUTINE SetNewPropBC + + SUBROUTINE SetNewPropBR(k, E, G, rho, Sa, Sb, t, TempProps) + INTEGER , INTENT(IN) :: k + REAL(ReKi), INTENT(IN) :: E, G, rho, Sa, Sb, t + REAL(ReKi), INTENT(INOUT):: TempProps(:, :) + if (k>size(TempProps,1)) then + call Fatal('Implementation Error. Attempt to add more properties than space allocated.'); + return + endif + TempProps(k, 1) = k + TempProps(k, 2) = E + TempProps(k, 3) = G + TempProps(k, 4) = rho + TempProps(k, 5) = Sa + TempProps(k, 6) = Sb + TempProps(k, 7) = t + END SUBROUTINE SetNewPropBR END SUBROUTINE SD_Discrt @@ -823,14 +912,14 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) INTEGER :: N1, N2 ! starting node and ending node in the element INTEGER :: P1, P2 ! property set numbers for starting and ending nodes INTEGER :: iDirCos - REAL(ReKi) :: D1, D2, t1, t2, E, G, rho ! properties of a section + REAL(ReKi) :: D1, D2, Sa1, Sa2, Sb1, Sb2, t1, t2, E, G, rho ! properties of a section REAL(FEKi) :: DirCos(3, 3) ! direction cosine matrices REAL(ReKi) :: L ! length of the element - REAL(ReKi) :: r1, r2, t, Iyy, Jzz, Ixx, A, kappa, kappa_x, kappa_y, nu, ratioSq, D_inner, D_outer + REAL(ReKi) :: r1, r2, t, Ixx, Iyy, Jzz, Jt, A, kappa, kappa_x, kappa_y, nu, ratio, ratioSq, D_inner, D_outer REAL(ReKi) :: k11, k12, k13, k14, k15, k16, k22, k23, k24, k25, k26, k33, k34, k35, k36, k44, k45, k46, k55, k56, k66 LOGICAL :: shear INTEGER(IntKi) :: eType !< Member type - REAL(ReKi) :: Point1(3), Point2(3) ! (x,y,z) positions of two nodes making up an element + REAL(ReKi) :: Point1(3), Point2(3), spin ! (x,y,z) positions of two nodes making up an element and the element spin angle about its axis INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ErrMsg = "" @@ -848,13 +937,14 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) P2 = p%Elems(I, iMProp+1) eType = p%Elems(I, iMType) iDirCos = p%Elems(I, iMDirCosID) + spin = p%ElemSpin(I) ! --- Properties common to all element types: L, DirCos (and Area and rho) Point1 = Init%Nodes(N1,2:4) Point2 = Init%Nodes(N2,2:4) - if (iDirCos/=-1) then - CALL GetDirCos(Point1, Point2, eType, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! sets L + if (iDirCos/=-1) then ! Spring element only + CALL GetDirCos(Point1, Point2, spin, eType, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! sets L ! overwrites direction cosines DirCos(1, 1) = Init%COSMs(iDirCos, 2) @@ -868,7 +958,7 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) DirCos(3, 3) = Init%COSMs(iDirCos, 10) else - CALL GetDirCos(Point1, Point2, eType, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! L and DirCos + CALL GetDirCos(Point1, Point2, spin, eType, DirCos, L, ErrStat2, ErrMsg2); if(Failed()) return ! L and DirCos endif @@ -912,13 +1002,13 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) ! --- Properties that are specific to some elements if (eType==idMemberBeamCirc) then - E = Init%PropsB(P1, 2) ! TODO E2 - G = Init%PropsB(P1, 3) ! TODO G2 - rho = Init%PropsB(P1, 4) ! TODO rho2 - D1 = Init%PropsB(P1, 5) - t1 = Init%PropsB(P1, 6) - D2 = Init%PropsB(P2, 5) - t2 = Init%PropsB(P2, 6) + E = Init%PropsBC(P1, 2) ! TODO E2 + G = Init%PropsBC(P1, 3) ! TODO G2 + rho = Init%PropsBC(P1, 4) ! TODO rho2 + D1 = Init%PropsBC(P1, 5) + t1 = Init%PropsBC(P1, 6) + D2 = Init%PropsBC(P2, 5) + t2 = Init%PropsBC(P2, 6) r1 = 0.25*(D1 + D2) t = 0.5*(t1+t2) if ( EqualRealNos(t, 0.0_ReKi) ) then @@ -930,7 +1020,8 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) Ixx = 0.25*Pi_D*(r1**4-r2**4) Iyy = Ixx Jzz = 2.0*Ixx - + Jt = Jzz + if( Init%FEMMod == 1 ) then ! uniform Euler-Bernoulli Shear = .false. kappa = 0 @@ -949,6 +1040,7 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) p%ElemProps(i)%Ixx = Ixx p%ElemProps(i)%Iyy = Iyy p%ElemProps(i)%Jzz = Jzz + p%ElemProps(i)%Jt = Jt p%ElemProps(i)%Shear = Shear p%ElemProps(i)%Kappa_x = kappa p%ElemProps(i)%Kappa_y = kappa @@ -958,9 +1050,91 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) p%ElemProps(i)%Rho = rho p%ElemProps(i)%D = (/D1, D2/) + else if (eType==idMemberBeamRect) then + E = Init%PropsBR(P1, 2) ! TODO E2 + G = Init%PropsBR(P1, 3) ! TODO G2 + rho = Init%PropsBR(P1, 4) ! TODO rho2 + Sa1 = Init%PropsBR(P1, 5) + Sb1 = Init%PropsBR(P1, 6) + t1 = Init%PropsBR(P1, 7) + Sa2 = Init%PropsBR(P2, 5) + Sb2 = Init%PropsBR(P2, 6) + t2 = Init%PropsBR(P2, 7) + + Sa1 = 0.5*(Sa1 + Sa2) + Sb1 = 0.5*(Sb1 + Sb2) + t = 0.5*(t1+t2) + if ( EqualRealNos(t, 0.0_ReKi) ) then + Sa2 = 0 + Sb2 = 0 + else + Sa2 = Sa1 - 2.0*t + Sb2 = Sb1 - 2.0*t + endif + A = Sa1*Sb1 - Sa2*Sb2 + Ixx = (Sa1*Sb1**3 - Sa2*Sb2**3)/12.0 + Iyy = (Sa1**3*Sb1 - Sa2**3*Sb2)/12.0 + Jzz = (Sa1*Sb1*(Sa1*Sa1+Sb1*Sb1) - Sa2*Sb2*(Sa2*Sa2+Sb2*Sb2))/12.0 + + ! Torsion constant + if ( Sa2==0.0 .or. Sb2==0.0 ) then ! Solid rectangular section + if (Sa1 >= Sb1) then + Jt = Sa1*Sb1**3/16.0*(16.0/3.0-3.36*Sb1/Sa1*(1-Sb1**4/12.0/Sa1**4)) + else + Jt = Sb1*Sa1**3/16.0*(16.0/3.0-3.36*Sa1/Sb1*(1-Sa1**4/12.0/Sb1**4)) + end if + else ! Thin-walled approximation + Jt = 2.0*t*(Sa1-t)**2*(Sb1-t)**2/(Sa1+Sb1-2.0*t) + if ( t > 0.05*min(Sa1,Sb1) ) then + CALL WrScr('[WARNING] The torsion constants and shear coefficients for rectangular members are only valid for thin-walled sections or solid sections.') + end if + end if + + ! Shear coefficients + if( Init%FEMMod == 1 ) then ! uniform Euler-Bernoulli + Shear = .false. + kappa_x = 0. + kappa_y = 0. + elseif( Init%FEMMod == 3 ) then ! uniform Timoshenko + Shear = .true. + nu = E / (2.0_ReKi*G) - 1.0_ReKi + if ( Sa2==0.0 .or. Sb2==0.0 ) then ! Solid rectangular section + kappa_x = 10.0*(1.0+nu)/(12.0+11.0*nu) + kappa_y = kappa_x + else ! Thin-walled approximation + ! kappa_x = 1.0/(1.0+Sb1/Sa1) + ! kappa_y = 1.0/(1.0+Sa1/Sb1) + ratio = Sb2/Sa1 + kappa_x = 10.0*(1.0+nu)*(1.0+3.0*ratio)**2 / ( & + (12.0+72.0*ratio+150.0*ratio**2+90.0*ratio**3) + & + nu*(11.0+66.0*ratio+135.0*ratio**2+90.0*ratio**3) + & + 10.0*ratio**2*((3.0+nu)*ratio+3.0*ratio**2) ) + ratio = Sa2/Sb1 + kappa_y = 10.0*(1.0+nu)*(1.0+3.0*ratio)**2 / ( & + (12.0+72.0*ratio+150.0*ratio**2+90.0*ratio**3) + & + nu*(11.0+66.0*ratio+135.0*ratio**2+90.0*ratio**3) + & + 10.0*ratio**2*((3.0+nu)*ratio+3.0*ratio**2) ) + endif + endif + + ! Storing Beam specific properties + p%ElemProps(i)%Ixx = Ixx + p%ElemProps(i)%Iyy = Iyy + p%ElemProps(i)%Jzz = Jzz + p%ElemProps(i)%Jt = Jt + p%ElemProps(i)%Shear = Shear + p%ElemProps(i)%Kappa_x = kappa_x + p%ElemProps(i)%Kappa_y = kappa_y + p%ElemProps(i)%YoungE = E + p%ElemProps(i)%ShearG = G + p%ElemProps(i)%Area = A + p%ElemProps(i)%Rho = rho + p%ElemProps(i)%Sa = (/Init%PropsBR(P1, 5), Init%PropsBR(P2, 5)/) + p%ElemProps(i)%Sb = (/Init%PropsBR(P1, 6), Init%PropsBR(P2, 6)/) + else if (eType==idMemberBeamArb) then - p%ElemProps(i)%eType = 1 + ! p%ElemProps(i)%eType = 1 if( Init%FEMMod == 1 ) then ! uniform Euler-Bernoulli Shear = .false. elseif( Init%FEMMod == 3 ) then ! uniform Timoshenko @@ -980,12 +1154,14 @@ SUBROUTINE SetElementProperties(Init, p, ErrStat, ErrMsg) Ixx = (Init%PropSetsX(P1, 8) + Init%PropSetsX(P2, 8)) / 2 Iyy = (Init%PropSetsX(P1, 9) + Init%PropSetsX(P2, 9)) / 2 Jzz = (Init%PropSetsX(P1, 10) + Init%PropSetsX(P2, 10)) / 2 + Jt = (Init%PropSetsX(P1, 11) + Init%PropSetsX(P2, 11)) / 2 D1 = 2._ReKi*(A/PI)**0.5 !Approximation, this value should not be used D2 = D1 p%ElemProps(i)%Ixx = Ixx p%ElemProps(i)%Iyy = Iyy p%ElemProps(i)%Jzz = Jzz + p%ElemProps(i)%Jt = Jt p%ElemProps(i)%Shear = Shear p%ElemProps(i)%Kappa_x = kappa_x p%ElemProps(i)%Kappa_y = kappa_y @@ -2338,7 +2514,7 @@ SUBROUTINE ElemM(ep, Me) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property REAL(FEKi), INTENT(OUT) :: Me(12, 12) REAL(FEKi) :: L0, Eps0 - if (ep%eType==idMemberBeamCirc) then + if (ep%eType==idMemberBeamCirc .or. ep%eType==idMemberBeamRect .or. ep%eType==idMemberBeamArb) then !Calculate Ke, Me to be used for output CALL ElemM_Beam(eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%rho, eP%DirCos, Me) @@ -2365,8 +2541,8 @@ SUBROUTINE ElemK(ep, Ke) TYPE(ElemPropType), INTENT(IN) :: eP !< Element Property REAL(FEKi), INTENT(OUT) :: Ke(12, 12) - if (ep%eType==idMemberBeamCirc) then - CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jzz, eP%Shear, eP%Kappa_x, eP%Kappa_y, eP%YoungE, eP%ShearG, eP%DirCos, Ke) + if (ep%eType==idMemberBeamCirc .or. ep%eType==idMemberBeamRect .or. ep%eType==idMemberBeamArb) then + CALL ElemK_Beam( eP%Area, eP%Length, eP%Ixx, eP%Iyy, eP%Jt, eP%Shear, eP%Kappa_x, eP%Kappa_y, eP%YoungE, eP%ShearG, eP%DirCos, Ke) else if (ep%eType==idMemberCable) then CALL ElemK_Cable(ep%Area, ep%Length, ep%YoungE, ep%T0, eP%DirCos, Ke) @@ -2385,7 +2561,7 @@ SUBROUTINE ElemF(ep, gravity, Fg, Fo) REAL(ReKi), INTENT(IN) :: gravity !< acceleration of gravity REAL(FEKi), INTENT(OUT) :: Fg(12) REAL(FEKi), INTENT(OUT) :: Fo(12) - if (ep%eType==idMemberBeamCirc) then + if (ep%eType==idMemberBeamCirc .or. ep%eType==idMemberBeamRect .or. ep%eType==idMemberBeamArb) then Fo(1:12)=0.0_FEKi else if (ep%eType==idMemberCable) then CALL ElemF_Cable(ep%T0, ep%DirCos, Fo) diff --git a/modules/subdyn/src/SubDyn.f90 b/modules/subdyn/src/SubDyn.f90 index 26f1a1d44c..db36131b94 100644 --- a/modules/subdyn/src/SubDyn.f90 +++ b/modules/subdyn/src/SubDyn.f90 @@ -925,6 +925,8 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) INTEGER(IntKi) :: Dummy_IntAry(SDMaxInpCols) LOGICAL :: Dummy_Bool INTEGER(IntKi) :: Dummy_Int +REAL(R8Ki) :: tmpMat(3,3) + INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMsg2 ! Initialize ErrStat @@ -1224,36 +1226,52 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL ReadIVar ( UnIn, SDInputFile, p%NMembers, 'NMembers', 'Number of members',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Members Headers' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Members Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%Members, p%NMembers, MembersCol, 'Members', ErrStat2, ErrMsg2) -Init%Members(:,:) = 0.0_ReKi - -nColumns=MembersCol +CALL AllocAry(Init%Members, p%NMembers, MembersCol, 'Members', ErrStat2, ErrMsg2) +CALL AllocAry(Init%MemberSpin, p%NMembers, 'MemberSpin', ErrStat2, ErrMsg2) +Init%Members(:,:) = 0.0_IntKi +Init%MemberSpin(:) = 0.0_ReKi if (p%NMembers == 0) then CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": There should be at least one SubDyn member: "'//trim(Line)//'"') return endif -CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return -READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line ; ErrMsg2='First line of members array'; if (Failed()) return -CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Members', 'First line of members array', ErrStat2, ErrMsg2 ) -if (ErrStat2/=0) then - ! We try with one column less (legacy format) - nColumns = MembersCol-1 - deallocate(StrArray) - CALL AllocAry(StrArray, nColumns, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return - CALL ReadCAryFromStr ( Line, StrArray, nColumns, 'Members', 'First line of members array', ErrStat2, ErrMsg2 ); if(Failed()) return - call LegacyWarning('Member table contains 6 columns instead of 7, using default member directional cosines ID (-1) for all members. & - &The directional cosines will be computed based on the member nodes for all members.') - Init%Members(:,7) = -1 ! For the spring element, we need the direction cosine from the user. Both JointIDs are coincident, the direction cosine cannot be determined. -endif -! Extract fields from first line -DO I = 1, nColumns - bInteger = is_integer(StrArray(I), Init%Members(1,I)) ! Convert from string to float - if (.not.bInteger) then - CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Non integer character found in Member line. Problematic line: "'//trim(Line)//'"') - return - endif +CALL AllocAry(StrArray, MembersCol, 'StrArray',ErrStat2,ErrMsg2); if (Failed()) return +DO J = 1, p%NMembers + READ(UnIn, FMT='(A)', IOSTAT=ErrStat2) Line; ErrMsg2='Error reading SubDyn members table'; if (Failed()) return + CALL ReadCAryFromStr ( Line, StrArray, MembersCol, 'Members', 'SubDyn members table should have 7 entries on each line', ErrStat2, ErrMsg2 ); if (Failed()) return + ! Extract fields from first line + DO I = 1, MembersCol - 1 + bInteger = is_integer(StrArray(I), Init%Members(J,I)) ! Convert from string to integer + if ( (I==6) .and. ( trim(StrArray(I))=='1c' .or. trim(StrArray(I))=='1C' ) ) then + Init%Members(J,I) = idMemberBeamCirc + else if ( (I==6) .and. ( trim(StrArray(I))=='1r' .or. trim(StrArray(I))=='1R' ) ) then + Init%Members(J,I) = idMemberBeamRect + else if (.not.bInteger) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Non integer character found in Member line. Problematic line: "'//trim(Line)//'"') + return + end if + END DO + I = MembersCol + if ( Init%Members(J,6)==idMemberBeamCirc .or. Init%Members(J,6)==idMemberBeamRect .or. Init%Members(J,6)==idMemberBeamArb ) then + bNumeric = is_numeric( StrArray(I), Init%MemberSpin(J) ) + if (.not.bNumeric) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": The last input entry for a beam member should be an angle in degrees for the member spin orientation (MSpin). Problematic line: "'//trim(Line)//'"') + return + end if + Init%MemberSpin(J) = Init%MemberSpin(J) * D2R + Init%Members(J,I) = -1 + else if ( Init%Members(J,6)==idMemberCable .or. Init%Members(J,6)==idMemberRigid ) then + Init%MemberSpin(J) = 0 + Init%Members(J,I) = -1 + else + Init%MemberSpin(J) = 0 + bInteger = is_integer(StrArray(I), Init%Members(J,I)) ! Convert from string to integer + if (.not.bInteger) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Non integer character found for COSMID for a spring member. Problematic line: "'//trim(Line)//'"') + return + end if + end if ENDDO if (allocated(StrArray)) then @@ -1261,27 +1279,39 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) endif ! ! Read remaining lines -DO I = 2, p%NMembers - CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, nColumns, 'Members line '//Num2LStr(I), 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return - Init%Members(I,1:nColumns) = Dummy_IntAry(1:nColumns) -ENDDO +! DO I = 2, p%NMembers +! CALL ReadAry( UnIn, SDInputFile, Dummy_IntAry, nColumns, 'Members line '//Num2LStr(I), 'Member number and connectivity ', ErrStat2,ErrMsg2, UnEc); if(Failed()) return +! Init%Members(I,1:nColumns) = Dummy_IntAry(1:nColumns) +! ENDDO IF (Check( p%NMembers < 1 , 'NMembers must be > 0')) return -!------------------ MEMBER CROSS-SECTION PROPERTY data 1/2 [isotropic material for now: use this table if circular-tubular elements ------------------------ -CALL ReadCom ( UnIn, SDInputFile, ' Member CROSS-Section Property Data 1/2 ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsB, 'NPropSets', 'Number of property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +!------------------ MEMBER CROSS-SECTION PROPERTY data 1/3 [isotropic material for now: use this table if circular-tubular elements ------------------------ +CALL ReadCom ( UnIn, SDInputFile, ' Member CROSS-Section Property Data 1/3 ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsBC, 'NPropSets', 'Number of property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return -CALL AllocAry(Init%PropSetsB, Init%NPropSetsB, PropSetsBCol, 'ProSets', ErrStat2, ErrMsg2) ; if(Failed()) return -DO I = 1, Init%NPropSetsB - CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsBCol, 'PropSets', 'PropSets number and values ', ErrStat2 , ErrMsg2, UnEc); if(Failed()) return - Init%PropSetsB(I,:) = Dummy_ReAry(1:PropSetsBCol) +CALL AllocAry(Init%PropSetsBC, Init%NPropSetsBC, PropSetsBCCol, 'PropSets', ErrStat2, ErrMsg2) ; if(Failed()) return +DO I = 1, Init%NPropSetsBC + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsBCCol, 'PropSets', 'PropSets number and values ', ErrStat2 , ErrMsg2, UnEc); if(Failed()) return + Init%PropSetsBC(I,:) = Dummy_ReAry(1:PropSetsBCCol) ENDDO -IF (Check( Init%NPropSetsB < 1 , 'NPropSets must be >0')) return +IF (Check( Init%NPropSetsBC < 0, 'NPropSetsBC must be >=0')) return + +!------------------ MEMBER CROSS-SECTION PROPERTY data 2/3 [isotropic material for now: use this table if rectangular-tubular elements --------------------- +CALL ReadCom ( UnIn, SDInputFile, ' Member CROSS-Section Property Data 2/3 ',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsBR, 'NPropSets', 'Number of property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL ReadCom ( UnIn, SDInputFile, 'Property Data 1/2 Units ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +CALL AllocAry(Init%PropSetsBR, Init%NPropSetsBR, PropSetsBRCol, 'PropSets', ErrStat2, ErrMsg2) ; if(Failed()) return +DO I = 1, Init%NPropSetsBR + CALL ReadAry( UnIn, SDInputFile, Dummy_ReAry, PropSetsBRCol, 'PropSets', 'PropSets number and values ', ErrStat2 , ErrMsg2, UnEc); if(Failed()) return + Init%PropSetsBR(I,:) = Dummy_ReAry(1:PropSetsBRCol) +ENDDO +IF (Check( Init%NPropSetsBR < 0, 'NPropSetsBR must be >=0')) return -!------------------ MEMBER CROSS-SECTION PROPERTY data 2/2 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below) ------------------------ -CALL ReadCom ( UnIn, SDInputFile, 'Member CROSS-Section Property Data 2/2 ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return +!------------------ MEMBER CROSS-SECTION PROPERTY data 2/3 [isotropic material for now: use this table if any section other than circular, however provide COSM(i,j) below) ------------------------ +CALL ReadCom ( UnIn, SDInputFile, 'Member CROSS-Section Property Data 3/3 ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadIVar ( UnIn, SDInputFile, Init%NPropSetsX, 'NXPropSets', 'Number of non-circular property sets',ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Header' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return CALL ReadCom ( UnIn, SDInputFile, 'Property Data 2/2 Unit ' ,ErrStat2, ErrMsg2, UnEc ); if(Failed()) return @@ -1289,7 +1319,7 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) DO I = 1, Init%NPropSetsX CALL ReadAry( UnIn, SDInputFile, Init%PropSetsX(I,:), PropSetsXCol, 'XPropSets', 'XPropSets ID and values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return ENDDO -IF (Check( Init%NPropSetsX < 0, 'NXPropSets must be >=0')) return +IF (Check( Init%NPropSetsX < 0, 'NPropSetsX must be >=0')) return if (.not. LegacyFormat) then !-------------------------- CABLE PROPERTIES ------------------------------------- @@ -1367,6 +1397,25 @@ SUBROUTINE SD_Input(SDInputFile, Init, p, ErrStat,ErrMsg) CALL AllocAry(Init%COSMs, Init%NCOSMs, COSMsCol, 'COSMs', ErrStat2, ErrMsg2); if(Failed()) return DO I = 1, Init%NCOSMs CALL ReadAry( UnIn, SDInputFile, Init%COSMs(I,:), COSMsCol, 'CosM', 'Cosine Matrix IDs and Values ', ErrStat2, ErrMsg2, UnEc ); if(Failed()) return + tmpMat = reshape(Init%COSMs(I,2:COSMsCol),shape(tmpMat)) + tmpMat = matmul(tmpMat,transpose(tmpMat)) + tmpMat(1,1) = tmpMat(1,1)-1.0_R8Ki + tmpMat(2,2) = tmpMat(2,2)-1.0_R8Ki + tmpMat(3,3) = tmpMat(3,3)-1.0_R8Ki + tmpMat = ABS(tmpMat) + do j = 1,3 + do k = 1,3 + if (tmpMat(j,k) > 0.0001_R8Ki) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Member cosine matrix on line '//trim(Num2LStr(I))//' with COSMID '//trim(Num2LStr(Init%COSMs(I,1)))//' is not orthogonal to the required precision and is therefore not a valid rotation matrix. ') + return + end if + end do + end do + tmpMat = reshape(Init%COSMs(I,2:COSMsCol),shape(tmpMat)) + if ( Determinant(tmpMat, ErrStat2, ErrMsg2) < 0.0_R8Ki) then + CALL Fatal(' Error in file "'//TRIM(SDInputFile)//'": Member cosine matrix on line '//trim(Num2LStr(I))//' with COSMID '//trim(Num2LStr(Init%COSMs(I,1)))//' has a negative determinant and is therefore not a valid rotation matrix. ') + return + end if ENDDO IF (Check( Init%NCOSMs < 0 ,'NCOSMs must be >=0')) return @@ -3717,7 +3766,7 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, Modes, Omega, Omega_Gy, E REAL(ReKi) :: rOP(3) ! Vector from origin to P (ref point) REAL(ReKi) :: rPG(3) ! Vector from origin to G REAL(FEKi),allocatable :: MBB(:,:) ! Leader DOFs mass matrix - REAL(ReKi) :: XYZ1(3),XYZ2(3) !temporary arrays + REAL(ReKi) :: XYZ1(3),XYZ2(3),spin !temporary arrays REAL(FEKi) :: DirCos(3,3) ! direction cosine matrix (global to local) CHARACTER(*),PARAMETER :: SectionDivide = '#____________________________________________________________________________________________________' real(ReKi), dimension(:,:), allocatable :: TI2 ! For Equivalent mass matrix @@ -3852,27 +3901,29 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, Modes, Omega, Omega_Gy, E call yaml_write_array(UnSum, 'Nodes', Init%Nodes, ReFmt, ErrStat2, ErrMsg2, AllFmt='1(F8.0,","),3(F15.3,","),(F15.0,","),3(ES15.6,","),ES15.6') !, comment='',label=.true.) ! Element properties - CALL AllocAry( DummyArray, size(p%ElemProps), 16, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return + CALL AllocAry( DummyArray, size(p%ElemProps), 18, 'Elem', ErrStat2, ErrMsg2 ); if(Failed()) return do i=1,size(p%ElemProps) - DummyArray(i,1) = p%Elems(i,1) ! Should be == i - DummyArray(i,2) = p%Elems(i,2) ! Node 1 - DummyArray(i,3) = p%Elems(i,3) ! Node 2 - DummyArray(i,4) = p%Elems(i,4) ! Prop 1 - DummyArray(i,5) = p%Elems(i,5) ! Prop 2 - DummyArray(i,6) = p%ElemProps(i)%eType ! Type - DummyArray(i,7) = p%ElemProps(i)%Length !Length - DummyArray(i,8) = p%ElemProps(i)%Area ! Area m^2 - DummyArray(i,9) = p%ElemProps(i)%Rho ! density kg/m^3 - DummyArray(i,10) = p%ElemProps(i)%YoungE ! Young modulus - DummyArray(i,11) = p%ElemProps(i)%ShearG ! G - DummyArray(i,12) = p%ElemProps(i)%Kappa_x ! Shear coefficient - DummyArray(i,13) = p%ElemProps(i)%Ixx ! Moment of inertia - DummyArray(i,14) = p%ElemProps(i)%Iyy ! Moment of inertia - DummyArray(i,15) = p%ElemProps(i)%Jzz ! Moment of inertia - DummyArray(i,16) = p%ElemProps(i)%T0 ! Pretension [N] - enddo - write(UnSum, '("#",4x,6(A9),10('//SFmt//'))') 'Elem_[#] ','Node_1','Node_2','Prop_1','Prop_2','Type','Length_[m]','Area_[m^2]','Dens._[kg/m^3]','E_[N/m2]','G_[N/m2]','shear_[-]','Ixx_[m^4]','Iyy_[m^4]','Jzz_[m^4]','T0_[N]' - call yaml_write_array(UnSum, 'Elements', DummyArray, ReFmt, ErrStat2, ErrMsg2, AllFmt='6(F8.0,","),3(F15.3,","),6(ES15.6,","),ES15.6') !, comment='',label=.true.) + DummyArray(i,1) = p%Elems(i,1) ! Should be == i + DummyArray(i,2) = p%Elems(i,2) ! Node 1 + DummyArray(i,3) = p%Elems(i,3) ! Node 2 + DummyArray(i,4) = p%Elems(i,4) ! Prop 1 + DummyArray(i,5) = p%Elems(i,5) ! Prop 2 + DummyArray(i,6) = p%ElemProps(i)%eType ! Type + DummyArray(i,7) = p%ElemProps(i)%Length ! Length [m] + DummyArray(i,8) = p%ElemProps(i)%Area ! Area [m^2] + DummyArray(i,9) = p%ElemProps(i)%Rho ! density [kg/m^3] + DummyArray(i,10) = p%ElemProps(i)%YoungE ! Young's modulus + DummyArray(i,11) = p%ElemProps(i)%ShearG ! Shear modulus + DummyArray(i,12) = p%ElemProps(i)%Kappa_x ! Shear area coefficient + DummyArray(i,13) = p%ElemProps(i)%Kappa_y ! Shear area coefficient + DummyArray(i,14) = p%ElemProps(i)%Ixx ! Area moment of inertia [m^4] + DummyArray(i,15) = p%ElemProps(i)%Iyy ! Area moment of inertia [m^4] + DummyArray(i,16) = p%ElemProps(i)%Jzz ! Polar area moment of inertia [m^4] + DummyArray(i,17) = p%ElemProps(i)%Jt ! Torsion constant [m^4] + DummyArray(i,18) = p%ElemProps(i)%T0 ! Pretension [N] + end do + write(UnSum, '("#",4x,6(A9),12('//SFmt//'))') 'Elem_[#] ','Node_1','Node_2','Prop_1','Prop_2','Type','Length_[m]','Area_[m^2]','Dens._[kg/m^3]','E_[N/m2]','G_[N/m2]','kappa_x_[-]','kappa_y_[-]','Ixx_[m^4]','Iyy_[m^4]','Jzz_[m^4]','Jt_[m^4]','T0_[N]' + call yaml_write_array(UnSum, 'Elements', DummyArray, ReFmt, ErrStat2, ErrMsg2, AllFmt='6(F8.0,","),3(F15.3,","),8(ES15.6,","),ES15.6') !, comment='',label=.true.) deallocate(DummyArray) ! --- C @@ -3895,10 +3946,18 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, Modes, Omega, Omega_Gy, E ! --- User inputs (less interesting, repeat of input file) WRITE(UnSum, '(A)') SectionDivide WRITE(UnSum, '(A)') '#User inputs' - WRITE(UnSum, '()') - WRITE(UnSum, '(A,I6)') '#Number of properties (NProps):',Init%NPropB + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') '#Number of circular-section beam properties (NProps):',Init%NPropBC WRITE(UnSum, '(A8,5(A15))') '#Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT' - WRITE(UnSum, '("#",I8, ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2 ) ') (NINT(Init%PropsB(i, 1)), (Init%PropsB(i, j), j = 2, 6), i = 1, Init%NPropB) + WRITE(UnSum, '("#",I8, ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2 ) ') (NINT(Init%PropsBC(i, 1)), (Init%PropsBC(i, j), j = 2, 6), i = 1, Init%NPropBC) + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') '#Number of rectangular-section beam properties (NProps):',Init%NPropBR + WRITE(UnSum, '(A8,6(A15))') '#Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecSa', 'XsecSb', 'XsecT' + WRITE(UnSum, '("#",I8, ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2 ) ') (NINT(Init%PropsBR(i, 1)), (Init%PropsBR(i, j), j = 2, 7), i = 1, Init%NPropBR) + WRITE(UnSum, '()') + WRITE(UnSum, '(A,I6)') '#Number of arbitrary-section beam properties (NProps):',Init%NPropSetsX + WRITE(UnSum, '(A8,10(A15))') '#Prop No.', 'YoungE', 'ShearG', 'MatDens', 'XsecA', 'XsecAsx', 'XsecAsy', 'XsecJxx', 'XsecJyy', 'XsecJ0', 'XsecJt' + WRITE(UnSum, '("#",I8, ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2,ES15.6E2 ) ') (NINT(Init%PropSetsX(i, 1)), (Init%PropSetsX(i, j), j = 2, 11), i = 1, Init%NPropSetsX) WRITE(UnSum, '()') WRITE(UnSum, '(A,I6)') '#No. of Reaction DOFs:',p%nDOFC__ @@ -3929,15 +3988,23 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, Modes, Omega, Omega_Gy, E !IT WILL HAVE TO BE MODIFIED FOR OTHER THAN CIRCULAR PIPE ELEMENTS propIDs=Init%Members(i,iMProp:iMProp+1) if (Init%Members(I, iMType)/=idMemberSpring) then ! This check only applies for members different than springs (springs have no mass and no length) - mLength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) ! TODO double check mass and length + mLength=MemberLength(Init%Members(i,1),Init,ErrStat,ErrMsg) ! TODO double check mass and length endif IF (ErrStat .EQ. ErrID_None) THEN - mType = Init%Members(I, iMType) ! + mType = Init%Members(I, iMType) if (mType==idMemberBeamCirc) then - iProp(1) = FINDLOCI(Init%PropSetsB(:,1), propIDs(1)) - iProp(2) = FINDLOCI(Init%PropSetsB(:,1), propIDs(2)) - mMass= BeamMass(Init%PropSetsB(iProp(1),4),Init%PropSetsB(iProp(1),5),Init%PropSetsB(iProp(1),6), & - Init%PropSetsB(iProp(2),4),Init%PropSetsB(iProp(2),5),Init%PropSetsB(iProp(2),6), mLength, method=-1) + iProp(1) = FINDLOCI(Init%PropSetsBC(:,1), propIDs(1)) + iProp(2) = FINDLOCI(Init%PropSetsBC(:,1), propIDs(2)) + mMass = BeamMassC(Init%PropSetsBC(iProp(1),4),Init%PropSetsBC(iProp(1),5),Init%PropSetsBC(iProp(1),6), & + Init%PropSetsBC(iProp(2),4),Init%PropSetsBC(iProp(2),5),Init%PropSetsBC(iProp(2),6), mLength, method=-1) + + WRITE(UnSum, '("#",I9,I10,I10,I10,I10,ES15.6E2,ES15.6E2, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propIDs(1),propIDs(2),& + mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) + else if (mType==idMemberBeamRect) then + iProp(1) = FINDLOCI(Init%PropSetsBR(:,1), propIDs(1)) + iProp(2) = FINDLOCI(Init%PropSetsBR(:,1), propIDs(2)) + mMass = BeamMassR(Init%PropSetsBR(iProp(1),4),Init%PropSetsBR(iProp(1),5),Init%PropSetsBR(iProp(1),6),Init%PropSetsBR(iProp(1),7), & + Init%PropSetsBR(iProp(2),4),Init%PropSetsBR(iProp(2),5),Init%PropSetsBR(iProp(2),6),Init%PropSetsBR(iProp(2),7), mLength, method=-1) WRITE(UnSum, '("#",I9,I10,I10,I10,I10,ES15.6E2,ES15.6E2, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propIDs(1),propIDs(2),& mMass,mLength,' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) @@ -3960,7 +4027,7 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, Modes, Omega, Omega_Gy, E else if (mType==idMemberBeamArb) then iProp(1) = FINDLOCI(Init%PropSetsX(:,1), propIDs(1)) iProp(2) = FINDLOCI(Init%PropSetsX(:,1), propIDs(2)) - mMass= -1 ! TODO compute mass for arbitrary beams + mMass = Init%PropSetsX(iProp(1),4) * Init%PropSetsX(iProp(1),5) * mLength ! Simplified calculation because arbitrary beams only support uniform section properties WRITE(UnSum, '("#",I9,I10,I10,I10,I10,ES15.6E2,ES15.6E2, A3,'//Num2LStr(Init%NDiv + 1 )//'(I6))') Init%Members(i,1:3),propIDs(1),propIDs(2),& mMass, mLength,' ',(Init%MemberNodes(i, j), j = 1, Init%NDiv+1) else @@ -3977,12 +4044,13 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, Modes, Omega, Omega_Gy, E WRITE(UnSum, '(A, I6)') '#Direction Cosine Matrices for all Members: GLOBAL-2-LOCAL. No. of 3x3 matrices=', p%NMembers WRITE(UnSum, '(A9,9(A15))') '#Member ID', 'DC(1,1)', 'DC(1,2)', 'DC(1,3)', 'DC(2,1)','DC(2,2)','DC(2,3)','DC(3,1)','DC(3,2)','DC(3,3)' DO i=1,p%NMembers - mType = Init%Members(I, iMType) + mType = Init%Members(I, iMType) iNode1 = FINDLOCI(Init%Joints(:,1), Init%Members(i,2)) ! index of joint 1 of member i iNode2 = FINDLOCI(Init%Joints(:,1), Init%Members(i,3)) ! index of joint 2 of member i XYZ1 = Init%Joints(iNode1,2:4) XYZ2 = Init%Joints(iNode2,2:4) - if ((mType == idMemberSpring) .or. (mType == idMemberBeamArb)) then ! The direction cosine for these member types must be provided by the user + spin = Init%MemberSpin(I) + if ( mType == idMemberSpring ) then ! The direction cosine for these member types must be provided by the user iDirCos = p%Elems(i, iMDirCosID) DirCos(1, 1) = Init%COSMs(iDirCos, 2) DirCos(2, 1) = Init%COSMs(iDirCos, 3) @@ -3994,7 +4062,7 @@ SUBROUTINE OutSummary(Init, p, m, InitInput, CBparams, Modes, Omega, Omega_Gy, E DirCos(2, 3) = Init%COSMs(iDirCos, 9) DirCos(3, 3) = Init%COSMs(iDirCos, 10) else - CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), mType, DirCos, mLength, ErrStat, ErrMsg) + CALL GetDirCos(XYZ1(1:3), XYZ2(1:3), spin, mType, DirCos, mLength, ErrStat, ErrMsg) endif DirCos=TRANSPOSE(DirCos) !This is now global to local WRITE(UnSum, '("#",I9,9(ES28.18E2))') Init%Members(i,1), ((DirCos(k,j),j=1,3),k=1,3) @@ -4275,10 +4343,10 @@ END FUNCTION MemberLength !------------------------------------------------------------------------------------------------------ !> Calculate member mass, given properties at the ends, keep units consistent !! For now it works only for circular pipes or for a linearly varying area -FUNCTION BeamMass(rho1,D1,t1,rho2,D2,t2,L,method) +FUNCTION BeamMassC(rho1,D1,t1,rho2,D2,t2,L,method) REAL(ReKi), INTENT(IN) :: rho1,D1,t1,rho2,D2,t2 ,L ! Density, OD and wall thickness for circular tube members at ends, Length of member INTEGER(IntKi), INTENT(IN) :: method ! -1: FEM compatible, 0: mid values, 1: circular tube, integral, - REAL(ReKi) :: BeamMass !mass + REAL(ReKi) :: BeamMassC !mass REAL(ReKi) :: a0,a1,a2,b0,b1,dd,dt !temporary coefficients REAL(ReKi) :: Area,r1,r2,t !Density allowed to vary linearly only @@ -4296,9 +4364,9 @@ FUNCTION BeamMass(rho1,D1,t1,rho2,D2,t2,L,method) endif Area = Pi_D*(r1*r1-r2*r2) if (method==0) then - BeamMass= (rho2+rho1)/2 * L * Area + BeamMassC= (rho2+rho1)/2 * L * Area else - BeamMass = rho1 * L * Area ! WHAT is currently used by FEM + BeamMassC = rho1 * L * Area ! WHAT is currently used by FEM endif ELSEIF (method==1) THEN !circular tube a0=pi * (D1*t1-t1**2.) @@ -4306,18 +4374,46 @@ FUNCTION BeamMass(rho1,D1,t1,rho2,D2,t2,L,method) dd=D2-D1 !OD variation a1=pi * ( dd*t1 + D1*dt -2.*t1*dt)/L a2=pi * ( dd*dt-dt**2.)/L**2. - BeamMass = b0*a0*L +(a0*b1+b0*a1)*L**2/2. + (b0*a2+b1*a1)*L**3/3 + a2*b1*L**4/4.!Integral of rho*A dz + BeamMassC = b0*a0*L +(a0*b1+b0*a1)*L**2/2. + (b0*a2+b1*a1)*L**3/3 + a2*b1*L**4/4.!Integral of rho*A dz ELSEIF (method==2) THEN !linearly varying area a0=D1 !This is an area a1=(D2-D1)/L !Delta area a2=0. - BeamMass = b0*a0*L +(a0*b1+b0*a1)*L**2/2. + (b0*a2+b1*a1)*L**3/3 + a2*b1*L**4/4.!Integral of rho*A dz + BeamMassC = b0*a0*L +(a0*b1+b0*a1)*L**2/2. + (b0*a2+b1*a1)*L**3/3 + a2*b1*L**4/4.!Integral of rho*A dz + ELSE + print*,'Wrong call to BeamMassC, method unknown',method + STOP + ENDIF + +END FUNCTION BeamMassC + +FUNCTION BeamMassR(rho1,Sa1,Sb1,t1,rho2,Sa2,Sb2,t2,L,method) + REAL(ReKi), INTENT(IN) :: rho1,Sa1,Sb1,t1,rho2,Sa2,Sb2,t2,L ! Density, outer side lenghts and wall thickness for rectangular tube members at ends, Length of member + INTEGER(IntKi), INTENT(IN) :: method ! -1: FEM compatible + REAL(ReKi) :: BeamMassR !mass + REAL(ReKi) :: Sa,Sb,SaIn,SbIn !temporary coefficients + REAL(ReKi) :: Area,t + ! Density currently not allowed to vary + IF (method<=0) THEN + ! Mid values for Sa, Sb, and t + Sa = 0.5_ReKi*(Sa1 + Sa2) + Sb = 0.5_ReKi*(Sb1 + Sb2) + t = 0.5_ReKi*( t1 + t2) + if ( EqualRealNos(t, 0.0_ReKi) ) then + SaIn = 0.0 + SbIn = 0.0 + else + SaIn = Sa - 2.0*t + SbIn = Sb - 2.0*t + endif + Area = Sa*Sb-SaIn*SbIn + BeamMassR = rho1 * L * Area ! WHAT is currently used by FEM ELSE - print*,'Wrong call to BeamMass, method unknown',method + print*,'Wrong call to BeamMassR, method unknown',method STOP ENDIF -END FUNCTION BeamMass +END FUNCTION BeamMassR !------------------------------------------------------------------------------------------------------ !> Check whether MAT IS SYMMETRIC AND RETURNS THE MAXIMUM RELATIVE ERROR diff --git a/modules/subdyn/src/SubDyn_Registry.txt b/modules/subdyn/src/SubDyn_Registry.txt index 80af480766..2c11d63158 100644 --- a/modules/subdyn/src/SubDyn_Registry.txt +++ b/modules/subdyn/src/SubDyn_Registry.txt @@ -32,6 +32,7 @@ typedef ^ ElemPropType ReKi Length - - - "Length of an element" typedef ^ ElemPropType ReKi Ixx - - - "Moment of inertia of an element" typedef ^ ElemPropType ReKi Iyy - - - "Moment of inertia of an element" typedef ^ ElemPropType ReKi Jzz - - - "Moment of inertia of an element" +typedef ^ ElemPropType ReKi Jt - - - "Torsion constant of an element" typedef ^ ElemPropType LOGICAL Shear - - - "Use timoshenko (true) E-B (false)" typedef ^ ElemPropType ReKi Kappa_x - - - "Shear coefficient" typedef ^ ElemPropType ReKi Kappa_y - - - "Shear coefficient" @@ -39,6 +40,8 @@ typedef ^ ElemPropType ReKi YoungE - - - "Young's modulus" typedef ^ ElemPropType ReKi ShearG - - - "Shear modulus" N/m^2 # Properties common to all element types: typedef ^ ElemPropType ReKi D {2} - - "Diameter at node 1 and 2, for visualization only" m +typedef ^ ElemPropType ReKi Sa {2} - - "Side A lengths at node 1 and 2, for visualization only" m +typedef ^ ElemPropType ReKi Sb {2} - - "Side B lengths at node 1 and 2, for visualization only" m typedef ^ ElemPropType ReKi Area - - - "Area of an element" m^2 typedef ^ ElemPropType ReKi Rho - - - "Density" kg/m^3 typedef ^ ElemPropType ReKi T0 - - - "Pretension " N @@ -99,7 +102,8 @@ typedef ^ SD_InitType ReKi g - - - "Gravity a typedef ^ SD_InitType DbKi DT - - - "Time step from Glue Code" seconds typedef ^ SD_InitType INTEGER NJoints - - - "Number of joints of the sub structure" typedef ^ SD_InitType INTEGER NPropSetsX - - - "Number of extended property sets" -typedef ^ SD_InitType INTEGER NPropSetsB - - - "Number of property sets for beams" +typedef ^ SD_InitType INTEGER NPropSetsBC - - - "Number of property sets for beams with a circular section" +typedef ^ SD_InitType INTEGER NPropSetsBR - - - "Number of property sets for beams with a rectangular section" typedef ^ SD_InitType INTEGER NPropSetsC - - - "Number of property sets for cables" typedef ^ SD_InitType INTEGER NPropSetsR - - - "Number of property sets for rigid links" typedef ^ SD_InitType INTEGER NPropSetsS - - - "Number of property sets for spring elements" @@ -109,7 +113,8 @@ typedef ^ SD_InitType INTEGER FEMMod - - - "FEM switc typedef ^ SD_InitType INTEGER NDiv - - - "Number of divisions for each member" typedef ^ SD_InitType LOGICAL CBMod - - - "Perform C-B flag" typedef ^ SD_InitType ReKi Joints {:}{:} - - "Joints number and coordinate values" -typedef ^ SD_InitType ReKi PropSetsB {:}{:} - - "Property sets number and values" +typedef ^ SD_InitType ReKi PropSetsBC {:}{:} - - "Property sets number and values for circular beam sections" +typedef ^ SD_InitType ReKi PropSetsBR {:}{:} - - "Property sets number and values for rectangular beam sections" typedef ^ SD_InitType ReKi PropSetsC {:}{:} - - "Property ID and values for cables" typedef ^ SD_InitType ReKi PropSetsR {:}{:} - - "Property ID and values for rigid link" typedef ^ SD_InitType ReKi PropSetsS {:}{:} - - "Property ID and values for spring element" @@ -121,6 +126,7 @@ typedef ^ SD_InitType IntKi GuyanDampMod - - - "Guyan dam typedef ^ SD_InitType ReKi RayleighDamp {2} - - "Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1]" typedef ^ SD_InitType ReKi GuyanDampMat {6}{6} - - "Guyan Damping Matrix, see also CBB" typedef ^ SD_InitType INTEGER Members {:}{:} - - "Member joints connection " +typedef ^ SD_InitType ReKi MemberSpin {:} - - "Member spin angle about its axis - for rectangular members " rad typedef ^ SD_InitType CHARACTER(ChanLen) SSOutList {:} - - "List of Output Channels " typedef ^ SD_InitType LOGICAL OutCOSM - - - "Output Cos-matrices Flag " typedef ^ SD_InitType LOGICAL TabDelim - - - "Generate a tab-delimited output file in OutJckF-Flag " @@ -131,12 +137,15 @@ typedef ^ SD_InitType ReKi Soil_K {:}{:}{:} - - "Soil stif typedef ^ SD_InitType ReKi Soil_Points {:}{:} - - "Node positions where soil stiffness will be added " typedef ^ SD_InitType Integer Soil_Nodes {:} - - "Node indices where soil stiffness will be added " typedef ^ SD_InitType INTEGER NElem - - - "Total number of elements" -typedef ^ SD_InitType INTEGER NPropB - - - "Total number of property sets for Beams" +typedef ^ SD_InitType INTEGER NPropBC - - - "Total number of property sets for Beams with a circular section" +typedef ^ SD_InitType INTEGER NPropBR - - - "Total number of property sets for Beams with a rectangular section" +typedef ^ SD_InitType INTEGER NPropX - - - "Total number of property sets for Beams with an arbitrary section" typedef ^ SD_InitType INTEGER NPropC - - - "Total number of property sets for Cable" typedef ^ SD_InitType INTEGER NPropR - - - "Total number of property sets for Rigid" typedef ^ SD_InitType INTEGER NPropS - - - "Total number of property sets for Spring" typedef ^ SD_InitType ReKi Nodes {:}{:} - - "Nodes number and coordinates " -typedef ^ SD_InitType ReKi PropsB {:}{:} - - "Property sets and values for Beams " +typedef ^ SD_InitType ReKi PropsBC {:}{:} - - "Property sets and values for Beams with a circular section" +typedef ^ SD_InitType ReKi PropsBR {:}{:} - - "Property sets and values for Beams with a rectangular section" typedef ^ SD_InitType ReKi PropsC {:}{:} - - "Property sets and values for Cable " typedef ^ SD_InitType ReKi PropsR {:}{:} - - "Property sets and values for Rigid link" typedef ^ SD_InitType ReKi PropsS {:}{:} - - "Property sets and values for Spring " @@ -205,6 +214,7 @@ typedef ^ ParameterType INTEGER nDOF - - - "Total degree typedef ^ ParameterType INTEGER nDOF_red - - - "Total degree of freedom after constraint reduction" typedef ^ ParameterType IntKi Nmembers - - - "Number of members of the sub structure" typedef ^ ParameterType IntKi Elems {:}{:} - - "Element nodes connections" +typedef ^ ParameterType ReKi ElemSpin {:} - - "Element spin angle about its axis" rad typedef ^ ParameterType ElemPropType ElemProps {:} - - "List of element properties" typedef ^ ParameterType R8Ki FC {:} - - "Initial cable force T0, not reduced" N typedef ^ ParameterType R8Ki FG {:} - - "Gravity force vector, not reduced" N diff --git a/modules/subdyn/src/SubDyn_Tests.f90 b/modules/subdyn/src/SubDyn_Tests.f90 index 6576a77c05..b8653d5b12 100644 --- a/modules/subdyn/src/SubDyn_Tests.f90 +++ b/modules/subdyn/src/SubDyn_Tests.f90 @@ -326,14 +326,15 @@ subroutine Test_Transformations(ErrStat,ErrMsg) integer(IntKi) :: eType real(FEKi), dimension(3,3) :: DirCos, Ref real(ReKi), dimension(6,6) :: T, Tref - real(ReKi) :: L + real(ReKi) :: L, spin integer(IntKi) :: I testname='Transf' ! --- DirCos P1=(/0,0,0/) P2=(/2,0,0/) - call GetDirCos(P1, P2, eType, DirCos, L, ErrStat, ErrMsg) + spin = 0.0 + call GetDirCos(P1, P2, spin, eType, DirCos, L, ErrStat, ErrMsg) Ref = reshape( (/0_FEKi,-1_FEKi,0_FEKi, 0_FEKi, 0_FEKi, -1_FEKi, 1_FEKi, 0_FEKi, 0_FEKi/) , (/3,3/)) call test_almost_equal('DirCos',Ref,DirCos,1e-8_FEKi,.true.,.true.) diff --git a/modules/subdyn/src/SubDyn_Types.f90 b/modules/subdyn/src/SubDyn_Types.f90 index 6a539f1ab2..b14e3c83bd 100644 --- a/modules/subdyn/src/SubDyn_Types.f90 +++ b/modules/subdyn/src/SubDyn_Types.f90 @@ -68,12 +68,15 @@ MODULE SubDyn_Types REAL(ReKi) :: Ixx = 0.0_ReKi !< Moment of inertia of an element [-] REAL(ReKi) :: Iyy = 0.0_ReKi !< Moment of inertia of an element [-] REAL(ReKi) :: Jzz = 0.0_ReKi !< Moment of inertia of an element [-] + REAL(ReKi) :: Jt = 0.0_ReKi !< Torsion constant of an element [-] LOGICAL :: Shear = .false. !< Use timoshenko (true) E-B (false) [-] REAL(ReKi) :: Kappa_x = 0.0_ReKi !< Shear coefficient [-] REAL(ReKi) :: Kappa_y = 0.0_ReKi !< Shear coefficient [-] REAL(ReKi) :: YoungE = 0.0_ReKi !< Young's modulus [-] REAL(ReKi) :: ShearG = 0.0_ReKi !< Shear modulus [N/m^2] REAL(ReKi) , DIMENSION(1:2) :: D = 0.0_ReKi !< Diameter at node 1 and 2, for visualization only [m] + REAL(ReKi) , DIMENSION(1:2) :: Sa = 0.0_ReKi !< Side A lengths at node 1 and 2, for visualization only [m] + REAL(ReKi) , DIMENSION(1:2) :: Sb = 0.0_ReKi !< Side B lengths at node 1 and 2, for visualization only [m] REAL(ReKi) :: Area = 0.0_ReKi !< Area of an element [m^2] REAL(ReKi) :: Rho = 0.0_ReKi !< Density [kg/m^3] REAL(ReKi) :: T0 = 0.0_ReKi !< Pretension [N] @@ -139,7 +142,8 @@ MODULE SubDyn_Types REAL(DbKi) :: DT = 0.0_R8Ki !< Time step from Glue Code [seconds] INTEGER(IntKi) :: NJoints = 0_IntKi !< Number of joints of the sub structure [-] INTEGER(IntKi) :: NPropSetsX = 0_IntKi !< Number of extended property sets [-] - INTEGER(IntKi) :: NPropSetsB = 0_IntKi !< Number of property sets for beams [-] + INTEGER(IntKi) :: NPropSetsBC = 0_IntKi !< Number of property sets for beams with a circular section [-] + INTEGER(IntKi) :: NPropSetsBR = 0_IntKi !< Number of property sets for beams with a rectangular section [-] INTEGER(IntKi) :: NPropSetsC = 0_IntKi !< Number of property sets for cables [-] INTEGER(IntKi) :: NPropSetsR = 0_IntKi !< Number of property sets for rigid links [-] INTEGER(IntKi) :: NPropSetsS = 0_IntKi !< Number of property sets for spring elements [-] @@ -149,7 +153,8 @@ MODULE SubDyn_Types INTEGER(IntKi) :: NDiv = 0_IntKi !< Number of divisions for each member [-] LOGICAL :: CBMod = .false. !< Perform C-B flag [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Joints !< Joints number and coordinate values [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsB !< Property sets number and values [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsBC !< Property sets number and values for circular beam sections [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsBR !< Property sets number and values for rectangular beam sections [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsC !< Property ID and values for cables [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsR !< Property ID and values for rigid link [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropSetsS !< Property ID and values for spring element [-] @@ -161,6 +166,7 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(1:2) :: RayleighDamp = 0.0_ReKi !< Mass and stiffness proportional damping coefficients (Rayleigh Damping) [only if GuyanDampMod=1] [-] REAL(ReKi) , DIMENSION(1:6,1:6) :: GuyanDampMat = 0.0_ReKi !< Guyan Damping Matrix, see also CBB [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Members !< Member joints connection [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: MemberSpin !< Member spin angle about its axis - for rectangular members [rad] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: SSOutList !< List of Output Channels [-] LOGICAL :: OutCOSM = .false. !< Output Cos-matrices Flag [-] LOGICAL :: TabDelim = .false. !< Generate a tab-delimited output file in OutJckF-Flag [-] @@ -171,12 +177,15 @@ MODULE SubDyn_Types REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Soil_Points !< Node positions where soil stiffness will be added [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: Soil_Nodes !< Node indices where soil stiffness will be added [-] INTEGER(IntKi) :: NElem = 0_IntKi !< Total number of elements [-] - INTEGER(IntKi) :: NPropB = 0_IntKi !< Total number of property sets for Beams [-] + INTEGER(IntKi) :: NPropBC = 0_IntKi !< Total number of property sets for Beams with a circular section [-] + INTEGER(IntKi) :: NPropBR = 0_IntKi !< Total number of property sets for Beams with a rectangular section [-] + INTEGER(IntKi) :: NPropX = 0_IntKi !< Total number of property sets for Beams with an arbitrary section [-] INTEGER(IntKi) :: NPropC = 0_IntKi !< Total number of property sets for Cable [-] INTEGER(IntKi) :: NPropR = 0_IntKi !< Total number of property sets for Rigid [-] INTEGER(IntKi) :: NPropS = 0_IntKi !< Total number of property sets for Spring [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Nodes !< Nodes number and coordinates [-] - REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsB !< Property sets and values for Beams [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsBC !< Property sets and values for Beams with a circular section [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsBR !< Property sets and values for Beams with a rectangular section [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsC !< Property sets and values for Cable [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsR !< Property sets and values for Rigid link [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PropsS !< Property sets and values for Spring [-] @@ -254,6 +263,7 @@ MODULE SubDyn_Types INTEGER(IntKi) :: nDOF_red = 0_IntKi !< Total degree of freedom after constraint reduction [-] INTEGER(IntKi) :: Nmembers = 0_IntKi !< Number of members of the sub structure [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: Elems !< Element nodes connections [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: ElemSpin !< Element spin angle about its axis [rad] TYPE(ElemPropType) , DIMENSION(:), ALLOCATABLE :: ElemProps !< List of element properties [-] REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FC !< Initial cable force T0, not reduced [N] REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: FG !< Gravity force vector, not reduced [N] @@ -753,12 +763,15 @@ subroutine SD_CopyElemPropType(SrcElemPropTypeData, DstElemPropTypeData, CtrlCod DstElemPropTypeData%Ixx = SrcElemPropTypeData%Ixx DstElemPropTypeData%Iyy = SrcElemPropTypeData%Iyy DstElemPropTypeData%Jzz = SrcElemPropTypeData%Jzz + DstElemPropTypeData%Jt = SrcElemPropTypeData%Jt DstElemPropTypeData%Shear = SrcElemPropTypeData%Shear DstElemPropTypeData%Kappa_x = SrcElemPropTypeData%Kappa_x DstElemPropTypeData%Kappa_y = SrcElemPropTypeData%Kappa_y DstElemPropTypeData%YoungE = SrcElemPropTypeData%YoungE DstElemPropTypeData%ShearG = SrcElemPropTypeData%ShearG DstElemPropTypeData%D = SrcElemPropTypeData%D + DstElemPropTypeData%Sa = SrcElemPropTypeData%Sa + DstElemPropTypeData%Sb = SrcElemPropTypeData%Sb DstElemPropTypeData%Area = SrcElemPropTypeData%Area DstElemPropTypeData%Rho = SrcElemPropTypeData%Rho DstElemPropTypeData%T0 = SrcElemPropTypeData%T0 @@ -805,12 +818,15 @@ subroutine SD_PackElemPropType(RF, Indata) call RegPack(RF, InData%Ixx) call RegPack(RF, InData%Iyy) call RegPack(RF, InData%Jzz) + call RegPack(RF, InData%Jt) call RegPack(RF, InData%Shear) call RegPack(RF, InData%Kappa_x) call RegPack(RF, InData%Kappa_y) call RegPack(RF, InData%YoungE) call RegPack(RF, InData%ShearG) call RegPack(RF, InData%D) + call RegPack(RF, InData%Sa) + call RegPack(RF, InData%Sb) call RegPack(RF, InData%Area) call RegPack(RF, InData%Rho) call RegPack(RF, InData%T0) @@ -849,12 +865,15 @@ subroutine SD_UnPackElemPropType(RF, OutData) call RegUnpack(RF, OutData%Ixx); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Iyy); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Jzz); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%Jt); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Shear); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Kappa_x); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Kappa_y); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%YoungE); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%ShearG); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%D); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%Sa); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%Sb); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Area); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Rho); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%T0); if (RegCheckErr(RF, RoutineName)) return @@ -1225,7 +1244,8 @@ subroutine SD_CopyInitType(SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, DstInitTypeData%DT = SrcInitTypeData%DT DstInitTypeData%NJoints = SrcInitTypeData%NJoints DstInitTypeData%NPropSetsX = SrcInitTypeData%NPropSetsX - DstInitTypeData%NPropSetsB = SrcInitTypeData%NPropSetsB + DstInitTypeData%NPropSetsBC = SrcInitTypeData%NPropSetsBC + DstInitTypeData%NPropSetsBR = SrcInitTypeData%NPropSetsBR DstInitTypeData%NPropSetsC = SrcInitTypeData%NPropSetsC DstInitTypeData%NPropSetsR = SrcInitTypeData%NPropSetsR DstInitTypeData%NPropSetsS = SrcInitTypeData%NPropSetsS @@ -1246,17 +1266,29 @@ subroutine SD_CopyInitType(SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, end if DstInitTypeData%Joints = SrcInitTypeData%Joints end if - if (allocated(SrcInitTypeData%PropSetsB)) then - LB(1:2) = lbound(SrcInitTypeData%PropSetsB) - UB(1:2) = ubound(SrcInitTypeData%PropSetsB) - if (.not. allocated(DstInitTypeData%PropSetsB)) then - allocate(DstInitTypeData%PropSetsB(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (allocated(SrcInitTypeData%PropSetsBC)) then + LB(1:2) = lbound(SrcInitTypeData%PropSetsBC) + UB(1:2) = ubound(SrcInitTypeData%PropSetsBC) + if (.not. allocated(DstInitTypeData%PropSetsBC)) then + allocate(DstInitTypeData%PropSetsBC(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) if (ErrStat2 /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsB.', ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsBC.', ErrStat, ErrMsg, RoutineName) return end if end if - DstInitTypeData%PropSetsB = SrcInitTypeData%PropSetsB + DstInitTypeData%PropSetsBC = SrcInitTypeData%PropSetsBC + end if + if (allocated(SrcInitTypeData%PropSetsBR)) then + LB(1:2) = lbound(SrcInitTypeData%PropSetsBR) + UB(1:2) = ubound(SrcInitTypeData%PropSetsBR) + if (.not. allocated(DstInitTypeData%PropSetsBR)) then + allocate(DstInitTypeData%PropSetsBR(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropSetsBR.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitTypeData%PropSetsBR = SrcInitTypeData%PropSetsBR end if if (allocated(SrcInitTypeData%PropSetsC)) then LB(1:2) = lbound(SrcInitTypeData%PropSetsC) @@ -1357,6 +1389,18 @@ subroutine SD_CopyInitType(SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, end if DstInitTypeData%Members = SrcInitTypeData%Members end if + if (allocated(SrcInitTypeData%MemberSpin)) then + LB(1:1) = lbound(SrcInitTypeData%MemberSpin) + UB(1:1) = ubound(SrcInitTypeData%MemberSpin) + if (.not. allocated(DstInitTypeData%MemberSpin)) then + allocate(DstInitTypeData%MemberSpin(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%MemberSpin.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitTypeData%MemberSpin = SrcInitTypeData%MemberSpin + end if if (allocated(SrcInitTypeData%SSOutList)) then LB(1:1) = lbound(SrcInitTypeData%SSOutList) UB(1:1) = ubound(SrcInitTypeData%SSOutList) @@ -1444,7 +1488,9 @@ subroutine SD_CopyInitType(SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, DstInitTypeData%Soil_Nodes = SrcInitTypeData%Soil_Nodes end if DstInitTypeData%NElem = SrcInitTypeData%NElem - DstInitTypeData%NPropB = SrcInitTypeData%NPropB + DstInitTypeData%NPropBC = SrcInitTypeData%NPropBC + DstInitTypeData%NPropBR = SrcInitTypeData%NPropBR + DstInitTypeData%NPropX = SrcInitTypeData%NPropX DstInitTypeData%NPropC = SrcInitTypeData%NPropC DstInitTypeData%NPropR = SrcInitTypeData%NPropR DstInitTypeData%NPropS = SrcInitTypeData%NPropS @@ -1460,17 +1506,29 @@ subroutine SD_CopyInitType(SrcInitTypeData, DstInitTypeData, CtrlCode, ErrStat, end if DstInitTypeData%Nodes = SrcInitTypeData%Nodes end if - if (allocated(SrcInitTypeData%PropsB)) then - LB(1:2) = lbound(SrcInitTypeData%PropsB) - UB(1:2) = ubound(SrcInitTypeData%PropsB) - if (.not. allocated(DstInitTypeData%PropsB)) then - allocate(DstInitTypeData%PropsB(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (allocated(SrcInitTypeData%PropsBC)) then + LB(1:2) = lbound(SrcInitTypeData%PropsBC) + UB(1:2) = ubound(SrcInitTypeData%PropsBC) + if (.not. allocated(DstInitTypeData%PropsBC)) then + allocate(DstInitTypeData%PropsBC(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsBC.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitTypeData%PropsBC = SrcInitTypeData%PropsBC + end if + if (allocated(SrcInitTypeData%PropsBR)) then + LB(1:2) = lbound(SrcInitTypeData%PropsBR) + UB(1:2) = ubound(SrcInitTypeData%PropsBR) + if (.not. allocated(DstInitTypeData%PropsBR)) then + allocate(DstInitTypeData%PropsBR(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) if (ErrStat2 /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsB.', ErrStat, ErrMsg, RoutineName) + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitTypeData%PropsBR.', ErrStat, ErrMsg, RoutineName) return end if end if - DstInitTypeData%PropsB = SrcInitTypeData%PropsB + DstInitTypeData%PropsBR = SrcInitTypeData%PropsBR end if if (allocated(SrcInitTypeData%PropsC)) then LB(1:2) = lbound(SrcInitTypeData%PropsC) @@ -1593,8 +1651,11 @@ subroutine SD_DestroyInitType(InitTypeData, ErrStat, ErrMsg) if (allocated(InitTypeData%Joints)) then deallocate(InitTypeData%Joints) end if - if (allocated(InitTypeData%PropSetsB)) then - deallocate(InitTypeData%PropSetsB) + if (allocated(InitTypeData%PropSetsBC)) then + deallocate(InitTypeData%PropSetsBC) + end if + if (allocated(InitTypeData%PropSetsBR)) then + deallocate(InitTypeData%PropSetsBR) end if if (allocated(InitTypeData%PropSetsC)) then deallocate(InitTypeData%PropSetsC) @@ -1620,6 +1681,9 @@ subroutine SD_DestroyInitType(InitTypeData, ErrStat, ErrMsg) if (allocated(InitTypeData%Members)) then deallocate(InitTypeData%Members) end if + if (allocated(InitTypeData%MemberSpin)) then + deallocate(InitTypeData%MemberSpin) + end if if (allocated(InitTypeData%SSOutList)) then deallocate(InitTypeData%SSOutList) end if @@ -1644,8 +1708,11 @@ subroutine SD_DestroyInitType(InitTypeData, ErrStat, ErrMsg) if (allocated(InitTypeData%Nodes)) then deallocate(InitTypeData%Nodes) end if - if (allocated(InitTypeData%PropsB)) then - deallocate(InitTypeData%PropsB) + if (allocated(InitTypeData%PropsBC)) then + deallocate(InitTypeData%PropsBC) + end if + if (allocated(InitTypeData%PropsBR)) then + deallocate(InitTypeData%PropsBR) end if if (allocated(InitTypeData%PropsC)) then deallocate(InitTypeData%PropsC) @@ -1688,7 +1755,8 @@ subroutine SD_PackInitType(RF, Indata) call RegPack(RF, InData%DT) call RegPack(RF, InData%NJoints) call RegPack(RF, InData%NPropSetsX) - call RegPack(RF, InData%NPropSetsB) + call RegPack(RF, InData%NPropSetsBC) + call RegPack(RF, InData%NPropSetsBR) call RegPack(RF, InData%NPropSetsC) call RegPack(RF, InData%NPropSetsR) call RegPack(RF, InData%NPropSetsS) @@ -1698,7 +1766,8 @@ subroutine SD_PackInitType(RF, Indata) call RegPack(RF, InData%NDiv) call RegPack(RF, InData%CBMod) call RegPackAlloc(RF, InData%Joints) - call RegPackAlloc(RF, InData%PropSetsB) + call RegPackAlloc(RF, InData%PropSetsBC) + call RegPackAlloc(RF, InData%PropSetsBR) call RegPackAlloc(RF, InData%PropSetsC) call RegPackAlloc(RF, InData%PropSetsR) call RegPackAlloc(RF, InData%PropSetsS) @@ -1710,6 +1779,7 @@ subroutine SD_PackInitType(RF, Indata) call RegPack(RF, InData%RayleighDamp) call RegPack(RF, InData%GuyanDampMat) call RegPackAlloc(RF, InData%Members) + call RegPackAlloc(RF, InData%MemberSpin) call RegPackAlloc(RF, InData%SSOutList) call RegPack(RF, InData%OutCOSM) call RegPack(RF, InData%TabDelim) @@ -1720,12 +1790,15 @@ subroutine SD_PackInitType(RF, Indata) call RegPackAlloc(RF, InData%Soil_Points) call RegPackAlloc(RF, InData%Soil_Nodes) call RegPack(RF, InData%NElem) - call RegPack(RF, InData%NPropB) + call RegPack(RF, InData%NPropBC) + call RegPack(RF, InData%NPropBR) + call RegPack(RF, InData%NPropX) call RegPack(RF, InData%NPropC) call RegPack(RF, InData%NPropR) call RegPack(RF, InData%NPropS) call RegPackAlloc(RF, InData%Nodes) - call RegPackAlloc(RF, InData%PropsB) + call RegPackAlloc(RF, InData%PropsBC) + call RegPackAlloc(RF, InData%PropsBR) call RegPackAlloc(RF, InData%PropsC) call RegPackAlloc(RF, InData%PropsR) call RegPackAlloc(RF, InData%PropsS) @@ -1754,7 +1827,8 @@ subroutine SD_UnPackInitType(RF, OutData) call RegUnpack(RF, OutData%DT); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NJoints); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NPropSetsX); if (RegCheckErr(RF, RoutineName)) return - call RegUnpack(RF, OutData%NPropSetsB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%NPropSetsBC); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%NPropSetsBR); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NPropSetsC); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NPropSetsR); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NPropSetsS); if (RegCheckErr(RF, RoutineName)) return @@ -1764,7 +1838,8 @@ subroutine SD_UnPackInitType(RF, OutData) call RegUnpack(RF, OutData%NDiv); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%CBMod); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Joints); if (RegCheckErr(RF, RoutineName)) return - call RegUnpackAlloc(RF, OutData%PropSetsB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%PropSetsBC); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%PropSetsBR); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%PropSetsC); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%PropSetsR); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%PropSetsS); if (RegCheckErr(RF, RoutineName)) return @@ -1776,6 +1851,7 @@ subroutine SD_UnPackInitType(RF, OutData) call RegUnpack(RF, OutData%RayleighDamp); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%GuyanDampMat); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Members); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%MemberSpin); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%SSOutList); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%OutCOSM); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%TabDelim); if (RegCheckErr(RF, RoutineName)) return @@ -1786,12 +1862,15 @@ subroutine SD_UnPackInitType(RF, OutData) call RegUnpackAlloc(RF, OutData%Soil_Points); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Soil_Nodes); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NElem); if (RegCheckErr(RF, RoutineName)) return - call RegUnpack(RF, OutData%NPropB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%NPropBC); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%NPropBR); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%NPropX); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NPropC); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NPropR); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NPropS); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Nodes); if (RegCheckErr(RF, RoutineName)) return - call RegUnpackAlloc(RF, OutData%PropsB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%PropsBC); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%PropsBR); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%PropsC); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%PropsR); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%PropsS); if (RegCheckErr(RF, RoutineName)) return @@ -2564,6 +2643,18 @@ subroutine SD_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg) end if DstParamData%Elems = SrcParamData%Elems end if + if (allocated(SrcParamData%ElemSpin)) then + LB(1:1) = lbound(SrcParamData%ElemSpin) + UB(1:1) = ubound(SrcParamData%ElemSpin) + if (.not. allocated(DstParamData%ElemSpin)) then + allocate(DstParamData%ElemSpin(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%ElemSpin.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%ElemSpin = SrcParamData%ElemSpin + end if if (allocated(SrcParamData%ElemProps)) then LB(1:1) = lbound(SrcParamData%ElemProps) UB(1:1) = ubound(SrcParamData%ElemProps) @@ -3403,6 +3494,9 @@ subroutine SD_DestroyParam(ParamData, ErrStat, ErrMsg) if (allocated(ParamData%Elems)) then deallocate(ParamData%Elems) end if + if (allocated(ParamData%ElemSpin)) then + deallocate(ParamData%ElemSpin) + end if if (allocated(ParamData%ElemProps)) then LB(1:1) = lbound(ParamData%ElemProps) UB(1:1) = ubound(ParamData%ElemProps) @@ -3650,6 +3744,7 @@ subroutine SD_PackParam(RF, Indata) call RegPack(RF, InData%nDOF_red) call RegPack(RF, InData%Nmembers) call RegPackAlloc(RF, InData%Elems) + call RegPackAlloc(RF, InData%ElemSpin) call RegPack(RF, allocated(InData%ElemProps)) if (allocated(InData%ElemProps)) then call RegPackBounds(RF, 1, lbound(InData%ElemProps), ubound(InData%ElemProps)) @@ -3827,6 +3922,7 @@ subroutine SD_UnPackParam(RF, OutData) call RegUnpack(RF, OutData%nDOF_red); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%Nmembers); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Elems); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%ElemSpin); if (RegCheckErr(RF, RoutineName)) return if (allocated(OutData%ElemProps)) deallocate(OutData%ElemProps) call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return if (IsAllocAssoc) then diff --git a/openfast_io/openfast_io/FAST_reader.py b/openfast_io/openfast_io/FAST_reader.py index 8bd0d3438e..f401271a87 100644 --- a/openfast_io/openfast_io/FAST_reader.py +++ b/openfast_io/openfast_io/FAST_reader.py @@ -1979,144 +1979,313 @@ def read_HydroDyn(self, hd_file): self.fst_vt['HydroDyn']['JointAxID'][i] = int(ln[4]) self.fst_vt['HydroDyn']['JointOvrlp'][i] = int(ln[5]) - #MEMBER CROSS-SECTION PROPERTIES + #CIRCULAR MEMBER CROSS-SECTION PROPERTIES f.readline() - self.fst_vt['HydroDyn']['NPropSets'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['PropSetID'] = [None]*self.fst_vt['HydroDyn']['NPropSets'] - self.fst_vt['HydroDyn']['PropD'] = [None]*self.fst_vt['HydroDyn']['NPropSets'] - self.fst_vt['HydroDyn']['PropThck'] = [None]*self.fst_vt['HydroDyn']['NPropSets'] + self.fst_vt['HydroDyn']['NPropSetsCyl'] = int_read(f.readline().split()[0]) + self.fst_vt['HydroDyn']['CylPropSetID'] = [None]*self.fst_vt['HydroDyn']['NPropSetsCyl'] + self.fst_vt['HydroDyn']['CylPropD'] = [None]*self.fst_vt['HydroDyn']['NPropSetsCyl'] + self.fst_vt['HydroDyn']['CylPropThck'] = [None]*self.fst_vt['HydroDyn']['NPropSetsCyl'] ln = f.readline().split() ln = f.readline().split() - for i in range(self.fst_vt['HydroDyn']['NPropSets']): + for i in range(self.fst_vt['HydroDyn']['NPropSetsCyl']): ln = f.readline().split() - self.fst_vt['HydroDyn']['PropSetID'][i] = int(ln[0]) - self.fst_vt['HydroDyn']['PropD'][i] = float(ln[1]) - self.fst_vt['HydroDyn']['PropThck'][i] = float(ln[2]) + self.fst_vt['HydroDyn']['CylPropSetID'][i] = int(ln[0]) + self.fst_vt['HydroDyn']['CylPropD'][i] = float(ln[1]) + self.fst_vt['HydroDyn']['CylPropThck'][i] = float(ln[2]) - #SIMPLE HYDRODYNAMIC COEFFICIENTS + #RECTANGULAR MEMBER CROSS-SECTION PROPERTIES + f.readline() + self.fst_vt['HydroDyn']['NPropSetsRec'] = int_read(f.readline().split()[0]) + self.fst_vt['HydroDyn']['RecPropSetID'] = [None]*self.fst_vt['HydroDyn']['NPropSetsRec'] + self.fst_vt['HydroDyn']['RecPropA'] = [None]*self.fst_vt['HydroDyn']['NPropSetsRec'] + self.fst_vt['HydroDyn']['RecPropB'] = [None]*self.fst_vt['HydroDyn']['NPropSetsRec'] + self.fst_vt['HydroDyn']['RecPropThck'] = [None]*self.fst_vt['HydroDyn']['NPropSetsRec'] + ln = f.readline().split() + ln = f.readline().split() + for i in range(self.fst_vt['HydroDyn']['NPropSetsRec']): + ln = f.readline().split() + self.fst_vt['HydroDyn']['RecPropSetID'][i] = int(ln[0]) + self.fst_vt['HydroDyn']['RecPropA'][i] = float(ln[1]) + self.fst_vt['HydroDyn']['RecPropB'][i] = float(ln[2]) + self.fst_vt['HydroDyn']['RecPropThck'][i] = float(ln[3]) + + #SIMPLE CIRCULAR-MEMBER HYDRODYNAMIC COEFFICIENTS + f.readline() + f.readline() + f.readline() + ln = f.readline().split() + self.fst_vt['HydroDyn']['CylSimplCd'] = float_read(ln[0]) + self.fst_vt['HydroDyn']['CylSimplCdMG'] = float_read(ln[1]) + self.fst_vt['HydroDyn']['CylSimplCa'] = float_read(ln[2]) + self.fst_vt['HydroDyn']['CylSimplCaMG'] = float_read(ln[3]) + self.fst_vt['HydroDyn']['CylSimplCp'] = float_read(ln[4]) + self.fst_vt['HydroDyn']['CylSimplCpMG'] = float_read(ln[5]) + self.fst_vt['HydroDyn']['CylSimplAxCd'] = float_read(ln[6]) + self.fst_vt['HydroDyn']['CylSimplAxCdMG'] = float_read(ln[7]) + self.fst_vt['HydroDyn']['CylSimplAxCa'] = float_read(ln[8]) + self.fst_vt['HydroDyn']['CylSimplAxCaMG'] = float_read(ln[9]) + self.fst_vt['HydroDyn']['CylSimplAxCp'] = float_read(ln[10]) + self.fst_vt['HydroDyn']['CylSimplAxCpMG'] = float_read(ln[11]) + self.fst_vt['HydroDyn']['CylSimplCb'] = float_read(ln[12]) + self.fst_vt['HydroDyn']['CylSimplCbMG'] = float_read(ln[13]) + + #SIMPLE RECTANGULAR-MEMBER HYDRODYNAMIC COEFFICIENTS f.readline() f.readline() f.readline() ln = f.readline().split() - self.fst_vt['HydroDyn']['SimplCd'] = float_read(ln[0]) - self.fst_vt['HydroDyn']['SimplCdMG'] = float_read(ln[1]) - self.fst_vt['HydroDyn']['SimplCa'] = float_read(ln[2]) - self.fst_vt['HydroDyn']['SimplCaMG'] = float_read(ln[3]) - self.fst_vt['HydroDyn']['SimplCp'] = float_read(ln[4]) - self.fst_vt['HydroDyn']['SimplCpMG'] = float_read(ln[5]) - self.fst_vt['HydroDyn']['SimplAxCd'] = float_read(ln[6]) - self.fst_vt['HydroDyn']['SimplAxCdMG'] = float_read(ln[7]) - self.fst_vt['HydroDyn']['SimplAxCa'] = float_read(ln[8]) - self.fst_vt['HydroDyn']['SimplAxCaMG'] = float_read(ln[9]) - self.fst_vt['HydroDyn']['SimplAxCp'] = float_read(ln[10]) - self.fst_vt['HydroDyn']['SimplAxCpMG'] = float_read(ln[11]) - self.fst_vt['HydroDyn']['SimplCb'] = float_read(ln[12]) - self.fst_vt['HydroDyn']['SimplCbMG'] = float_read(ln[13]) - - #DEPTH-BASED HYDRODYNAMIC COEFFICIENTS - f.readline() - self.fst_vt['HydroDyn']['NCoefDpth'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['Dpth'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthCd'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthCdMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthCa'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthCaMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthCp'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthCpMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthAxCd'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthAxCdMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthAxCa'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthAxCaMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthAxCp'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthAxCpMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthCb'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] - self.fst_vt['HydroDyn']['DpthCbMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpth'] + self.fst_vt['HydroDyn']['RecSimplCdA'] = float_read(ln[0]) + self.fst_vt['HydroDyn']['RecSimplCdAMG'] = float_read(ln[1]) + self.fst_vt['HydroDyn']['RecSimplCdB'] = float_read(ln[2]) + self.fst_vt['HydroDyn']['RecSimplCdBMG'] = float_read(ln[3]) + self.fst_vt['HydroDyn']['RecSimplCaA'] = float_read(ln[4]) + self.fst_vt['HydroDyn']['RecSimplCaAMG'] = float_read(ln[5]) + self.fst_vt['HydroDyn']['RecSimplCaB'] = float_read(ln[6]) + self.fst_vt['HydroDyn']['RecSimplCaBMG'] = float_read(ln[7]) + self.fst_vt['HydroDyn']['RecSimplCp'] = float_read(ln[8]) + self.fst_vt['HydroDyn']['RecSimplCpMG'] = float_read(ln[9]) + self.fst_vt['HydroDyn']['RecSimplAxCd'] = float_read(ln[10]) + self.fst_vt['HydroDyn']['RecSimplAxCdMG'] = float_read(ln[11]) + self.fst_vt['HydroDyn']['RecSimplAxCa'] = float_read(ln[12]) + self.fst_vt['HydroDyn']['RecSimplAxCaMG'] = float_read(ln[13]) + self.fst_vt['HydroDyn']['RecSimplAxCp'] = float_read(ln[14]) + self.fst_vt['HydroDyn']['RecSimplAxCpMG'] = float_read(ln[15]) + self.fst_vt['HydroDyn']['RecSimplCb'] = float_read(ln[16]) + self.fst_vt['HydroDyn']['RecSimplCbMG'] = float_read(ln[17]) + + #DEPTH-BASED CIRCULAR-MEMBER HYDRODYNAMIC COEFFICIENTS + f.readline() + self.fst_vt['HydroDyn']['NCoefDpthCyl'] = int_read(f.readline().split()[0]) + self.fst_vt['HydroDyn']['CylDpth'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthCd'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthCdMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthCa'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthCaMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthCp'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthCpMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthAxCd'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthAxCdMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthAxCa'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthAxCaMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthAxCp'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthAxCpMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthCb'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] + self.fst_vt['HydroDyn']['CylDpthCbMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthCyl'] ln = f.readline().split() ln = f.readline().split() - for i in range(self.fst_vt['HydroDyn']['NCoefDpth']): + for i in range(self.fst_vt['HydroDyn']['NCoefDpthCyl']): + ln = f.readline().split() + self.fst_vt['HydroDyn']['CylDpth'][i] = float_read(ln[0]) + self.fst_vt['HydroDyn']['CylDpthCd'][i] = float_read(ln[1]) + self.fst_vt['HydroDyn']['CylDpthCdMG'][i] = float_read(ln[2]) + self.fst_vt['HydroDyn']['CylDpthCa'][i] = float_read(ln[3]) + self.fst_vt['HydroDyn']['CylDpthCaMG'][i] = float_read(ln[4]) + self.fst_vt['HydroDyn']['CylDpthCp'][i] = float_read(ln[5]) + self.fst_vt['HydroDyn']['CylDpthCpMG'][i] = float_read(ln[6]) + self.fst_vt['HydroDyn']['CylDpthAxCd'][i] = float_read(ln[7]) + self.fst_vt['HydroDyn']['CylDpthAxCdMG'][i] = float_read(ln[8]) + self.fst_vt['HydroDyn']['CylDpthAxCa'][i] = float_read(ln[9]) + self.fst_vt['HydroDyn']['CylDpthAxCaMG'][i] = float_read(ln[10]) + self.fst_vt['HydroDyn']['CylDpthAxCp'][i] = float_read(ln[11]) + self.fst_vt['HydroDyn']['CylDpthAxCpMG'][i] = float_read(ln[12]) + self.fst_vt['HydroDyn']['CylDpthCb'][i] = float_read(ln[13]) + self.fst_vt['HydroDyn']['CylDpthCbMG'][i] = float_read(ln[14]) + + #DEPTH-BASED RECTANGULAR-MEMBER HYDRODYNAMIC COEFFICIENTS + f.readline() + self.fst_vt['HydroDyn']['NCoefDpthRec'] = int_read(f.readline().split()[0]) + self.fst_vt['HydroDyn']['RecDpth'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCdA'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCdAMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCdB'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCdBMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCaA'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCaAMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCaB'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCaBMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCp'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCpMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthAxCd'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthAxCdMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthAxCa'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthAxCaMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthAxCp'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthAxCpMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCb'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + self.fst_vt['HydroDyn']['RecDpthCbMG'] = [None]*self.fst_vt['HydroDyn']['NCoefDpthRec'] + ln = f.readline().split() + ln = f.readline().split() + for i in range(self.fst_vt['HydroDyn']['NCoefDpthRec']): + ln = f.readline().split() + self.fst_vt['HydroDyn']['RecDpth'][i] = float_read(ln[0]) + self.fst_vt['HydroDyn']['RecDpthCdA'][i] = float_read(ln[1]) + self.fst_vt['HydroDyn']['RecDpthCdAMG'][i] = float_read(ln[2]) + self.fst_vt['HydroDyn']['RecDpthCdB'][i] = float_read(ln[3]) + self.fst_vt['HydroDyn']['RecDpthCdBMG'][i] = float_read(ln[4]) + self.fst_vt['HydroDyn']['RecDpthCaA'][i] = float_read(ln[5]) + self.fst_vt['HydroDyn']['RecDpthCaAMG'][i] = float_read(ln[6]) + self.fst_vt['HydroDyn']['RecDpthCaB'][i] = float_read(ln[7]) + self.fst_vt['HydroDyn']['RecDpthCaBMG'][i] = float_read(ln[8]) + self.fst_vt['HydroDyn']['RecDpthCp'][i] = float_read(ln[9]) + self.fst_vt['HydroDyn']['RecDpthCpMG'][i] = float_read(ln[10]) + self.fst_vt['HydroDyn']['RecDpthAxCd'][i] = float_read(ln[11]) + self.fst_vt['HydroDyn']['RecDpthAxCdMG'][i] = float_read(ln[12]) + self.fst_vt['HydroDyn']['RecDpthAxCa'][i] = float_read(ln[13]) + self.fst_vt['HydroDyn']['RecDpthAxCaMG'][i] = float_read(ln[14]) + self.fst_vt['HydroDyn']['RecDpthAxCp'][i] = float_read(ln[15]) + self.fst_vt['HydroDyn']['RecDpthAxCpMG'][i] = float_read(ln[16]) + self.fst_vt['HydroDyn']['RecDpthCb'][i] = float_read(ln[17]) + self.fst_vt['HydroDyn']['RecDpthCbMG'][i] = float_read(ln[18]) + + #MEMBER-BASED CIRCULAR-MEMBER HYDRODYNAMIC COEFFICIENTS + f.readline() + self.fst_vt['HydroDyn']['NCoefMembersCyl'] = int_read(f.readline().split()[0]) + self.fst_vt['HydroDyn']['MemberID_HydCCyl'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCd1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCd2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCdMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCdMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCa1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCa2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCaMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCaMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCp1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCp2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCpMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCpMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCd1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCd2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCdMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCdMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCa1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCa2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCaMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCaMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCp1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCp2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCpMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberAxCpMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCb1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCb2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCbMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + self.fst_vt['HydroDyn']['CylMemberCbMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersCyl'] + + f.readline() + f.readline() + for i in range(self.fst_vt['HydroDyn']['NCoefMembersCyl']): ln = f.readline().split() - self.fst_vt['HydroDyn']['Dpth'][i] = float_read(ln[0]) - self.fst_vt['HydroDyn']['DpthCd'][i] = float_read(ln[1]) - self.fst_vt['HydroDyn']['DpthCdMG'][i] = float_read(ln[2]) - self.fst_vt['HydroDyn']['DpthCa'][i] = float_read(ln[3]) - self.fst_vt['HydroDyn']['DpthCaMG'][i] = float_read(ln[4]) - self.fst_vt['HydroDyn']['DpthCp'][i] = float_read(ln[5]) - self.fst_vt['HydroDyn']['DpthCpMG'][i] = float_read(ln[6]) - self.fst_vt['HydroDyn']['DpthAxCd'][i] = float_read(ln[7]) - self.fst_vt['HydroDyn']['DpthAxCdMG'][i] = float_read(ln[8]) - self.fst_vt['HydroDyn']['DpthAxCa'][i] = float_read(ln[9]) - self.fst_vt['HydroDyn']['DpthAxCaMG'][i] = float_read(ln[10]) - self.fst_vt['HydroDyn']['DpthAxCp'][i] = float_read(ln[11]) - self.fst_vt['HydroDyn']['DpthAxCpMG'][i] = float_read(ln[12]) - self.fst_vt['HydroDyn']['DpthCb'][i] = float_read(ln[13]) - self.fst_vt['HydroDyn']['DpthCbMG'][i] = float_read(ln[14]) - - #MEMBER-BASED HYDRODYNAMIC COEFFICIENTS - f.readline() - self.fst_vt['HydroDyn']['NCoefMembers'] = int_read(f.readline().split()[0]) - self.fst_vt['HydroDyn']['MemberID_HydC'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCd1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCd2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCdMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCdMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCa1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCa2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCaMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCaMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCp1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCp2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCpMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCpMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCd1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCd2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCdMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCdMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCa1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCa2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCaMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCaMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCp1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCp2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCpMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberAxCpMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCb1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCb2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCbMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - self.fst_vt['HydroDyn']['MemberCbMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembers'] - - f.readline() - f.readline() - for i in range(self.fst_vt['HydroDyn']['NCoefMembers']): + self.fst_vt['HydroDyn']['MemberID_HydCCyl'][i] = int(ln[0]) + self.fst_vt['HydroDyn']['CylMemberCd1'][i] = float_read(ln[1]) + self.fst_vt['HydroDyn']['CylMemberCd2'][i] = float_read(ln[2]) + self.fst_vt['HydroDyn']['CylMemberCdMG1'][i] = float_read(ln[3]) + self.fst_vt['HydroDyn']['CylMemberCdMG2'][i] = float_read(ln[4]) + self.fst_vt['HydroDyn']['CylMemberCa1'][i] = float_read(ln[5]) + self.fst_vt['HydroDyn']['CylMemberCa2'][i] = float_read(ln[6]) + self.fst_vt['HydroDyn']['CylMemberCaMG1'][i] = float_read(ln[7]) + self.fst_vt['HydroDyn']['CylMemberCaMG2'][i] = float_read(ln[8]) + self.fst_vt['HydroDyn']['CylMemberCp1'][i] = float_read(ln[9]) + self.fst_vt['HydroDyn']['CylMemberCp2'][i] = float_read(ln[10]) + self.fst_vt['HydroDyn']['CylMemberCpMG1'][i] = float_read(ln[11]) + self.fst_vt['HydroDyn']['CylMemberCpMG2'][i] = float_read(ln[12]) + self.fst_vt['HydroDyn']['CylMemberAxCd1'][i] = float_read(ln[13]) + self.fst_vt['HydroDyn']['CylMemberAxCd2'][i] = float_read(ln[14]) + self.fst_vt['HydroDyn']['CylMemberAxCdMG1'][i] = float_read(ln[15]) + self.fst_vt['HydroDyn']['CylMemberAxCdMG2'][i] = float_read(ln[16]) + self.fst_vt['HydroDyn']['CylMemberAxCa1'][i] = float_read(ln[17]) + self.fst_vt['HydroDyn']['CylMemberAxCa2'][i] = float_read(ln[18]) + self.fst_vt['HydroDyn']['CylMemberAxCaMG1'][i] = float_read(ln[19]) + self.fst_vt['HydroDyn']['CylMemberAxCaMG2'][i] = float_read(ln[20]) + self.fst_vt['HydroDyn']['CylMemberAxCp1'][i] = float_read(ln[21]) + self.fst_vt['HydroDyn']['CylMemberAxCp2'][i] = float_read(ln[22]) + self.fst_vt['HydroDyn']['CylMemberAxCpMG1'][i] = float_read(ln[23]) + self.fst_vt['HydroDyn']['CylMemberAxCpMG2'][i] = float_read(ln[24]) + self.fst_vt['HydroDyn']['CylMemberCb1'][i] = float_read(ln[25]) + self.fst_vt['HydroDyn']['CylMemberCb2'][i] = float_read(ln[26]) + self.fst_vt['HydroDyn']['CylMemberCbMG1'][i] = float_read(ln[27]) + self.fst_vt['HydroDyn']['CylMemberCbMG2'][i] = float_read(ln[28]) + + #MEMBER-BASED RECTANGULAR-MEMBER HYDRODYNAMIC COEFFICIENTS + f.readline() + self.fst_vt['HydroDyn']['NCoefMembersRec'] = int_read(f.readline().split()[0]) + self.fst_vt['HydroDyn']['MemberID_HydCRec'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCdA1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCdA2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCdAMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCdAMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCdB1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCdB2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCdBMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCdBMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCaA1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCaA2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCaAMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCaAMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCaB1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCaB2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCaBMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCaBMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCp1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCp2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCpMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCpMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCd1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCd2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCdMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCdMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCa1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCa2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCaMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCaMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCp1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCp2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCpMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberAxCpMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCb1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCb2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCbMG1'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + self.fst_vt['HydroDyn']['RecMemberCbMG2'] = [None]*self.fst_vt['HydroDyn']['NCoefMembersRec'] + + f.readline() + f.readline() + for i in range(self.fst_vt['HydroDyn']['NCoefMembersRec']): ln = f.readline().split() - self.fst_vt['HydroDyn']['MemberID_HydC'][i] = int(ln[0]) - self.fst_vt['HydroDyn']['MemberCd1'][i] = float_read(ln[1]) - self.fst_vt['HydroDyn']['MemberCd2'][i] = float_read(ln[2]) - self.fst_vt['HydroDyn']['MemberCdMG1'][i] = float_read(ln[3]) - self.fst_vt['HydroDyn']['MemberCdMG2'][i] = float_read(ln[4]) - self.fst_vt['HydroDyn']['MemberCa1'][i] = float_read(ln[5]) - self.fst_vt['HydroDyn']['MemberCa2'][i] = float_read(ln[6]) - self.fst_vt['HydroDyn']['MemberCaMG1'][i] = float_read(ln[7]) - self.fst_vt['HydroDyn']['MemberCaMG2'][i] = float_read(ln[8]) - self.fst_vt['HydroDyn']['MemberCp1'][i] = float_read(ln[9]) - self.fst_vt['HydroDyn']['MemberCp2'][i] = float_read(ln[10]) - self.fst_vt['HydroDyn']['MemberCpMG1'][i] = float_read(ln[11]) - self.fst_vt['HydroDyn']['MemberCpMG2'][i] = float_read(ln[12]) - self.fst_vt['HydroDyn']['MemberAxCd1'][i] = float_read(ln[13]) - self.fst_vt['HydroDyn']['MemberAxCd2'][i] = float_read(ln[14]) - self.fst_vt['HydroDyn']['MemberAxCdMG1'][i] = float_read(ln[15]) - self.fst_vt['HydroDyn']['MemberAxCdMG2'][i] = float_read(ln[16]) - self.fst_vt['HydroDyn']['MemberAxCa1'][i] = float_read(ln[17]) - self.fst_vt['HydroDyn']['MemberAxCa2'][i] = float_read(ln[18]) - self.fst_vt['HydroDyn']['MemberAxCaMG1'][i] = float_read(ln[19]) - self.fst_vt['HydroDyn']['MemberAxCaMG2'][i] = float_read(ln[20]) - self.fst_vt['HydroDyn']['MemberAxCp1'][i] = float_read(ln[21]) - self.fst_vt['HydroDyn']['MemberAxCp2'][i] = float_read(ln[22]) - self.fst_vt['HydroDyn']['MemberAxCpMG1'][i] = float_read(ln[23]) - self.fst_vt['HydroDyn']['MemberAxCpMG2'][i] = float_read(ln[24]) - self.fst_vt['HydroDyn']['MemberCb1'][i] = float_read(ln[25]) - self.fst_vt['HydroDyn']['MemberCb2'][i] = float_read(ln[26]) - self.fst_vt['HydroDyn']['MemberCbMG1'][i] = float_read(ln[27]) - self.fst_vt['HydroDyn']['MemberCbMG2'][i] = float_read(ln[28]) + self.fst_vt['HydroDyn']['MemberID_HydCRec'][i] = int(ln[0]) + self.fst_vt['HydroDyn']['RecMemberCdA1'][i] = float_read(ln[1]) + self.fst_vt['HydroDyn']['RecMemberCdA2'][i] = float_read(ln[2]) + self.fst_vt['HydroDyn']['RecMemberCdAMG1'][i] = float_read(ln[3]) + self.fst_vt['HydroDyn']['RecMemberCdAMG2'][i] = float_read(ln[4]) + self.fst_vt['HydroDyn']['RecMemberCdB1'][i] = float_read(ln[5]) + self.fst_vt['HydroDyn']['RecMemberCdB2'][i] = float_read(ln[6]) + self.fst_vt['HydroDyn']['RecMemberCdBMG1'][i] = float_read(ln[7]) + self.fst_vt['HydroDyn']['RecMemberCdBMG2'][i] = float_read(ln[8]) + self.fst_vt['HydroDyn']['RecMemberCaA1'][i] = float_read(ln[9]) + self.fst_vt['HydroDyn']['RecMemberCaA2'][i] = float_read(ln[10]) + self.fst_vt['HydroDyn']['RecMemberCaAMG1'][i] = float_read(ln[11]) + self.fst_vt['HydroDyn']['RecMemberCaAMG2'][i] = float_read(ln[12]) + self.fst_vt['HydroDyn']['RecMemberCaB1'][i] = float_read(ln[13]) + self.fst_vt['HydroDyn']['RecMemberCaB2'][i] = float_read(ln[14]) + self.fst_vt['HydroDyn']['RecMemberCaBMG1'][i] = float_read(ln[15]) + self.fst_vt['HydroDyn']['RecMemberCaBMG2'][i] = float_read(ln[16]) + self.fst_vt['HydroDyn']['RecMemberCp1'][i] = float_read(ln[17]) + self.fst_vt['HydroDyn']['RecMemberCp2'][i] = float_read(ln[18]) + self.fst_vt['HydroDyn']['RecMemberCpMG1'][i] = float_read(ln[19]) + self.fst_vt['HydroDyn']['RecMemberCpMG2'][i] = float_read(ln[20]) + self.fst_vt['HydroDyn']['RecMemberAxCd1'][i] = float_read(ln[21]) + self.fst_vt['HydroDyn']['RecMemberAxCd2'][i] = float_read(ln[22]) + self.fst_vt['HydroDyn']['RecMemberAxCdMG1'][i] = float_read(ln[23]) + self.fst_vt['HydroDyn']['RecMemberAxCdMG2'][i] = float_read(ln[24]) + self.fst_vt['HydroDyn']['RecMemberAxCa1'][i] = float_read(ln[25]) + self.fst_vt['HydroDyn']['RecMemberAxCa2'][i] = float_read(ln[26]) + self.fst_vt['HydroDyn']['RecMemberAxCaMG1'][i] = float_read(ln[27]) + self.fst_vt['HydroDyn']['RecMemberAxCaMG2'][i] = float_read(ln[28]) + self.fst_vt['HydroDyn']['RecMemberAxCp1'][i] = float_read(ln[29]) + self.fst_vt['HydroDyn']['RecMemberAxCp2'][i] = float_read(ln[30]) + self.fst_vt['HydroDyn']['RecMemberAxCpMG1'][i] = float_read(ln[31]) + self.fst_vt['HydroDyn']['RecMemberAxCpMG2'][i] = float_read(ln[32]) + self.fst_vt['HydroDyn']['RecMemberCb1'][i] = float_read(ln[33]) + self.fst_vt['HydroDyn']['RecMemberCb2'][i] = float_read(ln[34]) + self.fst_vt['HydroDyn']['RecMemberCbMG1'][i] = float_read(ln[35]) + self.fst_vt['HydroDyn']['RecMemberCbMG2'][i] = float_read(ln[36]) #MEMBERS f.readline() @@ -2126,6 +2295,8 @@ def read_HydroDyn(self, hd_file): self.fst_vt['HydroDyn']['MJointID2'] = [None]*self.fst_vt['HydroDyn']['NMembers'] self.fst_vt['HydroDyn']['MPropSetID1'] = [None]*self.fst_vt['HydroDyn']['NMembers'] self.fst_vt['HydroDyn']['MPropSetID2'] = [None]*self.fst_vt['HydroDyn']['NMembers'] + self.fst_vt['HydroDyn']['MSecGeom'] = [None]*self.fst_vt['HydroDyn']['NMembers'] + self.fst_vt['HydroDyn']['MSpinOrient'] = [None]*self.fst_vt['HydroDyn']['NMembers'] self.fst_vt['HydroDyn']['MDivSize'] = [None]*self.fst_vt['HydroDyn']['NMembers'] self.fst_vt['HydroDyn']['MCoefMod'] = [None]*self.fst_vt['HydroDyn']['NMembers'] self.fst_vt['HydroDyn']['MHstLMod'] = [None]*self.fst_vt['HydroDyn']['NMembers'] @@ -2139,10 +2310,12 @@ def read_HydroDyn(self, hd_file): self.fst_vt['HydroDyn']['MJointID2'][i] = int(ln[2]) self.fst_vt['HydroDyn']['MPropSetID1'][i] = int(ln[3]) self.fst_vt['HydroDyn']['MPropSetID2'][i] = int(ln[4]) - self.fst_vt['HydroDyn']['MDivSize'][i] = float(ln[5]) - self.fst_vt['HydroDyn']['MCoefMod'][i] = int(ln[6]) - self.fst_vt['HydroDyn']['MHstLMod'][i] = int(ln[7]) - self.fst_vt['HydroDyn']['PropPot'][i] = bool_read(ln[8]) + self.fst_vt['HydroDyn']['MSecGeom'][i] = int(ln[5]) + self.fst_vt['HydroDyn']['MSpinOrient'][i] = float(ln[6]) + self.fst_vt['HydroDyn']['MDivSize'][i] = float(ln[7]) + self.fst_vt['HydroDyn']['MCoefMod'][i] = int(ln[8]) + self.fst_vt['HydroDyn']['MHstLMod'][i] = int(ln[9]) + self.fst_vt['HydroDyn']['PropPot'][i] = bool_read(ln[10]) #FILLED MEMBERS f.readline() @@ -2437,7 +2610,8 @@ def read_SubDyn(self, sd_file): self.fst_vt['SubDyn']['MPropSetID1'] = [None]*self.fst_vt['SubDyn']['NMembers'] self.fst_vt['SubDyn']['MPropSetID2'] = [None]*self.fst_vt['SubDyn']['NMembers'] self.fst_vt['SubDyn']['MType'] = [None]*self.fst_vt['SubDyn']['NMembers'] - self.fst_vt['SubDyn']['M_COSMID'] = [None]*self.fst_vt['SubDyn']['NMembers'] + self.fst_vt['SubDyn']['M_Spin'] = [None]*self.fst_vt['SubDyn']['NMembers'] + self.fst_vt['SubDyn']['M_COSMID'] = [None]*self.fst_vt['SubDyn']['NMembers'] ln = f.readline().split() ln = f.readline().split() for i in range(self.fst_vt['SubDyn']['NMembers']): @@ -2447,55 +2621,87 @@ def read_SubDyn(self, sd_file): self.fst_vt['SubDyn']['MJointID2'][i] = int(ln[2]) self.fst_vt['SubDyn']['MPropSetID1'][i] = int(ln[3]) self.fst_vt['SubDyn']['MPropSetID2'][i] = int(ln[4]) - self.fst_vt['SubDyn']['MType'][i] = int(ln[5]) - if len(ln) > 6: - self.fst_vt['SubDyn']['M_COSMID'][i] = int(ln[6]) - f.readline() - # MEMBER X-SECTION PROPERTY data 1/2 - self.fst_vt['SubDyn']['NPropSets'] = int_read(f.readline().split()[0]) - self.fst_vt['SubDyn']['PropSetID1'] = [None]*self.fst_vt['SubDyn']['NPropSets'] - self.fst_vt['SubDyn']['YoungE1'] = [None]*self.fst_vt['SubDyn']['NPropSets'] - self.fst_vt['SubDyn']['ShearG1'] = [None]*self.fst_vt['SubDyn']['NPropSets'] - self.fst_vt['SubDyn']['MatDens1'] = [None]*self.fst_vt['SubDyn']['NPropSets'] - self.fst_vt['SubDyn']['XsecD'] = [None]*self.fst_vt['SubDyn']['NPropSets'] - self.fst_vt['SubDyn']['XsecT'] = [None]*self.fst_vt['SubDyn']['NPropSets'] + if ln[5].lower() == '1c': + self.fst_vt['SubDyn']['MType'][i] = 1 + elif ln[5].lower() == '1r': + self.fst_vt['SubDyn']['MType'][i] = -1 + else: + self.fst_vt['SubDyn']['MType'][i] = int(ln[5]) + if self.fst_vt['SubDyn']['MType'][i] == 5: + self.fst_vt['SubDyn']['M_Spin'][i] = 0. + self.fst_vt['SubDyn']['M_COSMID'][i] = int(ln[6]) + else: + self.fst_vt['SubDyn']['M_Spin'][i] = float(ln[6]) + self.fst_vt['SubDyn']['M_COSMID'][i] = -1 + f.readline() + # MEMBER X-SECTION PROPERTY data 1/3 + self.fst_vt['SubDyn']['NBCPropSets'] = int_read(f.readline().split()[0]) + self.fst_vt['SubDyn']['PropSetID1'] = [None]*self.fst_vt['SubDyn']['NBCPropSets'] + self.fst_vt['SubDyn']['YoungE1'] = [None]*self.fst_vt['SubDyn']['NBCPropSets'] + self.fst_vt['SubDyn']['ShearG1'] = [None]*self.fst_vt['SubDyn']['NBCPropSets'] + self.fst_vt['SubDyn']['MatDens1'] = [None]*self.fst_vt['SubDyn']['NBCPropSets'] + self.fst_vt['SubDyn']['XsecD'] = [None]*self.fst_vt['SubDyn']['NBCPropSets'] + self.fst_vt['SubDyn']['XsecT'] = [None]*self.fst_vt['SubDyn']['NBCPropSets'] ln = f.readline().split() ln = f.readline().split() - for i in range(self.fst_vt['SubDyn']['NPropSets']): + for i in range(self.fst_vt['SubDyn']['NBCPropSets']): ln = f.readline().split() self.fst_vt['SubDyn']['PropSetID1'][i] = int(ln[0]) self.fst_vt['SubDyn']['YoungE1'][i] = float(ln[1]) self.fst_vt['SubDyn']['ShearG1'][i] = float(ln[2]) self.fst_vt['SubDyn']['MatDens1'][i] = float(ln[3]) - self.fst_vt['SubDyn']['XsecD'][i] = float(ln[4]) - self.fst_vt['SubDyn']['XsecT'][i] = float(ln[5]) + self.fst_vt['SubDyn']['XsecD'][i] = float(ln[4]) + self.fst_vt['SubDyn']['XsecT'][i] = float(ln[5]) + f.readline() + # MEMBER X-SECTION PROPERTY data 2/3 + self.fst_vt['SubDyn']['NBRPropSets'] = int_read(f.readline().split()[0]) + self.fst_vt['SubDyn']['PropSetID2'] = [None]*self.fst_vt['SubDyn']['NBRPropSets'] + self.fst_vt['SubDyn']['YoungE2'] = [None]*self.fst_vt['SubDyn']['NBRPropSets'] + self.fst_vt['SubDyn']['ShearG2'] = [None]*self.fst_vt['SubDyn']['NBRPropSets'] + self.fst_vt['SubDyn']['MatDens2'] = [None]*self.fst_vt['SubDyn']['NBRPropSets'] + self.fst_vt['SubDyn']['XsecSa'] = [None]*self.fst_vt['SubDyn']['NBRPropSets'] + self.fst_vt['SubDyn']['XsecSb'] = [None]*self.fst_vt['SubDyn']['NBRPropSets'] + self.fst_vt['SubDyn']['XsecT2'] = [None]*self.fst_vt['SubDyn']['NBRPropSets'] + ln = f.readline().split() + ln = f.readline().split() + for i in range(self.fst_vt['SubDyn']['NBRPropSets']): + ln = f.readline().split() + self.fst_vt['SubDyn']['PropSetID2'][i] = int(ln[0]) + self.fst_vt['SubDyn']['YoungE2'][i] = float(ln[1]) + self.fst_vt['SubDyn']['ShearG2'][i] = float(ln[2]) + self.fst_vt['SubDyn']['MatDens2'][i] = float(ln[3]) + self.fst_vt['SubDyn']['XsecSa'][i] = float(ln[4]) + self.fst_vt['SubDyn']['XsecSb'][i] = float(ln[5]) + self.fst_vt['SubDyn']['XsecT2'][i] = float(ln[6]) f.readline() - # MEMBER X-SECTION PROPERTY data 2/2 + # MEMBER X-SECTION PROPERTY data 3/3 self.fst_vt['SubDyn']['NXPropSets'] = int_read(f.readline().split()[0]) - self.fst_vt['SubDyn']['PropSetID2'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] - self.fst_vt['SubDyn']['YoungE2'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] - self.fst_vt['SubDyn']['ShearG2'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] - self.fst_vt['SubDyn']['MatDens2'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] + self.fst_vt['SubDyn']['PropSetID3'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] + self.fst_vt['SubDyn']['YoungE3'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] + self.fst_vt['SubDyn']['ShearG3'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] + self.fst_vt['SubDyn']['MatDens3'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] self.fst_vt['SubDyn']['XsecA'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] self.fst_vt['SubDyn']['XsecAsx'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] self.fst_vt['SubDyn']['XsecAsy'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] self.fst_vt['SubDyn']['XsecJxx'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] self.fst_vt['SubDyn']['XsecJyy'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] self.fst_vt['SubDyn']['XsecJ0'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] + self.fst_vt['SubDyn']['XsecJt'] = [None]*self.fst_vt['SubDyn']['NXPropSets'] ln = f.readline().split() ln = f.readline().split() for i in range(self.fst_vt['SubDyn']['NXPropSets']): ln = f.readline().split() - self.fst_vt['SubDyn']['PropSetID2'][i] = int(ln[0]) - self.fst_vt['SubDyn']['YoungE2'][i] = float(ln[1]) - self.fst_vt['SubDyn']['ShearG2'][i] = float(ln[2]) - self.fst_vt['SubDyn']['MatDens2'][i] = float(ln[3]) + self.fst_vt['SubDyn']['PropSetID3'][i] = int(ln[0]) + self.fst_vt['SubDyn']['YoungE3'][i] = float(ln[1]) + self.fst_vt['SubDyn']['ShearG3'][i] = float(ln[2]) + self.fst_vt['SubDyn']['MatDens3'][i] = float(ln[3]) self.fst_vt['SubDyn']['XsecA'][i] = float(ln[4]) self.fst_vt['SubDyn']['XsecAsx'][i] = float(ln[5]) self.fst_vt['SubDyn']['XsecAsy'][i] = float(ln[6]) self.fst_vt['SubDyn']['XsecJxx'][i] = float(ln[7]) self.fst_vt['SubDyn']['XsecJyy'][i] = float(ln[8]) self.fst_vt['SubDyn']['XsecJ0'][i] = float(ln[9]) + self.fst_vt['SubDyn']['XsecJt'][i] = float(ln[10]) # CABLE PROPERTIES f.readline() self.fst_vt['SubDyn']['NCablePropSets'] = int_read(f.readline().split()[0]) diff --git a/openfast_io/openfast_io/FAST_writer.py b/openfast_io/openfast_io/FAST_writer.py index d142ff9361..f5ef8c0c48 100644 --- a/openfast_io/openfast_io/FAST_writer.py +++ b/openfast_io/openfast_io/FAST_writer.py @@ -1676,98 +1676,203 @@ def write_HydroDyn(self): ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['JointAxID'][i])) ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['JointOvrlp'][i])) f.write(" ".join(ln) + '\n') - f.write('---------------------- MEMBER CROSS-SECTION PROPERTIES -------------------------\n') - f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NPropSets'], 'NPropSets', '- Number of member property sets (-)\n')) + f.write('---------------------- CYLINDRICAL MEMBER CROSS-SECTION PROPERTIES -------------------------\n') + f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NPropSetsCyl'], 'NPropSetsCyl', '- Number of cylindrical member property sets (-)\n')) f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'PropD', 'PropThck']])+'\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(m)', '(m)']])+'\n') - for i in range(self.fst_vt['HydroDyn']['NPropSets']): + for i in range(self.fst_vt['HydroDyn']['NPropSetsCyl']): ln = [] - ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['PropSetID'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['PropD'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['PropThck'][i])) + ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['CylPropSetID'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylPropD'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylPropThck'][i])) f.write(" ".join(ln) + '\n') - f.write('---------------------- SIMPLE HYDRODYNAMIC COEFFICIENTS (model 1) --------------\n') + f.write('---------------------- RECTANGULAR MEMBER CROSS-SECTION PROPERTIES -------------------------\n') + f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NPropSetsRec'], 'NPropSetsRec', '- Number of rectangular member property sets (-)\n')) + f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'PropA', 'PropB', 'PropThck']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(m)', '(m)', '(m)']])+'\n') + for i in range(self.fst_vt['HydroDyn']['NPropSetsRec']): + ln = [] + ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['RecPropSetID'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecPropA'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecPropB'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecPropThck'][i])) + f.write(" ".join(ln) + '\n') + f.write('---------------------- SIMPLE CYLINDRICAL-MEMBER HYDRODYNAMIC COEFFICIENTS (model 1) --------------\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['SimplCd', 'SimplCdMG', 'SimplCa', 'SimplCaMG', 'SimplCp', 'SimplCpMG', 'SimplAxCd', 'SimplAxCdMG', 'SimplAxCa', 'SimplAxCaMG', 'SimplAxCp', 'SimplAxCpMG', 'SimplCb', 'SimplCbMG']])+'\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*14])+'\n') ln = [] - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCd'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCdMG'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCa'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCaMG'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCp'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCpMG'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCd'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCdMG'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCa'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCaMG'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCp'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplAxCpMG'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCb'])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['SimplCbMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplCd'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplCdMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplCa'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplCaMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplCp'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplCpMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplAxCd'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplAxCdMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplAxCa'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplAxCaMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplAxCp'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplAxCpMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplCb'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylSimplCbMG'])) f.write(" ".join(ln) + '\n') - f.write('---------------------- DEPTH-BASED HYDRODYNAMIC COEFFICIENTS (model 2) ---------\n') - f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefDpth'], 'NCoefDpth', '- Number of depth-dependent coefficients (-)\n')) + f.write('---------------------- SIMPLE RECTANGULAR-MEMBER HYDRODYNAMIC COEFFICIENTS (model 1) --------------\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['SimplCdA', 'SimplCdAMG', 'SimplCdB', 'SimplCdBMG', 'SimplCaA', 'SimplCaAMG', 'SimplCaB', 'SimplCaBMG', 'SimplCp', 'SimplCpMG', 'SimplAxCd', 'SimplAxCdMG', 'SimplAxCa', 'SimplAxCaMG', 'SimplAxCp', 'SimplAxCpMG', 'SimplCb', 'SimplCbMG']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*18])+'\n') + ln = [] + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCdA'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCdAMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCdB'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCdBMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCaA'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCaAMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCaB'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCaBMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCp'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCpMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplAxCd'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplAxCdMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplAxCa'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplAxCaMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplAxCp'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplAxCpMG'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCb'])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecSimplCbMG'])) + f.write(" ".join(ln) + '\n') + f.write('---------------------- DEPTH-BASED CYLINDRICAL-MEMBER HYDRODYNAMIC COEFFICIENTS (model 2) ---------\n') + f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefDpthCyl'], 'NCoefDpthCyl', '- Number of depth-dependent cylindrical-member coefficients (-)\n')) f.write(" ".join(['{:^11s}'.format(i) for i in ['Dpth', 'DpthCd', 'DpthCdMG', 'DpthCa', 'DpthCaMG', 'DpthCp', 'DpthCpMG', 'DpthAxCd', 'DpthAxCdMG', 'DpthAxCa', 'DpthAxCaMG', 'DpthAxCp', 'DpthAxCpMG', 'DpthCb', 'DpthCbMG']])+'\n') - f.write(" ".join(['{:^11s}'.format(i) for i in ['(m)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)']])+'\n') - for i in range(self.fst_vt['HydroDyn']['NCoefDpth']): + f.write(" ".join(['{:^11s}'.format(i) for i in ['(m)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)']])+'\n') + for i in range(self.fst_vt['HydroDyn']['NCoefDpthCyl']): + ln = [] + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpth'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthCd'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthCdMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthCa'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthCaMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthCp'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthCpMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthAxCd'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthAxCdMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthAxCa'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthAxCaMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthAxCp'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthAxCpMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthCb'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylDpthCbMG'][i])) + f.write(" ".join(ln) + '\n') + f.write('---------------------- DEPTH-BASED RECTANGULAR-MEMBER HYDRODYNAMIC COEFFICIENTS (model 2) ---------\n') + f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefDpthRec'], 'NCoefDpthRec', '- Number of depth-dependent rectangular-member coefficients (-)\n')) + f.write(" ".join(['{:^11s}'.format(i) for i in ['Dpth', 'DpthCdA', 'DpthCdAMG', 'DpthCdB', 'DpthCdBMG', 'DpthCaA', 'DpthCaAMG', 'DpthCaB', 'DpthCaBMG', 'DpthCp', 'DpthCpMG', 'DpthAxCd', 'DpthAxCdMG', 'DpthAxCa', 'DpthAxCaMG', 'DpthAxCp', 'DpthAxCpMG', 'DpthCb', 'DpthCbMG']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(m)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)']])+'\n') + for i in range(self.fst_vt['HydroDyn']['NCoefDpthRec']): + ln = [] + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpth'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCdA'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCdAMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCdB'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCdBMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCaA'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCaAMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCaB'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCaBMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCp'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCpMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthAxCd'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthAxCdMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthAxCa'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthAxCaMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthAxCp'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthAxCpMG'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCb'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecDpthCbMG'][i])) + f.write(" ".join(ln) + '\n') + f.write('---------------------- MEMBER-BASED CYLINDRICAL-MEMBER HYDRODYNAMIC COEFFICIENTS (model 3) --------\n') + f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefMembersCyl'], 'NCoefMembersCyl', '- Number of member-based cylindrical-member coefficients (-)\n')) + mem_coeff_names = ['MemberID', 'MemberCd1', 'MemberCd2', 'MemberCdMG1', 'MemberCdMG2', 'MemberCa1', 'MemberCa2', 'MemberCaMG1', 'MemberCaMG2', 'MemberCp1', 'MemberCp2', 'MemberCpMG1', 'MemberCpMG2', 'MemberAxCd1', 'MemberAxCd2', 'MemberAxCdMG1', 'MemberAxCdMG2', 'MemberAxCa1', 'MemberAxCa2', 'MemberAxCaMG1', 'MemberAxCaMG2', 'MemberAxCp1', 'MemberAxCp2', 'MemberAxCpMG1', 'MemberAxCpMG2','MemberCb1','MemberCb2','MemberCbMG1','MemberCbMG2'] + f.write(" ".join(['{:^11s}'.format(i) for i in mem_coeff_names])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*len(mem_coeff_names)])+'\n') + for i in range(self.fst_vt['HydroDyn']['NCoefMembersCyl']): ln = [] - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['Dpth'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCd'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCdMG'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCa'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCaMG'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCp'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCpMG'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCd'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCdMG'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCa'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCaMG'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCp'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthAxCpMG'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCb'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['DpthCbMG'][i])) + ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MemberID_HydCCyl'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCd1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCd2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCdMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCdMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCa1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCa2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCaMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCaMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCp1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCp2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCpMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCpMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCd1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCd2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCdMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCdMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCa1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCa2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCaMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCaMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCp1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCp2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCpMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberAxCpMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCb1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCb2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCbMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['CylMemberCbMG2'][i])) f.write(" ".join(ln) + '\n') - f.write('---------------------- MEMBER-BASED HYDRODYNAMIC COEFFICIENTS (model 3) --------\n') - f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefMembers'], 'NCoefMembers', '- Number of member-based coefficients (-)\n')) - mem_coeff_names = ['MemberID_HydC', 'MemberCd1', 'MemberCd2', 'MemberCdMG1', 'MemberCdMG2', 'MemberCa1', 'MemberCa2', 'MemberCaMG1', 'MemberCaMG2', 'MemberCp1', 'MemberCp2', 'MemberCpMG1', 'MemberCpMG2', 'MemberAxCd1', 'MemberAxCd2', 'MemberAxCdMG1', 'MemberAxCdMG2', 'MemberAxCa1', 'MemberAxCa2', 'MemberAxCaMG1', 'MemberAxCaMG2', 'MemberAxCp1', 'MemberAxCp2', 'MemberAxCpMG1', 'MemberAxCpMG2','MemberCb1','MemberCb2','MemberCbMG1','MemberCbMG2'] + f.write('---------------------- MEMBER-BASED RECTANGULAR-MEMBER HYDRODYNAMIC COEFFICIENTS (model 3) --------\n') + f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NCoefMembersRec'], 'NCoefMembersRec', '- Number of member-based rectangular-member coefficients (-)\n')) + mem_coeff_names = ['MemberID', 'MemberCdA1', 'MemberCdA2', 'MemberCdAMG1', 'MemberCdAMG2', 'MemberCdB1', 'MemberCdB2', 'MemberCdBMG1', 'MemberCdBMG2', 'MemberCaA1', 'MemberCaA2', 'MemberCaAMG1', 'MemberCaAMG2', 'MemberCaB1', 'MemberCaB2', 'MemberCaBMG1', 'MemberCaBMG2', 'MemberCp1', 'MemberCp2', 'MemberCpMG1', 'MemberCpMG2', 'MemberAxCd1', 'MemberAxCd2', 'MemberAxCdMG1', 'MemberAxCdMG2', 'MemberAxCa1', 'MemberAxCa2', 'MemberAxCaMG1', 'MemberAxCaMG2', 'MemberAxCp1', 'MemberAxCp2', 'MemberAxCpMG1', 'MemberAxCpMG2','MemberCb1','MemberCb2','MemberCbMG1','MemberCbMG2'] f.write(" ".join(['{:^11s}'.format(i) for i in mem_coeff_names])+'\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)']*len(mem_coeff_names)])+'\n') - for i in range(self.fst_vt['HydroDyn']['NCoefMembers']): + for i in range(self.fst_vt['HydroDyn']['NCoefMembersRec']): ln = [] - ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MemberID_HydC'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCd1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCd2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCdMG1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCdMG2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCa1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCa2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCaMG1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCaMG2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCp1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCp2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCpMG1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCpMG2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCd1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCd2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCdMG1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCdMG2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCa1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCa2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCaMG1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCaMG2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCp1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCp2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCpMG1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberAxCpMG2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCb1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCb2'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCbMG1'][i])) - ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MemberCbMG2'][i])) + ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MemberID_HydCRec'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCdA1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCdA2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCdAMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCdAMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCdB1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCdB2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCdBMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCdBMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCaA1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCaA2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCaAMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCaAMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCaB1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCaB2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCaBMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCaBMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCp1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCp2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCpMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCpMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCd1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCd2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCdMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCdMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCa1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCa2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCaMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCaMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCp1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCp2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCpMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberAxCpMG2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCb1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCb2'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCbMG1'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['RecMemberCbMG2'][i])) f.write(" ".join(ln) + '\n') f.write('-------------------- MEMBERS -------------------------------------------------\n') f.write('{:<11d} {:<11} {:}'.format(self.fst_vt['HydroDyn']['NMembers'], 'NMembers', '- Number of members (-)\n')) - f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID', 'MJointID1', 'MJointID2', 'MPropSetID1', 'MPropSetID2', 'MDivSize', 'MCoefMod', 'MHstLMod', 'PropPot']])+' ! [MCoefMod=1: use simple coeff table, 2: use depth-based coeff table, 3: use member-based coeff table] [ PropPot/=0 if member is modeled with potential-flow theory]\n') - f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(-)', '(-)', '(-)', '(-)', '(m)', '(switch)', '(switch)', '(flag)']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID', 'MJointID1', 'MJointID2', 'MPropSetID1', 'MPropSetID2', 'MSecGeom', 'MSpinOrient', 'MDivSize', 'MCoefMod', 'MHstLMod', 'PropPot']])+' ! [MCoefMod=1: use simple coeff table, 2: use depth-based coeff table, 3: use member-based coeff table] [ PropPot/=0 if member is modeled with potential-flow theory]\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)', '(-)', '(-)', '(-)', '(-)', '(switch)', '(deg)', '(m)', '(switch)', '(switch)', '(flag)']])+'\n') for i in range(self.fst_vt['HydroDyn']['NMembers']): ln = [] ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MemberID'][i])) @@ -1775,6 +1880,8 @@ def write_HydroDyn(self): ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MJointID2'][i])) ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MPropSetID1'][i])) ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MPropSetID2'][i])) + ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MSecGeom'][i])) + ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MSpinOrient'][i])) ln.append('{:^11}'.format(self.fst_vt['HydroDyn']['MDivSize'][i])) ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MCoefMod'][i])) ln.append('{:^11d}'.format(self.fst_vt['HydroDyn']['MHstLMod'][i])) @@ -2023,8 +2130,8 @@ def write_SubDyn(self): f.write(" ".join(ln) + '\n') f.write('----------------------------------- MEMBERS --------------------------------------\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NMembers'], 'NMembers', '- Number of frame members\n')) - f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID', 'MJointID1', 'MJointID2', 'MPropSetID1', 'MPropSetID2', 'MType', 'COSMID']])+' ![MType={1:beam circ., 2:cable, 3:rigid, 4:beam arb.}. COMSID={-1:none}]\n') - f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(-)','(-)','(-)','(-)','(-)','(-)']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['MemberID', 'MJointID1', 'MJointID2', 'MPropSetID1', 'MPropSetID2', 'MType', 'MSpin/COSMID']])+' ![MType={1c:beam circ., 1r: beam rect., 2:cable, 3:rigid, 4:beam arb., 5:spring}. COMSID={-1:none}]\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(-)','(-)','(-)','(-)','(-)','(deg/-)']])+'\n') for i in range(self.fst_vt['SubDyn']['NMembers']): ln = [] ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MemberID'][i])) @@ -2032,16 +2139,25 @@ def write_SubDyn(self): ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MJointID2'][i])) ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MPropSetID1'][i])) ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MPropSetID2'][i])) - ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MType'][i])) + if self.fst_vt['SubDyn']['MType'][i] == -1: + ln.append('{:^11s}'.format('1r')) + elif self.fst_vt['SubDyn']['MType'][i] == 1: + ln.append('{:^11s}'.format('1c')) + else: + ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['MType'][i])) # Need to change M_COSMID None elements to -1 self.fst_vt['SubDyn']['M_COSMID'][i] = -1 if self.fst_vt['SubDyn']['M_COSMID'][i] is None else self.fst_vt['SubDyn']['M_COSMID'][i] - ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['M_COSMID'][i])) + + if self.fst_vt['SubDyn']['MType'][i] == 5: + ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['M_COSMID'][i])) + else: + ln.append('{:^11}'.format(self.fst_vt['SubDyn']['M_Spin'][i])) f.write(" ".join(ln) + '\n') f.write('------------------ CIRCULAR BEAM CROSS-SECTION PROPERTIES -----------------------------\n') - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NPropSets'], 'NPropSets', '- Number of structurally unique cross-sections\n')) - f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'YoungE', 'ShearG1', 'MatDens', 'XsecD', 'XsecT']])+'\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NBCPropSets'], 'NPropSets', '- Number of structurally unique circular cross-sections\n')) + f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'YoungE', 'ShearG', 'MatDens', 'XsecD', 'XsecT']])+'\n') f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(N/m2)','(N/m2)','(kg/m3)','(m)','(m)']])+'\n') - for i in range(self.fst_vt['SubDyn']['NPropSets']): + for i in range(self.fst_vt['SubDyn']['NBCPropSets']): ln = [] ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['PropSetID1'][i])) ln.append('{:^11e}'.format(self.fst_vt['SubDyn']['YoungE1'][i])) @@ -2050,22 +2166,37 @@ def write_SubDyn(self): ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecD'][i])) ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecT'][i])) f.write(" ".join(ln) + '\n') - f.write('----------------- ARBITRARY BEAM CROSS-SECTION PROPERTIES -----------------------------\n') - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NXPropSets'], 'NXPropSets', '- Number of structurally unique non-circular cross-sections (if 0 the following table is ignored)\n')) - f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'YoungE', 'ShearG2', 'MatDens', 'XsecA', 'XsecAsx', 'XsecAsy', 'XsecJxx', 'XsecJyy', 'XsecJ0']])+'\n') - f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(N/m2)','(N/m2)','(kg/m3)','(m2)','(m2)','(m2)','(m4)','(m4)','(m4)']])+'\n') - for i in range(self.fst_vt['SubDyn']['NXPropSets']): + f.write('------------------ RECTANGULAR BEAM CROSS-SECTION PROPERTIES -----------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NBRPropSets'], 'NPropSets', '- Number of structurally unique rectangular cross-sections\n')) + f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'YoungE', 'ShearG', 'MatDens', 'XsecSa', 'XsecSb', 'XsecT']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(N/m2)','(N/m2)','(kg/m3)','(m)','(m)','(m)']])+'\n') + for i in range(self.fst_vt['SubDyn']['NBRPropSets']): ln = [] ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['PropSetID2'][i])) - ln.append('{:^11}'.format(self.fst_vt['SubDyn']['YoungE2'][i])) - ln.append('{:^11}'.format(self.fst_vt['SubDyn']['ShearG2'][i])) + ln.append('{:^11e}'.format(self.fst_vt['SubDyn']['YoungE2'][i])) + ln.append('{:^11e}'.format(self.fst_vt['SubDyn']['ShearG2'][i])) ln.append('{:^11}'.format(self.fst_vt['SubDyn']['MatDens2'][i])) + ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecSa'][i])) + ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecSb'][i])) + ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecT2'][i])) + f.write(" ".join(ln) + '\n') + f.write('----------------- ARBITRARY BEAM CROSS-SECTION PROPERTIES -----------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NXPropSets'], 'NXPropSets', '- Number of structurally unique arbitrary cross-sections (if 0 the following table is ignored)\n')) + f.write(" ".join(['{:^11s}'.format(i) for i in ['PropSetID', 'YoungE', 'ShearG', 'MatDens', 'XsecA', 'XsecAsx', 'XsecAsy', 'XsecJxx', 'XsecJyy', 'XsecJ0', 'XsecJt']])+'\n') + f.write(" ".join(['{:^11s}'.format(i) for i in ['(-)','(N/m2)','(N/m2)','(kg/m3)','(m2)','(m2)','(m2)','(m4)','(m4)','(m4)','(m4)']])+'\n') + for i in range(self.fst_vt['SubDyn']['NXPropSets']): + ln = [] + ln.append('{:^11d}'.format(self.fst_vt['SubDyn']['PropSetID3'][i])) + ln.append('{:^11e}'.format(self.fst_vt['SubDyn']['YoungE3'][i])) + ln.append('{:^11e}'.format(self.fst_vt['SubDyn']['ShearG3'][i])) + ln.append('{:^11}'.format(self.fst_vt['SubDyn']['MatDens3'][i])) ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecA'][i])) ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecAsx'][i])) ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecAsy'][i])) ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecJxx'][i])) ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecJyy'][i])) ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecJ0'][i])) + ln.append('{:^11}'.format(self.fst_vt['SubDyn']['XsecJt'][i])) f.write(" ".join(ln) + '\n') f.write('-------------------------- CABLE PROPERTIES -------------------------------------\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['SubDyn']['NCablePropSets'], 'NCablePropSets', '- Number of cable cable properties\n')) diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake index bdcaa6e0b4..b5ca00e1fe 100644 --- a/reg_tests/CTestList.cmake +++ b/reg_tests/CTestList.cmake @@ -456,6 +456,7 @@ hd_regression("hd_WaveStMod3" "hydrodyn;offshore") hd_regression("hd_MHstLMod2" "hydrodyn;offshore") hd_regression("hd_MHstLMod1_compare" "hydrodyn;offshore") hd_regression("hd_MHstLMod2_compare" "hydrodyn;offshore") +hd_regression("hd_MHstLMod2_RectMmbr" "hydrodyn;offshore") hd_regression("hd_MCF_WaveStMod0" "hydrodyn;offshore") hd_regression("hd_MCF_WaveStMod1" "hydrodyn;offshore") hd_regression("hd_MCF_WaveStMod2" "hydrodyn;offshore") @@ -483,6 +484,7 @@ sd_regression("SD_Spring_Case3" "subdyn;offshore") sd_regression("SD_Revolute_Joint" "subdyn;offshore") sd_regression("SD_2Beam_Spring" "subdyn;offshore") sd_regression("SD_2Beam_Cantilever" "subdyn;offshore") +sd_regression("SD_CantileverBeam_Rectangular" "subdyn;offshore") # TODO test below are bugs, should be added when fixed # sd_regression("SD_Force" "subdyn;offshore") # sd_regression("SD_AnsysComp4_UniversalCableRigid" "subdyn;offshore") diff --git a/reg_tests/r-test b/reg_tests/r-test index 54a2998d96..fa4c58a3bd 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 54a2998d96908461eeb554f756bfc9da69055804 +Subproject commit fa4c58a3bd697afc0c62a1adce4c754a77d0df7a