Commit 5eb1582c authored by famen's avatar famen
Browse files

Implemented Lidar assisted control in below rated region:

1. optimal tsr tracking (ott) and optimal aero-torque tracking (oat)
2. using pitch to track optimal tsr
parent 0d9dec59
Pipeline #23497 passed with stage
in 4 minutes and 18 seconds
......@@ -13,3 +13,6 @@ __pycache__/
/version.h
build_vs17/
build_DHI_vs17/
examples/HAWC2/DTU10MW/res/
examples/HAWC2/DTU10MW/log/
examples/HAWC2/DTU10MW/control/*.dll
8
lac_mode 3
cp_opt 0.485
tsr_opt 7.35
gain_oat 2.0
pitch_limit_min -2.5
pitch_limit_max 3.0
kp_ott_torque 1.0
kp_ott_torque 1.0
\ No newline at end of file
......@@ -4,7 +4,7 @@ module dtu_we_controller
! Main module of the Basic DTU Wind Energy Controller.
! Interface for HAWC2 type2_dll
!
! use dtu_we_controller_fcns
use dtu_we_controller_fcns
use BuildInfo
use safety_system_mod
use dll_utils
......@@ -20,6 +20,7 @@ module dtu_we_controller
! variables for debugging purpose
character(1) str
logical, save :: DEBUG_Flag = .false.
! Now it works for Intel Fortran Compiler with Visual Studio 2017/2019 and GNU Fortran on Windows
! TODO:
! Remember to test this implementation on Linux
......@@ -35,7 +36,7 @@ module dtu_we_controller
end interface
! TODO:
! Now it works with intel fortran using VS 2017/2019
! Remember to consider cross-platform and cross-compiler
! Remember to consider cross-platform e.g. test the implementation on Linux
procedure(WTController), bind(c), pointer :: fp_WTController
contains
......@@ -158,6 +159,7 @@ subroutine init_regulation(array1, array2) bind(c, name='init_regulation')
! Full load control parameters
TorqueCtrlRatio=min(1.0_mk,max(0.0_mk,array1(15)))
! - Gains
! - Baseline CPC pitch controller PID parameters
PID_pit_var%kpro(1) = array1(16)
PID_pit_var%kint(1) = array1(17)
PID_pit_var%kdif(1) = array1(18)
......@@ -173,6 +175,14 @@ subroutine init_regulation(array1, array2) bind(c, name='init_regulation')
PitchGSVar%invkk2 = 1.0_mk/(array1(22)*degrad*degrad)
endif
rel_limit = array1(23)
! - Lidar-assisted-control CPC pitch controller PID parameters
PID_lac_pit_var%kpro(1) = PID_pit_var%kpro(1)
PID_lac_pit_var%kint(1) = PID_pit_var%kint(1)
PID_lac_pit_var%kdif(1) = PID_pit_var%kdif(1)
PID_lac_pit_var%kpro(2) = 0.0_mk
PID_lac_pit_var%kint(2) = 0.0_mk
PID_lac_pit_var%kdif(2) = 0.0_mk
! Cut-in simulation parameters
CutinVar%time = array1(24)
CutinVar%delay = array1(25)*2.0_mk*pi/GenSpeedRefMax
......@@ -257,12 +267,97 @@ subroutine init_regulation(array1, array2) bind(c, name='init_regulation')
R = 0.5_mk*array1(47)
! Alternative partial load controller
Kopt_dot= array1(48)
TSR_opt = array1(49)
if (array1(11) .le. 0.0_mk) then
PartialLoadControlMode = 2
! if user provides negative number. It is used as the extension name for a text file
! which contains additional parameters needed by lidar assisted control. e.g '-1 = *.1'
TSR_opt = array1(49)
if (TSR_opt .le. 0.0_mk) then
! Read in extra control input file for lidar assisted control
write(lac_input_data%name,'(i3)') iabs(int(array1(49)))
inquire(file='./control/lacdata.'//trim(adjustl(lac_input_data%name)),exist=findes)
if (findes) then
open(68,file='./control/lacdata.'//trim(adjustl(lac_input_data%name)))
read(68,*,iostat=ifejl) lac_input_data%lines
if (.not.allocated(lac_input_data%data_val)) then
allocate(lac_input_data%data_val(lac_input_data%lines))
endif
if (.not.allocated(lac_input_data%data_name)) then
allocate(lac_input_data%data_name(lac_input_data%lines))
endif
if (ifejl.eq.0) then
do i=1,lac_input_data%lines
read(68,*,iostat=ifejl) lac_input_data%data_name(i), lac_input_data%data_val(i)
if (ifejl.ne.0) then
write(6,'(a,i2)') ' *** ERROR *** Could not read date lines in Lidar'&
//'assisted control in file: lacdata.'//trim(adjustl(lac_input_data%name))//' in line:', i+1
stop
endif
enddo
lac_input_data%mode = int(lac_input_data%data_val(1))
lac_input_data%cp_opt = lac_input_data%data_val(2)
lac_input_data%tsr_opt = lac_input_data%data_val(3)
lac_input_data%gain_oat = lac_input_data%data_val(4)
lac_input_data%pitch_min = lac_input_data%data_val(5)
lac_input_data%pitch_max = lac_input_data%data_val(6)
lac_input_data%kp_ott_torq = lac_input_data%data_val(7)
lac_input_data%ki_ott_torq = lac_input_data%data_val(8)
write(6,'(a)') ' *** INFO *** Lidar Assisted Control input File ''lacdata.'//trim(adjustl(lac_input_data%name))&
//''' is read successfully.'
lidar_assisted_control = lac_input_data%mode
else
write(6,'(a,i2)') ' *** ERROR *** Could not read number of lines '&
//'in Lidar assisted control file: lacdata.'//trim(adjustl(lac_input_data%name))//' in line:',1
stop
endif
close(68)
else
write(6,*) ' *** ERROR *** File ''lacdata.'//trim(adjustl(lac_input_data%name))&
//''' does not exist in the ./control/folder'
stop
endif
endif
! Show some useful info when in the Debug mode
if(compiled_with_debug .and. (TSR_opt .le. 0.0_mk)) then
! write(6,'(1x,a,f10.6)') trim(lac_input_data%data_name(2))//' =', lac_input_data%cp_opt
write(6,'(i3,7f10.6)') lac_input_data%mode,lac_input_data%cp_opt,lac_input_data%tsr_opt,lac_input_data%gain_oat, &
lac_input_data%pitch_min,lac_input_data%pitch_max, lac_input_data%kp_ott_torq,lac_input_data%ki_ott_torq
! stop
endif
if(array1(11) .gt. 0.0_mk) then
PartialLoadControlMode = 1
else
PartialLoadControlMode = 2
endif
! if ((array1(11) .le. 0.0_mk) .and. (TSR_opt .gt. 0.0_mk)) then
! PartialLoadControlMode = 2
! lidar_assisted_control = 2
! elseif(array1(11) .gt. 0.0_mk) then
! PartialLoadControlMode = 1
! if(TSR_opt .gt. 0.0_mk) then
! lidar_assisted_control = 1
! else
! lidar_assisted_control = 0
! endif
! else
! write(6,'(a)'), ' *** ERROR ***: Partial load control method is not set correctly!'
! stop
! endif
if(lidar_assisted_control .gt. 0) then
write (6,'(a,a,i2,a,f8.3,a,f8.3,a)') ' Lidar Assisted Control is actived.', &
' Method = ',lidar_assisted_control, &
' Optimal TSR = ', lac_input_data%tsr_opt, &
' Rotor radius = ', R , ' [m]'
write(6,'(a)'), ' *** INFO ***: Wind speed measured by 4-beam nacelle LIDAR is used!'
else
PartialLoadControlMode = 1
write(6,'(a)'), ' *** INFO ***: Hub heigt wind speed is used!'
! stop
endif
! Gain scheduling dQdomega
PitchGSVar%kp_speed = array1(50)
if (array1(51) .gt. 0.0_mk) then
......@@ -687,6 +782,14 @@ subroutine update_regulation(array1, array2) bind(c,name='update_regulation')
! 14: dll type2_dll individual_pitch_controller inpvec 2; [rad] only needed if using individual pitch control
! 15: dll type2_dll individual_pitch_controller inpvec 3; [rad] only needed if using individual pitch control
! 16: Tower top x-velocity [m/s]
! 17-21: 1-beam Lidar measurements
! 22-26: 2-beam Lidar measurements
! 27-31: 3-beam Lidar measurements
! 32-36: 4-beam Lidar measurements
! 17: aero nacelle_lidar 0 0 0 15 45 100 18.67 2 100 1; LOS vel.
! 22: aero nacelle_lidar 0 0 0 15 -45 100 18.67 2 100 2; LOS vel.
! 27: aero nacelle_lidar 0 0 0 -15 45 100 18.67 2 100 3; LOS vel.
! 32: aero nacelle_lidar 0 0 0 -15 -45 100 18.67 2 100 4; LOS vel.
! Output array2 contains
!
! 1: Generator torque reference [Nm]
......@@ -730,7 +833,10 @@ subroutine update_regulation(array1, array2) bind(c,name='update_regulation')
! Local variables
integer GridFlag, EmergPitchStop, ActiveMechBrake
integer i
real(mk) GenSpeed, wsp, PitchVect(3), Pe, TT_acc(2), time
real(mk) avg_wsp_lidar,u,v,w ! Lidar assisted control
real(mk) line_of_sight_wsp(4), wsp_lidar(4)
real(mk) ipc_pitch(3);
real(mk) TTfa_vel ! floating
EmergPitchStop = 0
......@@ -779,6 +885,31 @@ subroutine update_regulation(array1, array2) bind(c,name='update_regulation')
!
! Tower fore-aft velocity
TTfa_vel = array1(16)
!
! Lidar assisted control
if (lidar_assisted_control .gt. 0) then
! line of sight velocity
line_of_sight_wsp(1) = array1(17)
line_of_sight_wsp(2) = array1(22)
line_of_sight_wsp(3) = array1(27)
line_of_sight_wsp(4) = array1(32)
! only consider velocity in u-direction
do i = 1,4
u = line_of_sight_wsp(i)/cos(15*degrad)
! v = line_of_sight_wsp(i)/sin(15*degrad)*cos(45*degrad)
! w = line_of_sight_wsp(i)/sin(15*degrad)*sin(45*degrad)
! wsp_lidar(i) = dsqrt(u**2+v**2+w**2)
wsp_lidar(i) = u
enddo
avg_wsp_lidar = (wsp_lidar(1) + wsp_lidar(2) + wsp_lidar(3) + wsp_lidar(4))/4.0_mk
wsp = avg_wsp_lidar
! wsp = dsqrt(array1(7)**2)
if(stepno == 2 .and. compiled_with_debug .and. lidar_assisted_control .gt. 0) then
! write(6,'(7a20)') 'Time [s]','RotorSpeed [rad/s]','PitchAngle [deg]','GenTorq [Nm]','Pe[W]','WSP [m/s]','WSP_Lidar[m/s]'
endif
else
wsp = dsqrt(array1(7)**2)
endif
!
!***********************************************************************************************
! Safety system
......@@ -821,7 +952,7 @@ subroutine update_regulation(array1, array2) bind(c,name='update_regulation')
!***********************************************************************************************
! Output
!***********************************************************************************************
array2( 1) = GenTorqueRef/GearRatio +GenTorque_addition ! 1: Generator torque reference [Nm]
array2( 2) = PitchColRef + ipc_pitch(1) + Pitch_addition ! 2: Pitch angle reference of blade 1 [rad]
array2( 3) = PitchColRef + ipc_pitch(2) + Pitch_addition ! 3: Pitch angle reference of blade 2 [rad]
......@@ -873,6 +1004,19 @@ subroutine update_regulation(array1, array2) bind(c,name='update_regulation')
array2(46) = Floatingvar%TTfa_vel_filt ! 46: Filtered tower-top fore-aft velocity [m/s]
array2(47) = GenTorque_addition ! 47: Generator Torque from additional loop [Nm]
array2(48) = Pitch_addition ! 48: Blade pitch angle from additional loop [rad]
if(lidar_assisted_control .gt. 0) then
array2(49) = GenSpeed*R/wsp ! 49: tip speed ratio at step i[-]
array2(50) = avg_wsp_lidar ! 50: averged velc. measured by Lidar at 1D [-]
else
array2(49) = GenSpeed*R/wsp ! 49: tip speed ratio at step i[-]
array2(50) = 0.0_mk ! 50: averged velc. measured by Lidar at 1D [-]
endif
if((mod(stepno,500) == 0) .and. compiled_with_debug .and. (lidar_assisted_control .gt. 0)) then
! write(6,'(7a20)') 'Time [s]','RotorSpeed [rad/s]','PitchAngle [deg]','GenTorq [Nm]','Pe[W]','WSP [m/s]','WSP_Lidar[m/s]'
! write(6,'(7E20.6)') time, GenSpeed,array2(2)*raddeg, array2(1), array2(1)*GenSpeed, wsp, avg_wsp_lidar
endif
return
end subroutine update_regulation
!**************************************************************************************************
......
......@@ -9,10 +9,16 @@ module global_variables
!DEC$ IF .NOT. DEFINED(__LINUX__)
!DEC$ attributes DLLEXPORT :: pCtrlInputFile
!DEC$ END IF
#ifndef NDEBUG
logical, parameter :: compiled_with_debug = .true.
#else
logical, parameter :: compiled_with_debug = .false.
#endif
! Parameters
logical generator_cutin
integer :: lidar_assisted_control = 0
integer PartialLoadControlMode, stoptype
integer CtrlStatus ! Integer indicating the status of the controller.
! (0: Normal operation, <0: Start-up, >0: Shutdown for different reasons)
......@@ -20,7 +26,7 @@ module global_variables
real(mk) RatedWindSpeed
real(mk) GenSpeedRefMax, GenSpeedRefMin, PeRated, GenTorqueRated, PitchStopAng, GenTorqueMax
real(mk) TTfa_PWR_lower, TTfa_PWR_upper, TorqueCtrlRatio
real(mk) Kopt, Kopt_dot, TSR_opt, R, GearRatio
real(mk) Kopt, Kopt_dot, TSR_opt, R, GearRatio,kgain_lac
real(mk) Vcutout, Vstorm
real(mk) Err0, ErrDot0, PitNonLin1, rel_limit
integer NAve_Pitch
......@@ -91,7 +97,11 @@ module global_variables
type(TcontrolFile), pointer :: pCtrlInputFile
! define global avariables for external 3rd party DLLs
Type (Tdll), save :: external_dll
type (Tdll), save :: external_dll
! Define global avariables for Lidar assisted control
type(TLACData), save :: lac_input_data
type(Tpid2var), save :: PID_lac_pit_var
!**************************************************************************************************
end module global_variables
......
......@@ -178,6 +178,34 @@ module user_defined_types
integer :: fileID,lineNumber=0
end type TcontrolFile
! Additional input data type for Lidar Assisted Control
type TLidarData
character(len=32) :: name = '4beam'
real(mk) :: alpha ! Half-cone opening angle of beam [deg]
real(mk) :: beta ! Azimuth angle of beam measured (clockwise as seen from turbine)
! from vertical up postion [deg]
real(mk) :: Lf ! Focus length measured from rotor center (along the beam) [m]
real(mk) :: Gamma ! Rayleigh length of beam [m]
real(mk) :: M ! half-width of integration interval of Lorentzian [Gamma]
! i.e. Lorentzian (centered at focus point) will be truncated at +-M*Gamma
real(mk) :: vLOS ! line of sight velociy
end type TLidarData
type TLACData
character(len=32) :: name ! file name of the lidar assisted control input file
integer :: lines ! number of lines
integer :: mode = 0 ! lidar assisted control mode
real(mk) :: gain_oat, kp_ott_pitch, ki_ott_pitch, cp_opt, k_opt_wsp, tsr_opt, kp_ott_torq, ki_ott_torq
real(mk) :: pitch_min = -2.0_mk, pitch_max = 4.0_mk
real(mk), dimension(:), allocatable :: data_val
character(len=32), dimension(:), allocatable :: data_name
type(Tfirstordervar) :: lac_firstorder_lp_var
type(Tlowpass2order) :: lac_secondorder_lp_var
type(TLidarData) :: nacelle_lidar
end type TLACData
! IO data type
type Tline
character*512 :: line
......
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