diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index 2a03635b84..3b603da049 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -293,6 +293,7 @@ SUBROUTINE Init_Lin(p_FAST, y_FAST, m_FAST, AD, ED, NumBl, NumBlNodes, ErrStat, m_FAST%Lin%n_rot = 0 m_FAST%Lin%IsConverged = .false. m_FAST%Lin%FoundSteady = .false. + m_FAST%Lin%ForceLin = .false. m_FAST%Lin%AzimIndx = 1 p_FAST%AzimDelta = TwoPi / p_FAST%NLinTimes @@ -5317,12 +5318,25 @@ SUBROUTINE FAST_CalcSteady( n_t_global, t_global, p_FAST, y_FAST, m_FAST, ED, BD ! this is the 2pi boundary, so we are either larger than the last target azimuth or less than the next one NextAzimuth = psi >= m_FAST%Lin%AzimTarget(m_FAST%Lin%AzimIndx) .and. psi < m_FAST%Lin%AzimTarget(m_FAST%Lin%AzimIndx-1) end if + + ! Forcing linearization if it's the last step + if (t_global >= p_FAST%TMax - 0.5_DbKi*p_FAST%DT) then + call WrScr('') + call WrScr('[WARNING] Steady state not found before end of simulation. Forcing linearization.') + m_FAST%Lin%ForceLin = .True. + m_FAST%Lin%AzimIndx = 1 + NextAzimuth = .True. + endif if (NextAzimuth) then ! interpolate to find y at the target azimuth call FAST_DiffInterpOutputs( m_FAST%Lin%AzimTarget(m_FAST%Lin%AzimIndx), p_FAST, y_FAST, m_FAST, ED, BD, SrvD, AD, IfW, HD, SD, ExtPtfm, MAPp, FEAM, MD, Orca, & IceF, IceD, ErrStat, ErrMsg ) + ! If linearization is forced + if (m_FAST%Lin%ForceLin) then + m_FAST%Lin%IsConverged = .True. + endif if (m_FAST%Lin%IsConverged .or. m_FAST%Lin%n_rot == 0) then ! save this operating point for linearization later m_FAST%Lin%LinTimes(m_FAST%Lin%AzimIndx) = t_global @@ -5349,6 +5363,10 @@ SUBROUTINE FAST_CalcSteady( n_t_global, t_global, p_FAST, y_FAST, m_FAST, ED, BD end if end if + if (m_FAST%Lin%ForceLin) then + m_FAST%Lin%IsConverged=.true. + m_FAST%Lin%FoundSteady=.true. + endif END SUBROUTINE FAST_CalcSteady diff --git a/modules/openfast-library/src/FAST_Registry.txt b/modules/openfast-library/src/FAST_Registry.txt index bfaf87a116..f6f9fadf4d 100644 --- a/modules/openfast-library/src/FAST_Registry.txt +++ b/modules/openfast-library/src/FAST_Registry.txt @@ -325,6 +325,7 @@ typedef ^ FAST_MiscLinType IntKi CopyOP_CtrlCode - - - "mesh control co typedef ^ FAST_MiscLinType DbKi AzimTarget {:} - - "target azimuth positions in CalcSteady algorithm" rad typedef ^ FAST_MiscLinType logical IsConverged - - - "whether the error calculation in the CalcSteady algorithm is converged" - typedef ^ FAST_MiscLinType logical FoundSteady - - - "whether the CalcSteady algorithm found a steady-state solution" - +typedef ^ FAST_MiscLinType logical ForceLin - - - "whether the CalcSteady algorithm found a steady-state solution" - typedef ^ FAST_MiscLinType IntKi n_rot - - - "number of rotations completed in CalcSteady algorithm" - typedef ^ FAST_MiscLinType IntKi AzimIndx - - - "index into target azimuth array in CalcSteady algorithm" - typedef ^ FAST_MiscLinType IntKi NextLinTimeIndx - - - "index for next time in LinTimes where linearization should occur" - diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index 7a28e2cfc2..9b53f2b5b4 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -6131,6 +6131,9 @@ SUBROUTINE FAST_Linearize_T(t_initial, n_t_global, Turbine, ErrStat, ErrMsg) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) if (Turbine%m_FAST%Lin%FoundSteady) then + if (Turbine%m_FAST%Lin%ForceLin) then + Turbine%p_FAST%NLinTimes=1 + endif do iLinTime=1,Turbine%p_FAST%NLinTimes t_global = Turbine%m_FAST%Lin%LinTimes(iLinTime) @@ -6162,6 +6165,12 @@ SUBROUTINE FAST_Linearize_T(t_initial, n_t_global, Turbine, ErrStat, ErrMsg) if (Turbine%p_FAST%WrVTK == VTK_ModeShapes) CALL WrVTKCheckpoint() + if (Turbine%m_FAST%Lin%ForceLin) then + ErrStat2 = ErrID_Warn + ErrMsg2 = 'Linearization was forced at simulation end. The linearized model may not be sufficiently representative of the solution in steady state.' + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + endif + end if end if diff --git a/modules/openfast-library/src/FAST_Types.f90 b/modules/openfast-library/src/FAST_Types.f90 index 801d11adf5..c7f0c39fa5 100644 --- a/modules/openfast-library/src/FAST_Types.f90 +++ b/modules/openfast-library/src/FAST_Types.f90 @@ -325,6 +325,7 @@ MODULE FAST_Types REAL(DbKi) , DIMENSION(:), ALLOCATABLE :: AzimTarget !< target azimuth positions in CalcSteady algorithm [rad] LOGICAL :: IsConverged !< whether the error calculation in the CalcSteady algorithm is converged [-] LOGICAL :: FoundSteady !< whether the CalcSteady algorithm found a steady-state solution [-] + LOGICAL :: ForceLin !< whether the CalcSteady algorithm found a steady-state solution [-] INTEGER(IntKi) :: n_rot !< number of rotations completed in CalcSteady algorithm [-] INTEGER(IntKi) :: AzimIndx !< index into target azimuth array in CalcSteady algorithm [-] INTEGER(IntKi) :: NextLinTimeIndx !< index for next time in LinTimes where linearization should occur [-] @@ -14769,6 +14770,7 @@ SUBROUTINE FAST_CopyMiscLinType( SrcMiscLinTypeData, DstMiscLinTypeData, CtrlCod ENDIF DstMiscLinTypeData%IsConverged = SrcMiscLinTypeData%IsConverged DstMiscLinTypeData%FoundSteady = SrcMiscLinTypeData%FoundSteady + DstMiscLinTypeData%ForceLin = SrcMiscLinTypeData%ForceLin DstMiscLinTypeData%n_rot = SrcMiscLinTypeData%n_rot DstMiscLinTypeData%AzimIndx = SrcMiscLinTypeData%AzimIndx DstMiscLinTypeData%NextLinTimeIndx = SrcMiscLinTypeData%NextLinTimeIndx @@ -14901,6 +14903,7 @@ SUBROUTINE FAST_PackMiscLinType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er END IF Int_BufSz = Int_BufSz + 1 ! IsConverged Int_BufSz = Int_BufSz + 1 ! FoundSteady + Int_BufSz = Int_BufSz + 1 ! ForceLin Int_BufSz = Int_BufSz + 1 ! n_rot Int_BufSz = Int_BufSz + 1 ! AzimIndx Int_BufSz = Int_BufSz + 1 ! NextLinTimeIndx @@ -14987,6 +14990,8 @@ SUBROUTINE FAST_PackMiscLinType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, Er Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = TRANSFER(InData%FoundSteady, IntKiBuf(1)) Int_Xferred = Int_Xferred + 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%ForceLin, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%n_rot Int_Xferred = Int_Xferred + 1 IntKiBuf(Int_Xferred) = InData%AzimIndx @@ -15130,6 +15135,8 @@ SUBROUTINE FAST_UnPackMiscLinType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Int_Xferred = Int_Xferred + 1 OutData%FoundSteady = TRANSFER(IntKiBuf(Int_Xferred), OutData%FoundSteady) Int_Xferred = Int_Xferred + 1 + OutData%ForceLin = TRANSFER(IntKiBuf(Int_Xferred), OutData%ForceLin) + Int_Xferred = Int_Xferred + 1 OutData%n_rot = IntKiBuf(Int_Xferred) Int_Xferred = Int_Xferred + 1 OutData%AzimIndx = IntKiBuf(Int_Xferred)