diff --git a/glue-codes/fast-farm/src/FAST_Farm_IO.f90 b/glue-codes/fast-farm/src/FAST_Farm_IO.f90 index 86e3f58cb3..32fce6d53c 100644 --- a/glue-codes/fast-farm/src/FAST_Farm_IO.f90 +++ b/glue-codes/fast-farm/src/FAST_Farm_IO.f90 @@ -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 diff --git a/glue-codes/fast-farm/src/FAST_Farm_Subs.f90 b/glue-codes/fast-farm/src/FAST_Farm_Subs.f90 index 30a7160478..5a2eabde5c 100644 --- a/glue-codes/fast-farm/src/FAST_Farm_Subs.f90 +++ b/glue-codes/fast-farm/src/FAST_Farm_Subs.f90 @@ -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 diff --git a/modules/wakedynamics/src/WakeDynamics.f90 b/modules/wakedynamics/src/WakeDynamics.f90 index 6664c6e44f..05b357088e 100644 --- a/modules/wakedynamics/src/WakeDynamics.f90 +++ b/modules/wakedynamics/src/WakeDynamics.f90 @@ -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 diff --git a/modules/wakedynamics/src/WakeDynamics_Registry.txt b/modules/wakedynamics/src/WakeDynamics_Registry.txt index 56ae0024ef..692d06973b 100644 --- a/modules/wakedynamics/src/WakeDynamics_Registry.txt +++ b/modules/wakedynamics/src/WakeDynamics_Registry.txt @@ -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 diff --git a/modules/wakedynamics/src/WakeDynamics_Types.f90 b/modules/wakedynamics/src/WakeDynamics_Types.f90 index 23368a4d45..faec69b17a 100644 --- a/modules/wakedynamics/src/WakeDynamics_Types.f90 +++ b/modules/wakedynamics/src/WakeDynamics_Types.f90 @@ -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]