Skip to content
4 changes: 2 additions & 2 deletions glue-codes/fast-farm/src/FAST_Farm_IO.f90
Original file line number Diff line number Diff line change
Expand Up @@ -775,11 +775,11 @@ SUBROUTINE Farm_ReadPrimaryFile( InputFile, p, WD_InitInp, AWAE_InitInp, OutList

CALL ReadVarWDefault( UnIn, InputFile, WD_InitInp%NumDFull, "NumDFull", &
"Distance of full wake propagation, expressed as a multiple of RotorDiamRef [>0.0] or DEFAULT [DEFAULT=15]", &
15_IntKi, ErrStat2, ErrMsg2, UnEc); if (Failed()) return
15.0_ReKi, ErrStat2, ErrMsg2, UnEc); if (Failed()) return

CALL ReadVarWDefault( UnIn, InputFile, WD_InitInp%NumDBuff, "NumDBuff", &
"Length of wake propagation buffer region, expressed as a multiple of RotorDiamRef [>=0.0] or DEFAULT [DEFAULT=5]", &
5_IntKi, ErrStat2, ErrMsg2, UnEc); if (Failed()) return
5.0_ReKi, ErrStat2, ErrMsg2, UnEc); if (Failed()) return

WD_InitInp%RotorDiamRef = p%RotorDiamRef

Expand Down
2 changes: 1 addition & 1 deletion glue-codes/fast-farm/src/FAST_Farm_Subs.f90
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ SUBROUTINE Farm_Initialize( farm, InputFile, ErrStat, ErrMsg )
call AllocAry( farm%p%MaxNumPlanes, farm%p%NumTurbines, 'farm%p%MaxNumPlanes', ErrStat2, ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName); if (Failed()) return
do i=1,farm%p%NumTurbines
! Eventually, we will have different settings for different rotors
farm%p%MaxNumPlanes(i) = ceiling( 15.0 * Real( WD_InitInput%InputFileData%NumDFull + WD_InitInput%InputFileData%NumDBuff , ReKi ) / AWAE_InitInput%InputFileData%C_Meander )
farm%p%MaxNumPlanes(i) = ceiling( 15.0 * ( WD_InitInput%InputFileData%NumDFull + WD_InitInput%InputFileData%NumDBuff ) / AWAE_InitInput%InputFileData%C_Meander )
farm%p%MaxNumPlanes(i) = max( 2, min( farm%p%MaxNumPlanes(i) , farm%p%n_TMax + 2 ) )
end do

