From 002e8c7812649ab006be464b01ccbf66ea4a82a9 Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 29 Jul 2026 15:12:17 -0600 Subject: [PATCH 1/2] Fix segfault in SetVTKParameters when CompElast=SED with VTK enabled When using Simplified ElastoDyn (CompElast=3) with VTK output enabled, Init%OutData_ED was never allocated, causing an out-of-bounds access at the SetVTKParameters call site. Additionally, SetVTKParameters itself had several unguarded accesses to ED data structures. Fixes: - Guard call site with allocated() check, pass dummy when ED unused - Add Module_SED case for BladeLength/HubRad in SetVTKParameters - Use SED%y%TowerLn2Mesh for tower mesh when CompElast=SED (add TARGET) - Handle SED in blade surface section (no BladeLn2Mesh available) Co-authored-by: GitHub Copilot (Claude Opus 4) Co-authored-by: Claude --- modules/openfast-library/src/FAST_Subs.f90 | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index a93532e4b..634447baa 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -166,6 +166,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, m_Glue, p_FAST, y_FAST, m_FAST, ED, SE logical :: CallStart REAL(R8Ki) :: theta(3) ! angles for hub orientation matrix for aeromaps + TYPE(ED_InitOutputType) :: InitOutData_ED_Dummy ! dummy for SetVTKParameters when ED is not used CHARACTER(*), PARAMETER :: RoutineName = 'FAST_InitializeAll' CHARACTER(ErrMsgLen) :: ErrMsg2 @@ -1523,8 +1524,13 @@ SUBROUTINE FAST_InitializeAll( t_initial, m_Glue, p_FAST, y_FAST, m_FAST, ED, SE !---------------------------------------------------------------------------- if ( p_FAST%WrVTK > VTK_None ) then - ! TODO: support multiple ElastoDyns - call SetVTKParameters(p_FAST, Init%OutData_ED(1), Init%OutData_SED, Init%OutData_AD, Init%OutData_SeaSt, Init%OutData_HD, ED, SED, BD, AD, HD, ErrStat2, ErrMsg2) + ! TODO: support multiple ElastoDyns -- remove InitOutData_ED_Dummy when done. + ! FIXME: this solution conflicts with multirotor development. When merging, favor the multirotor approach already in dev over this. + if (allocated(Init%OutData_ED)) then + call SetVTKParameters(p_FAST, Init%OutData_ED(1), Init%OutData_SED, Init%OutData_AD, Init%OutData_SeaSt, Init%OutData_HD, ED, SED, BD, AD, HD, ErrStat2, ErrMsg2) + else + call SetVTKParameters(p_FAST, InitOutData_ED_Dummy, Init%OutData_SED, Init%OutData_AD, Init%OutData_SeaSt, Init%OutData_HD, ED, SED, BD, AD, HD, ErrStat2, ErrMsg2) + end if call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) end if @@ -3803,7 +3809,7 @@ SUBROUTINE SetVTKParameters(p_FAST, InitOutData_ED, InitOutData_SED, InitOutData TYPE(SeaSt_InitOutputType), INTENT(INOUT) :: InitOutData_SeaSt !< The initialization output from SeaState TYPE(HydroDyn_InitOutputType),INTENT(INOUT) :: InitOutData_HD !< The initialization output from HydroDyn TYPE(ElastoDyn_Data), TARGET, INTENT(IN ) :: ED !< ElastoDyn data - TYPE(SED_Data), INTENT(IN ) :: SED !< Simplified-ElastoDyn data + TYPE(SED_Data), TARGET, INTENT(IN ) :: SED !< Simplified-ElastoDyn data TYPE(BeamDyn_Data), INTENT(IN ) :: BD !< BeamDyn data TYPE(AeroDyn_Data), INTENT(IN ) :: AD !< AeroDyn data TYPE(HydroDyn_Data), INTENT(IN ) :: HD !< HydroDyn data @@ -3862,6 +3868,9 @@ SUBROUTINE SetVTKParameters(p_FAST, InitOutData_ED, InitOutData_SED, InitOutData if ( p_FAST%CompElast == Module_BD ) then BladeLength = TwoNorm(BD%y(1)%BldMotion%Position(:,1) - BD%y(1)%BldMotion%Position(:,BD%y(1)%BldMotion%Nnodes)) HubRad = InitOutData_ED%HubRad + else if ( p_FAST%CompElast == Module_SED ) then + BladeLength = InitOutData_SED%BladeLength + HubRad = InitOutData_SED%HubRad else BladeLength = InitOutData_ED%BladeLength HubRad = InitOutData_ED%HubRad @@ -3916,7 +3925,11 @@ SUBROUTINE SetVTKParameters(p_FAST, InitOutData_ED, InitOutData_SED, InitOutData ! Create the tower surface data !....................... ! TODO: Support multiple towers - TowerMotionMesh => ED%y(1)%TowerLn2Mesh + if (p_FAST%CompElast == Module_SED) then + TowerMotionMesh => SED%y%TowerLn2Mesh + else + TowerMotionMesh => ED%y(1)%TowerLn2Mesh + end if CALL AllocAry(p_FAST%VTK_Surface%TowerRad,TowerMotionMesh%NNodes,'VTK_Surface%TowerRad',ErrStat2,ErrMsg2) CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) @@ -4001,7 +4014,9 @@ SUBROUTINE SetVTKParameters(p_FAST, InitOutData_ED, InitOutData_SED, InitOutData CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) IF (ErrStat >= AbortErrLev) RETURN END DO -! ELSE IF (p_FAST%CompElast == Module_SED) THEN ! no blade surface info from SED + ELSE IF (p_FAST%CompElast == Module_SED) THEN + ! SED has no blade line2 mesh; skip generic blade surface generation + call WrScr('Skipping generic blade surfaces for Simplified ElastoDyn (no blade mesh available).') ELSE call WrScr('Using generic blade surfaces for ElastoDyn (rectangular airfoil, constant chord). ') ! TODO make this an option DO K=1,NumBl From 3df8ed675a28494633bfd13c9d499b3f955b565b Mon Sep 17 00:00:00 2001 From: andrew-platt Date: Wed, 29 Jul 2026 17:25:02 -0600 Subject: [PATCH 2/2] SED: add fatal error for zero drivetrain inertia with GenDOF enabled When GenDOF is True and both RotIner and GenIner are zero, the drivetrain inertia J_DT is zero, causing division by zero in SED_CalcContStateDeriv. This produced NaN states that propagated through the hub orientation into InflowWind, manifesting as a cryptic 'GF wind array exhausted at NaN seconds' error. Add an initialization check that reports a clear fatal error explaining the issue and how to fix it. Co-authored-by: GitHub Copilot (Claude Opus 4) Co-authored-by: Claude --- modules/simple-elastodyn/src/SED.f90 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/simple-elastodyn/src/SED.f90 b/modules/simple-elastodyn/src/SED.f90 index 3c1d2fa54..4e54d98b0 100644 --- a/modules/simple-elastodyn/src/SED.f90 +++ b/modules/simple-elastodyn/src/SED.f90 @@ -190,6 +190,14 @@ subroutine SED_SetParameters(ErrStat3,ErrMsg3) ! system inertia p%J_DT = p%RotIner + p%GBoxRatio**2_IntKi * p%GenIner + ! Check for zero inertia with GenDOF enabled (would cause division by zero in CalcContStateDeriv) + if (p%GenDOF .and. EqualRealNos(real(p%J_DT, ReKi), 0.0_ReKi)) then + ErrStat3 = ErrID_Fatal + ErrMsg3 = 'GenDOF is enabled but drivetrain inertia (RotIner + GBoxRatio^2*GenIner) is zero. '// & + 'This would result in a division by zero. Set RotIner or GenIner to a non-zero value, or disable GenDOF.' + return + end if + ! Set the outputs call SetOutParam(InputFileData%OutList, p, ErrStat3, ErrMsg3 ) end subroutine SED_SetParameters