Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error catching #46

Merged
merged 28 commits into from
Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9c523dd
testing initial commit
nikhar-abbas Mar 29, 2021
f20dcdb
update compilers
nikhar-abbas Mar 29, 2021
05786d0
remove default shell
nikhar-abbas Mar 29, 2021
64a754f
use conda environment
nikhar-abbas Mar 29, 2021
9d3f2c0
mingw flag
nikhar-abbas Mar 30, 2021
e2eab81
pr template - initial commit
nikhar-abbas Mar 30, 2021
37838fb
Add error variables, error catching for interp functions
dzalkind Apr 5, 2021
d5b7a4f
Expand Assert function and rename to CheckInputs
dzalkind Apr 13, 2021
d12fbc1
Parse integer inputs, update CheckInputs
dzalkind Apr 16, 2021
f928868
Add double and string input parsing
dzalkind Apr 20, 2021
365d820
Merge pull request #41 from nikhar-abbas/f/ci_tests
nikhar-abbas Apr 21, 2021
a275d37
Fix setpoint smoother to use last gen pwr (#43)
nikhar-abbas Apr 22, 2021
22b6508
Generator power in SS (#44)
nikhar-abbas Apr 22, 2021
df32a55
Add array parsing, debug outputting, fix long string reading
dzalkind May 7, 2021
d0fe8b1
Clean up array parsing
dzalkind May 7, 2021
039389a
Make Flp and Fl filter variables consistent with others
dzalkind May 7, 2021
97c7bcf
Parse all double arrays, only read/parse lines if no error
dzalkind May 7, 2021
05879d5
Parse integer arrays
dzalkind May 7, 2021
8fdeeca
Read Cp surface
dzalkind May 10, 2021
7fbfb86
Reorganize ROSCO file reading code
dzalkind May 17, 2021
c88f272
Make error tracing consistent: RoutineNames
dzalkind May 17, 2021
008d34a
Finish making error tracing consistent
dzalkind May 17, 2021
ce0510b
Use unsaturated pitch command in setpoint smoother (#45)
nikhar-abbas May 25, 2021
398cb42
Don't check WE_CP, FA_HPFCornerFreq until API change
dzalkind May 27, 2021
d5963fd
Remove check on F_NotchBetaNumDen(1), not necessary
dzalkind May 27, 2021
6729e9f
Re-organize ReadSetParameters
dzalkind May 27, 2021
4ff5ad3
Merge remote-tracking branch 'upstream/develop' into error_catching
dzalkind May 27, 2021
8f0a93c
Fix controller-breaking typo
dzalkind May 27, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## Description and Purpose

## Type of change
What types of change is it?
_Select the appropriate type(s) that describe this PR_

- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (non-backwards-compatible fix or feature)
- [ ] Code style update (formatting, renaming)
- [ ] Refactoring (no functional changes, no API changes)
- [ ] Documentation update
- [ ] Maintenance update
- [ ] Other (please describe)

## Github issues addressed, if one exists

## Examples/Testing, if applicable


62 changes: 62 additions & 0 deletions .github/workflows/CI_rosco.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: CI_rosco-toolbox

# We run CI on push commits on all branches
on: [push, pull_request]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
name: Build (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: ["ubuntu-latest", "macOS-latest", "windows-latest"]
python-version: ["3.8"]

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Setup environment
uses: conda-incubator/setup-miniconda@v2
with:
miniconda-version: "latest"
channels: conda-forge, general
auto-update-conda: true
python-version: 3.8
environment-file: environment.yml

# Install compilers
- name: Add dependencies linux
if: false == contains( matrix.os, 'windows')
shell: pwsh
run: |
conda install -y compilers

- name: Add dependencies windows
if: true == contains( matrix.os, 'windows')
shell: bash -l {0}
run: |
conda install -y m2w64-toolchain

# Install ROSCO linux
- name: Compile ROSCO linux
if: false == contains( matrix.os, 'windows')
shell: pwsh
run: |
mkdir build
cd build
cmake ..
make install

# Install ROSCO windows
- name: Compile ROSCO windows
if: true == contains( matrix.os, 'windows')
shell: pwsh
run: |
mkdir build
cd build
cmake .. -G "MinGW Makefiles"
make install

3 changes: 3 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
channels:
- conda-forge
- defaults
1 change: 1 addition & 0 deletions src/Constants.f90
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ MODULE Constants
REAL(8), PARAMETER :: PI = 3.14159265359 ! Mathematical constant pi
INTEGER(4), PARAMETER :: NP_1 = 1 ! First rotational harmonic
INTEGER(4), PARAMETER :: NP_2 = 2 ! Second rotational harmonic
CHARACTER(*), PARAMETER :: NewLine = ACHAR(10) ! The delimiter for New Lines [ Windows is CHAR(13)//CHAR(10); MAC is CHAR(13); Unix is CHAR(10) {CHAR(13)=\r is a line feed, CHAR(10)=\n is a new line}]
END MODULE Constants
108 changes: 98 additions & 10 deletions src/ControllerBlocks.f90
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,71 @@ MODULE ControllerBlocks
IMPLICIT NONE

CONTAINS
! -----------------------------------------------------------------------------------
! Calculate setpoints for primary control actions
SUBROUTINE ComputeVariablesSetpoints(CntrPar, LocalVar, objInst)
USE ROSCO_Types, ONLY : ControlParameters, LocalVariables, ObjectInstances
USE Constants
! Allocate variables
TYPE(ControlParameters), INTENT(INOUT) :: CntrPar
TYPE(LocalVariables), INTENT(INOUT) :: LocalVar
TYPE(ObjectInstances), INTENT(INOUT) :: objInst

REAL(8) :: VS_RefSpd ! Referece speed for variable speed torque controller, [rad/s]
REAL(8) :: PC_RefSpd ! Referece speed for pitch controller, [rad/s]
REAL(8) :: Omega_op ! Optimal TSR-tracking generator speed, [rad/s]
! temp
! REAL(8) :: VS_TSRop = 7.5

! ----- Calculate yaw misalignment error -----
LocalVar%Y_MErr = LocalVar%Y_M + CntrPar%Y_MErrSet ! Yaw-alignment error

! ----- Pitch controller speed and power error -----
! Implement setpoint smoothing
IF (LocalVar%SS_DelOmegaF < 0) THEN
PC_RefSpd = CntrPar%PC_RefSpd - LocalVar%SS_DelOmegaF
ELSE
PC_RefSpd = CntrPar%PC_RefSpd
ENDIF

LocalVar%PC_SpdErr = PC_RefSpd - LocalVar%GenSpeedF ! Speed error
LocalVar%PC_PwrErr = CntrPar%VS_RtPwr - LocalVar%VS_GenPwr ! Power error

! ----- Torque controller reference errors -----
! Define VS reference generator speed [rad/s]
IF ((CntrPar%VS_ControlMode == 2) .OR. (CntrPar%VS_ControlMode == 3)) THEN
VS_RefSpd = (CntrPar%VS_TSRopt * LocalVar%We_Vw_F / CntrPar%WE_BladeRadius) * CntrPar%WE_GearboxRatio
VS_RefSpd = saturate(VS_RefSpd,CntrPar%VS_MinOMSpd, CntrPar%VS_RefSpd)
ELSE
VS_RefSpd = CntrPar%VS_RefSpd
ENDIF

! Implement setpoint smoothing
IF (LocalVar%SS_DelOmegaF > 0) THEN
VS_RefSpd = VS_RefSpd - LocalVar%SS_DelOmegaF
ENDIF

! Force zero torque in shutdown mode
IF (LocalVar%SD) THEN
VS_RefSpd = CntrPar%VS_MinOMSpd
ENDIF

! Force minimum rotor speed
VS_RefSpd = max(VS_RefSpd, CntrPar%VS_MinOmSpd)

! TSR-tracking reference error
IF ((CntrPar%VS_ControlMode == 2) .OR. (CntrPar%VS_ControlMode == 3)) THEN
LocalVar%VS_SpdErr = VS_RefSpd - LocalVar%GenSpeedF
ENDIF

! Define transition region setpoint errors
LocalVar%VS_SpdErrAr = VS_RefSpd - LocalVar%GenSpeedF ! Current speed error - Region 2.5 PI-control (Above Rated)
LocalVar%VS_SpdErrBr = CntrPar%VS_MinOMSpd - LocalVar%GenSpeedF ! Current speed error - Region 1.5 PI-control (Below Rated)

! Region 3 minimum pitch angle for state machine
LocalVar%VS_Rgn3Pitch = LocalVar%PC_MinPit + CntrPar%PC_Switch

END SUBROUTINE ComputeVariablesSetpoints
!-------------------------------------------------------------------------------------------------------------------------------
SUBROUTINE StateMachine(CntrPar, LocalVar)
! State machine, determines the state of the wind turbine to specify the corresponding control actions
Expand Down Expand Up @@ -101,11 +166,11 @@ SUBROUTINE StateMachine(CntrPar, LocalVar)
END IF
END SUBROUTINE StateMachine
!-------------------------------------------------------------------------------------------------------------------------------
SUBROUTINE WindSpeedEstimator(LocalVar, CntrPar, objInst, PerfData, DebugVar)
SUBROUTINE WindSpeedEstimator(LocalVar, CntrPar, objInst, PerfData, DebugVar, ErrVar)
! Wind Speed Estimator estimates wind speed at hub height. Currently implements two types of estimators
! WE_Mode = 0, Filter hub height wind speed as passed from servodyn using first order low pass filter with 1Hz cornering frequency
! WE_Mode = 1, Use Inversion and Inveriance filter as defined by Ortege et. al.
USE ROSCO_Types, ONLY : LocalVariables, ControlParameters, ObjectInstances, PerformanceData, DebugVariables
USE ROSCO_Types, ONLY : LocalVariables, ControlParameters, ObjectInstances, PerformanceData, DebugVariables, ErrorVariables
IMPLICIT NONE

! Inputs
Expand All @@ -114,6 +179,8 @@ SUBROUTINE WindSpeedEstimator(LocalVar, CntrPar, objInst, PerfData, DebugVar)
TYPE(ObjectInstances), INTENT(INOUT) :: objInst
TYPE(PerformanceData), INTENT(INOUT) :: PerfData
TYPE(DebugVariables), INTENT(INOUT) :: DebugVar
TYPE(ErrorVariables), INTENT(INOUT) :: ErrVar

! Allocate Variables
REAL(8) :: F_WECornerFreq ! Corner frequency (-3dB point) for first order low pass filter for measured hub height wind speed [Hz]

Expand Down Expand Up @@ -143,6 +210,9 @@ SUBROUTINE WindSpeedEstimator(LocalVar, CntrPar, objInst, PerfData, DebugVar)
REAL(8) :: R_m ! Measurement noise covariance [(rad/s)^2]

REAL(8), DIMENSION(3,1), SAVE :: B

CHARACTER(*), PARAMETER :: RoutineName = 'WindSpeedEstimator'

! ---- Debug Inputs ------
DebugVar%WE_b = LocalVar%PC_PitComTF*R2D
DebugVar%WE_w = LocalVar%RotSpeedF
Expand All @@ -152,7 +222,10 @@ SUBROUTINE WindSpeedEstimator(LocalVar, CntrPar, objInst, PerfData, DebugVar)

! Inversion and Invariance Filter implementation
IF (CntrPar%WE_Mode == 1) THEN
LocalVar%WE_VwIdot = CntrPar%WE_Gamma/CntrPar%WE_Jtot*(LocalVar%VS_LastGenTrq*CntrPar%WE_GearboxRatio - AeroDynTorque(LocalVar, CntrPar, PerfData))
! Compute AeroDynTorque
Tau_r = AeroDynTorque(LocalVar, CntrPar, PerfData, ErrVar)

LocalVar%WE_VwIdot = CntrPar%WE_Gamma/CntrPar%WE_Jtot*(LocalVar%VS_LastGenTrq*CntrPar%WE_GearboxRatio - Tau_r)
LocalVar%WE_VwI = LocalVar%WE_VwI + LocalVar%WE_VwIdot*LocalVar%DT
LocalVar%WE_Vw = LocalVar%WE_VwI + CntrPar%WE_Gamma*LocalVar%RotSpeedF

Expand Down Expand Up @@ -180,11 +253,13 @@ SUBROUTINE WindSpeedEstimator(LocalVar, CntrPar, objInst, PerfData, DebugVar)

ELSE
! Find estimated operating Cp and system pole
A_op = interp1d(CntrPar%WE_FOPoles_v,CntrPar%WE_FOPoles,v_h)
A_op = interp1d(CntrPar%WE_FOPoles_v,CntrPar%WE_FOPoles,v_h,ErrVar)

! TEST INTERP2D
lambda = LocalVar%RotSpeed * CntrPar%WE_BladeRadius/v_h
Cp_op = interp2d(PerfData%Beta_vec,PerfData%TSR_vec,PerfData%Cp_mat, LocalVar%BlPitch(1)*R2D, lambda )

Cp_op = interp2d(PerfData%Beta_vec,PerfData%TSR_vec,PerfData%Cp_mat, LocalVar%BlPitch(1)*R2D, lambda, ErrVar)

Cp_op = max(0.0,Cp_op)

! Update Jacobian
Expand All @@ -200,7 +275,7 @@ SUBROUTINE WindSpeedEstimator(LocalVar, CntrPar, objInst, PerfData, DebugVar)
Q(3,3) = (2.0**2.0)/600.0

! Prediction update
Tau_r = AeroDynTorque(LocalVar,CntrPar,PerfData)
Tau_r = AeroDynTorque(LocalVar, CntrPar, PerfData, ErrVar)
a = PI * v_m/(2.0*L)
dxh(1,1) = 1.0/CntrPar%WE_Jtot * (Tau_r - CntrPar%WE_GearboxRatio * LocalVar%VS_LastGenTrqF)
dxh(2,1) = -a*v_t
Expand Down Expand Up @@ -236,6 +311,11 @@ SUBROUTINE WindSpeedEstimator(LocalVar, CntrPar, objInst, PerfData, DebugVar)
LocalVar%WE_Vw = LPFilter(LocalVar%HorWindV, LocalVar%DT, F_WECornerFreq, LocalVar%iStatus, .FALSE., objInst%instLPF)
ENDIF

! Add RoutineName to error message
IF (ErrVar%aviFAIL < 0) THEN
ErrVar%ErrMsg = RoutineName//':'//TRIM(ErrVar%ErrMsg)
ENDIF

END SUBROUTINE WindSpeedEstimator
!-------------------------------------------------------------------------------------------------------------------------------
SUBROUTINE SetpointSmoother(LocalVar, CntrPar, objInst)
Expand All @@ -255,7 +335,7 @@ SUBROUTINE SetpointSmoother(LocalVar, CntrPar, objInst)
! ------ Setpoint Smoothing ------
IF ( CntrPar%SS_Mode == 1) THEN
! Find setpoint shift amount
DelOmega = ((LocalVar%PC_PitComT - CntrPar%PC_MinPit)/0.524) * CntrPar%SS_VSGain - ((LocalVar%VS_GenPwr - LocalVar%VS_LastGenTrq))/CntrPar%VS_RtPwr * CntrPar%SS_PCGain ! Normalize to 30 degrees for now
DelOmega = ((LocalVar%PC_PitComT - LocalVar%PC_MinPit)/0.524) * CntrPar%SS_VSGain - ((CntrPar%VS_RtPwr - LocalVar%VS_LastGenPwr))/CntrPar%VS_RtPwr * CntrPar%SS_PCGain ! Normalize to 30 degrees for now
DelOmega = DelOmega * CntrPar%PC_RefSpd
! Filter
LocalVar%SS_DelOmegaF = LPFilter(DelOmega, LocalVar%DT, CntrPar%F_SSCornerFreq, LocalVar%iStatus, .FALSE., objInst%instLPF)
Expand All @@ -265,20 +345,28 @@ SUBROUTINE SetpointSmoother(LocalVar, CntrPar, objInst)

END SUBROUTINE SetpointSmoother
!-------------------------------------------------------------------------------------------------------------------------------
REAL FUNCTION PitchSaturation(LocalVar, CntrPar, objInst, DebugVar)
REAL FUNCTION PitchSaturation(LocalVar, CntrPar, objInst, DebugVar, ErrVar)
! PitchSaturation defines a minimum blade pitch angle based on a lookup table provided by DISCON.IN
! SS_Mode = 0, No setpoint smoothing
! SS_Mode = 1, Implement pitch saturation
USE ROSCO_Types, ONLY : LocalVariables, ControlParameters, ObjectInstances, DebugVariables
USE ROSCO_Types, ONLY : LocalVariables, ControlParameters, ObjectInstances, DebugVariables, ErrorVariables
IMPLICIT NONE
! Inputs
TYPE(ControlParameters), INTENT(IN) :: CntrPar
TYPE(LocalVariables), INTENT(INOUT) :: LocalVar
TYPE(ObjectInstances), INTENT(INOUT) :: objInst
TYPE(DebugVariables), INTENT(INOUT) :: DebugVar
TYPE(ErrorVariables), INTENT(INOUT) :: ErrVar

CHARACTER(*), PARAMETER :: RoutineName = 'PitchSaturation'

! Define minimum blade pitch angle as a function of estimated wind speed
PitchSaturation = interp1d(CntrPar%PS_WindSpeeds, CntrPar%PS_BldPitchMin, LocalVar%WE_Vw_F)
PitchSaturation = interp1d(CntrPar%PS_WindSpeeds, CntrPar%PS_BldPitchMin, LocalVar%WE_Vw_F, ErrVar)

! Add RoutineName to error message
IF (ErrVar%aviFAIL < 0) THEN
ErrVar%ErrMsg = RoutineName//':'//TRIM(ErrVar%ErrMsg)
ENDIF

END FUNCTION PitchSaturation
!-------------------------------------------------------------------------------------------------------------------------------
Expand Down
Loading