Expand Down
82 changes: 51 additions & 31 deletions modules/wakedynamics/src/WakeDynamics.f90
Original file line number Diff line number Diff line change
Expand Up @@ -970,42 +970,62 @@ subroutine WD_UpdateStates( t, n, u, p, x, xd, z, OtherState, m, errStat, errMsg

do i=maxPln,0,-1

! if a plane is beyond the buffer, simply drop it and all following planes (it should only be the last plane that gets dropped)
if ( xd%x_plane(i) > p%x_Buff ) then
xd%NumPlanes = max( xd%NumPlanes - 1.0, 2.0 ) ! Plane indexing includes 0, hence the -1.0
cycle
endif

xd%NumPlanes = max( xd%NumPlanes - 1.0, 2.0 )

else if ( i+1 < NINT(xd%NumPlanes) .and. xd%x_plane(i) >= xd%x_plane(i+1) ) then

call SetErrStat(ErrID_Warn, ' Turbine '//trim(num2lstr(p%TurbNum))//' wake plane '//trim(num2lstr(i))//' (x_plane='//trim(num2lstr(xd%x_plane(i)))//') has overtaken wake plane '//trim(num2lstr(i+1))//' (x_plane='//trim(num2lstr(xd%x_plane(i+1)))//'). Offending wake plane removed. Reduce f_c to prevent planes from passing each other. ', errStat, errMsg, RoutineName)
if (errStat >= AbortErrLev) then
call Cleanup()
return
end if

! Remove offending plane and shift everything behind up

xd%NumPlanes = xd%NumPlanes - 1.0

! Didn't check xd%NumPlanes >= 2 here. The first wake plane is unlikely to move upwind of the rotor.

do j = i+1,NINT(xd%NumPlanes)-1
! If a plane overtakes another plane, merge the planes by averaging, then shift all remaining planes forward.
if ( i+1 < NINT(xd%NumPlanes)) then ! don't overstep bounds with i+1 indexing
if (xd%x_plane(i) >= xd%x_plane(i+1) ) then

xd%Vx_wind_disk_filt(j-1) = xd%Vx_wind_disk_filt(j)
xd%x_plane ( j-1) = xd%x_plane ( j)
xd%TI_amb_filt ( j-1) = xd%TI_amb_filt ( j)
xd%D_rotor_filt ( j-1) = xd%D_rotor_filt ( j)
xd%YawErr_filt ( j-1) = xd%YawErr_filt ( j)
xd%p_plane ( :,j-1) = xd%p_plane ( :,j)
xd%xhat_plane ( :,j-1) = xd%xhat_plane ( :,j)
xd%V_plane_filt ( :,j-1) = xd%V_plane_filt ( :,j)
xd%Vx_wake ( :,j-1) = xd%Vx_wake ( :,j)
xd%Vr_wake ( :,j-1) = xd%Vr_wake ( :,j)
xd%Vx_wake2 (:,:,j-1) = xd%Vx_wake2 (:,:,j)
xd%Vy_wake2 (:,:,j-1) = xd%Vy_wake2 (:,:,j)
xd%Vz_wake2 (:,:,j-1) = xd%Vz_wake2 (:,:,j)
call SetErrStat(ErrID_Warn, ' Turbine '//trim(num2lstr(p%TurbNum))//' wake plane '//trim(num2lstr(i))// &
' (x_plane='//trim(num2lstr(xd%x_plane(i)))//') has overtaken wake plane '//trim(num2lstr(i+1))// &
' (x_plane='//trim(num2lstr(xd%x_plane(i+1)))// &
'). Merging planes by averaging. Reduce f_c to prevent planes from passing each other. ', errStat, errMsg, RoutineName)
if (errStat >= AbortErrLev) then
call Cleanup()
return
end if

end do
! Merge the i and i+1 plane by averaging them together
xd%Vx_wind_disk_filt(i) = (xd%Vx_wind_disk_filt(i) + xd%Vx_wind_disk_filt(i+1)) / 2.0_ReKi
xd%x_plane ( i) = (xd%x_plane ( i) + xd%x_plane ( i+1)) / 2.0_ReKi
xd%TI_amb_filt ( i) = (xd%TI_amb_filt ( i) + xd%TI_amb_filt ( i+1)) / 2.0_ReKi
xd%D_rotor_filt ( i) = (xd%D_rotor_filt ( i) + xd%D_rotor_filt ( i+1)) / 2.0_ReKi
xd%YawErr_filt ( i) = (xd%YawErr_filt ( i) + xd%YawErr_filt ( i+1)) / 2.0_ReKi
xd%p_plane ( :,i) = (xd%p_plane ( :,i) + xd%p_plane ( :,i+1)) / 2.0_ReKi
xd%xhat_plane ( :,i) = (xd%xhat_plane ( :,i) + xd%xhat_plane ( :,i+1)) / 2.0_ReKi
xd%xhat_plane ( :,i) = xd%xhat_plane ( :,i) / TwoNorm(xd%xhat_plane( :,i)) ! renormalize
xd%V_plane_filt ( :,i) = (xd%V_plane_filt ( :,i) + xd%V_plane_filt ( :,i+1)) / 2.0_ReKi
xd%Vx_wake ( :,i) = (xd%Vx_wake ( :,i) + xd%Vx_wake ( :,i+1)) / 2.0_ReKi
xd%Vr_wake ( :,i) = (xd%Vr_wake ( :,i) + xd%Vr_wake ( :,i+1)) / 2.0_ReKi
xd%Vx_wake2 (:,:,i) = (xd%Vx_wake2 (:,:,i) + xd%Vx_wake2 (:,:,i+1)) / 2.0_ReKi
xd%Vy_wake2 (:,:,i) = (xd%Vy_wake2 (:,:,i) + xd%Vy_wake2 (:,:,i+1)) / 2.0_ReKi
xd%Vz_wake2 (:,:,i) = (xd%Vz_wake2 (:,:,i) + xd%Vz_wake2 (:,:,i+1)) / 2.0_ReKi

! Since i and i+1 planes are now merged effectively dropping a plane, shift all planes that follow forward
do j = i+1,NINT(xd%NumPlanes)-2 ! NumPlanes includes 0 index plane, so last valid index is NumPlanes-1.
xd%Vx_wind_disk_filt(j) = xd%Vx_wind_disk_filt(j+1)
xd%x_plane ( j) = xd%x_plane ( j+1)
xd%TI_amb_filt ( j) = xd%TI_amb_filt ( j+1)
xd%D_rotor_filt ( j) = xd%D_rotor_filt ( j+1)
xd%YawErr_filt ( j) = xd%YawErr_filt ( j+1)
xd%p_plane ( :,j) = xd%p_plane ( :,j+1)
xd%xhat_plane ( :,j) = xd%xhat_plane ( :,j+1)
xd%V_plane_filt ( :,j) = xd%V_plane_filt ( :,j+1)
xd%Vx_wake ( :,j) = xd%Vx_wake ( :,j+1)
xd%Vr_wake ( :,j) = xd%Vr_wake ( :,j+1)
xd%Vx_wake2 (:,:,j) = xd%Vx_wake2 (:,:,j+1)
xd%Vy_wake2 (:,:,j) = xd%Vy_wake2 (:,:,j+1)
xd%Vz_wake2 (:,:,j) = xd%Vz_wake2 (:,:,j+1)
end do

! Now that we shifted the planes up, remove the last one
xd%NumPlanes = xd%NumPlanes - 1.0

end if
end if

end do
Expand Down
4 changes: 2 additions & 2 deletions modules/wakedynamics/src/WakeDynamics_Registry.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ param ^ - INTEGER Mod_Wake_Cartesian
# ..... InputFile Data .......................................................................................................
typedef ^ WD_InputFileType ReKi dr - - - "Radial increment of radial finite-difference grid [>0.0]" m
typedef ^ WD_InputFileType IntKi NumRadii - - - "Number of radii in the radial finite-difference grid [>=2]" -
typedef ^ WD_InputFileType IntKi NumDFull - - - "Distance of full wake propagation as a multiple of RotorDiamRef" -
typedef ^ WD_InputFileType IntKi NumDBuff - - - "Length of wake propagation buffer region as a multiple of RotorDiamRef" -
typedef ^ WD_InputFileType ReKi NumDFull - - - "Distance of full wake propagation as a multiple of RotorDiamRef" -
typedef ^ WD_InputFileType ReKi NumDBuff - - - "Length of wake propagation buffer region as a multiple of RotorDiamRef" -
typedef ^ WD_InputFileType IntKi Mod_Wake - - - "Switch between wake formulations 1=Polar, 2=Cartesian, 3=Curl" -
typedef ^ WD_InputFileType ReKi f_c - - - "Cut-off frequency of the low-pass time-filter for the wake advection, deflection, and meandering model [>0.0]" Hz
typedef ^ WD_InputFileType ReKi C_HWkDfl_O - - - "Calibrated parameter in the correction for wake deflection defining the horizontal offset at the rotor" m
Expand Down
4 changes: 2 additions & 2 deletions modules/wakedynamics/src/WakeDynamics_Types.f90
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ MODULE WakeDynamics_Types
TYPE, PUBLIC :: WD_InputFileType
REAL(ReKi) :: dr = 0.0_ReKi !< Radial increment of radial finite-difference grid [>0.0] [m]
INTEGER(IntKi) :: NumRadii = 0_IntKi !< Number of radii in the radial finite-difference grid [>=2] [-]
INTEGER(IntKi) :: NumDFull = 0_IntKi !< Distance of full wake propagation as a multiple of RotorDiamRef [-]
INTEGER(IntKi) :: NumDBuff = 0_IntKi !< Length of wake propagation buffer region as a multiple of RotorDiamRef [-]
REAL(ReKi) :: NumDFull = 0.0_ReKi !< Distance of full wake propagation as a multiple of RotorDiamRef [-]
REAL(ReKi) :: NumDBuff = 0.0_ReKi !< Length of wake propagation buffer region as a multiple of RotorDiamRef [-]
INTEGER(IntKi) :: Mod_Wake = 0_IntKi !< Switch between wake formulations 1=Polar, 2=Cartesian, 3=Curl [-]
REAL(ReKi) :: f_c = 0.0_ReKi !< Cut-off frequency of the low-pass time-filter for the wake advection, deflection, and meandering model [>0.0] [Hz]
REAL(ReKi) :: C_HWkDfl_O = 0.0_ReKi !< Calibrated parameter in the correction for wake deflection defining the horizontal offset at the rotor [m]
Expand Down
Loading