Commit ea56b61b authored by Jaime Liew's avatar Jaime Liew
Browse files

add derating functionality (max, const rotation)

parent 1d820e5f
Pipeline #7056 passed with stages
in 54 seconds
......@@ -331,6 +331,9 @@ subroutine init_regulation_advanced(array1, array2) bind(c,name='init_regulation
! Rotor speed notch filter
! constant 77 ; Frequency of notch filter [Hz] applied on the rotor speed before computing torque above rated (constant power), if zero no notch filter used
! constant 78 ; Damping of notch filter [-] applied on the rotor speed before computing torque above rated (constant power), (Default 0.01 used if zero)
!
! constant 79 ; Derate strategy. 0 = No Derating, 1 = constant rotation, 2 = max rotation
! constant 80 ; Derate percentage (eg. 70 means 70% of nominal power)
call init_regulation(array1, array2)
! Generator torque exclusion zone
if (array1(53).gt.0.0_mk) ExcluZone%Lwr = array1(53)
......@@ -372,6 +375,9 @@ subroutine init_regulation_advanced(array1, array2) bind(c,name='init_regulation
if (array1(78).gt.0.0_mk) DT_mode_filt_torque%zeta2 = array1(78)
! Initialization
TimerExcl = -0.02_mk
! Derating parameters
Deratevar%strat = array1(79)
Deratevar%dr = array1(80)/100.0
return
end subroutine init_regulation_advanced
!**************************************************************************************************
......
......@@ -53,6 +53,10 @@ module dtu_we_controller_fcns
real(mk) invkk1, invkk2
real(mk) kp_speed, invkk1_speed, invkk2_speed
end type
type TDeratevar
integer :: strat
real(mk) :: dr
end type
! Custom Types
type(Twpdata), save :: OPdatavar
type(Texclzone), save :: ExcluZone
......
......@@ -51,6 +51,7 @@ module turbine_controller_mod
type(Tswitch), save :: SwitchVar
type(TSafetySystem), save :: MoniVar
type(TPitchGSvar), save :: PitchGSVar
type(TDeratevar), save :: Deratevar
!**************************************************************************************************
contains
!**************************************************************************************************
......@@ -80,11 +81,22 @@ subroutine turbine_controller(CtrlStatus, GridFlag, GenSpeed, PitchVect, wsp, Pe
TTAcc = dsqrt(TTAccVect(1)**2 + TTAccVect(2)**2)
call monitoring(CtrlStatus, GridFlag, GenSpeed, TTAcc, PitchVect, PitchColRefOld, dump_array)
!***********************************************************************************************
! Normal operation for control status CtrlStatus = 0
!***********************************************************************************************
if (CtrlStatus .eq. 0) then
! Control Status CtrlStatus = 0
!-----------------------------------------------------------------------------------------------
! Normal operation
!-----------------------------------------------------------------------------------------------
if (CtrlStatus .eq. 0 .and. Deratevar%strat .eq. 0) then
call normal_operation(GenSpeed, PitchVect, wsp, Pe, TTAccVect(2), GenTorqueRef, PitchColRef,&
dump_array)
!-----------------------------------------------------------------------------------------------
! Derate operation
!-----------------------------------------------------------------------------------------------
elseif (CtrlStatus .eq. 0 .and. Deratevar%strat .gt. 0) then
call derate_operation(GenSpeed, PitchVect, wsp, Pe, TTAccVect(2), GenTorqueRef, PitchColRef,&
dump_array)
endif
!***********************************************************************************************
! Cut-in procedure for control status CtrlStatus = -1
......@@ -185,6 +197,106 @@ subroutine normal_operation(GenSpeed, PitchVect, wsp, Pe, TTfa_acc, GenTorqueRef
return
end subroutine normal_operation
!**************************************************************************************************
subroutine derate_operation(GenSpeed, PitchVect, wsp, Pe, TTfa_acc, GenTorqueRef, PitchColRef,dump_array)
! Controller for derate operation.
!
real(mk), intent(in) :: PitchVect(3) ! Measured pitch angles [rad].
real(mk), intent(in) :: GenSpeed ! Measured generator speed [rad/s].
real(mk), intent(in) :: wsp ! Measured wind speed [m/s].
real(mk), intent(in) :: Pe ! Measured electrical power [W].
real(mk), intent(in) :: TTfa_acc ! Measured tower top longitudinal acceleration.
real(mk), intent(out) :: GenTorqueRef ! Generator torque reference [Nm].
real(mk), intent(out) :: PitchColRef ! Reference collective pitch [rad].
real(mk), intent(inout) :: dump_array(50) ! Array for output.
real(mk) WSPfilt
real(mk) GenSpeedFilt, dGenSpeed_dtFilt,PeFilt
real(mk) PitchMean, PitchMeanFilt, PitchMin
real(mk) GenSpeedRef_full , GenSpeedDerate
real(mk) Qdamp_ref, theta_dam_ref, P_filt
real(mk) x, y(2)
!***********************************************************************************************
! Inputs and their filtering
!***********************************************************************************************
! Mean pitch angle
PitchMean = (PitchVect(1) + PitchVect(2) + PitchVect(3)) / 3.0_mk
! Low-pass filtering of the rotor speed
y = lowpass2orderfilt(deltat, stepno, omega2ordervar, GenSpeed)
GenSpeedFilt = y(1)
dGenSpeed_dtFilt = y(2)
! Low pass filtered power
y = lowpass2orderfilt(deltat, stepno, power2ordervar, Pe)
PeFilt=y(1)
! Low-pass filtering of the mean pitch angle for gain scheduling
PitchMeanFilt = lowpass1orderfilt(deltat, stepno, pitchfirstordervar, PitchMean)
PitchMeanFilt = min(PitchMeanFilt, 30.0_mk*degrad)
! Low-pass filtering of the nacelle wind speed
WSPfilt = lowpass1orderfilt(deltat, stepno, wspfirstordervar, wsp)
! Minimum pitch angle may vary with filtered wind speed
PitchMin = GetOptiPitch(WSPfilt)
!***********************************************************************************************
! Limit reference speed for storm control
!***********************************************************************************************
if (Vcutout .gt. Vstorm) then
GenSpeedRef_full = GenSpeedRefMax - max(0.0_mk, &
(WSPfilt - Vstorm)/(Vcutout - Vstorm)*(GenSpeedRefMax - GenSpeedRefMin))
else
GenSpeedRef_full = GenSpeedRefMax
endif
!***********************************************************************************************
! Select Case based on derate strategy
!***********************************************************************************************
select case (Deratevar%strat)
case(1) ! constant rotation
GenSpeedDerate = ((Deratevar%dr*PeRated)/Kopt)**(1.0/3) ! Derated Rotor Speed
GenSpeedRefMax = min(GenSpeedRefMax,GenSpeedDerate)
GenTorqueRated = (Deratevar%dr*PeRated)/GenSpeedRefMax
case(2) ! maximum rotation
GenTorqueRated = (Deratevar%dr*PeRated)/GenSpeedRefMax
end select
GenSpeedRef_full = max(min(GenSpeedRef_full, GenSpeedRefMax), GenSpeedRefMin)
!***********************************************************************************************
! PID regulation of generator torque
!***********************************************************************************************
call torquecontroller(GenSpeed, GenSpeedFilt, dGenSpeed_dtFilt, PitchMean, WSPfilt, PitchMin, &
GenSpeedRef_full, Pe, GenTorqueRef, dump_array)
!***********************************************************************************************
! Active DT damping based on filtered rotor speed
!***********************************************************************************************
call drivetraindamper(GenSpeed, Qdamp_ref, dump_array)
if (newtimestep) TimerGenCutin = TimerGenCutin + deltat
x = switch_spline(TimerGenCutin, CutinVar%delay, 2.0_mk*CutinVar%delay)
GenTorqueRef = min(max(GenTorqueRef + Qdamp_ref*x, 0.0_mk), GenTorqueMax)
!***********************************************************************************************
! PID regulation of collective pitch angle
!***********************************************************************************************
call pitchcontroller(GenSpeedFilt, dGenSpeed_dtFilt, PitchMeanFilt, PeFilt, PitchMin, &
GenSpeedRef_full, PitchColRef, dump_array)
!***********************************************************************************************
! Active Tower damping based on filtered tower top aceleration
!***********************************************************************************************
P_filt = lowpass1orderfilt(deltat, stepno, TTfa_PWRfirstordervar, GenTorqueRef*GenSpeedFilt)
call towerdamper(TTfa_acc, theta_dam_ref, dump_array)
x = switch_spline(P_filt, TTfa_PWR_lower*PeRated, TTfa_PWR_upper*PeRated)
PitchColRef = min(max(PitchColRef + theta_dam_ref*x, PID_pit_var%outmin), PID_pit_var%outmax)
! Write into dump array
dump_array(1) = GenTorqueRef*GenSpeed
dump_array(2) = WSPfilt
dump_array(3) = GenSpeedFilt
dump_array(20) = PitchMeanFilt
return
end subroutine derate_operation
!**************************************************************************************************
subroutine start_up(CtrlStatus, GenSpeed, PitchVect, wsp, GenTorqueRef, PitchColRef, dump_array)
!
! Start-up procedures.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment