Skip to content

Commit

Permalink
Add open loop control of StCs
Browse files Browse the repository at this point in the history
  • Loading branch information
dzalkind committed Jul 7, 2023
1 parent 53d097c commit 02fea3e
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 13 deletions.
56 changes: 47 additions & 9 deletions Examples/23_structural_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@
import numpy as np
from ROSCO_toolbox.ofTools.fast_io.FAST_reader import InputReader_OpenFAST
from ROSCO_toolbox.inputs.validation import load_rosco_yaml
from ROSCO_toolbox.controller import OpenLoopControl


'''
ROSCO currently supports user-defined hooks for structural control control actuation, if StC_Mode = 1.
The control logic can be determined in Controllers.f90 with the StructrualControl subroutine.
In the DISCON input, users must specify StC_GroupIndex relating to the control ChannelID.
These indices can be found in the ServoDyn summary file (*SrvD.sum)
In the example below (and hard-coded in ROSCO) a step change of -4e5 N on the first structural controller
is applied at 50 sec.
In the example below, we implement a smooth step change mimicing the exchange of ballast from the
upwind column to the down wind columns
The develop branch (as of Mar 3, 2023) of OpenFAST (v3.5.0, upcoming) is required to run this example
OpenFAST v3.5.0 is required to run this example
'''


Expand All @@ -45,7 +47,7 @@ def main():

# Input yaml and output directory
parameter_filename = os.path.join(rosco_dir,'Tune_Cases/IEA15MW_ballast.yaml')
run_dir = os.path.join(example_out_dir,'23_structural_control')
run_dir = os.path.join(example_out_dir,'23_structural_control_OL_2')
os.makedirs(run_dir,exist_ok=True)

# Read initial input file
Expand All @@ -65,6 +67,41 @@ def main():
for StC_file in reader.fst_vt['ServoDyn']['SStCfiles']:
reader.fst_vt['SStC'].append(reader.read_StC(StC_file))

# Set up open loop inputs to ROSCO
t_trans = 60
t_sigma = 80
t_max = 200

applied_force = [-2e6, 1e6, 1e6]

olc = OpenLoopControl(t_max=t_max)
olc.interp_timeseries(
'struct_control_1',
[0,t_trans,t_trans+t_sigma],
[0,0,applied_force[0]] ,
'sigma'
)

olc.interp_timeseries(
'struct_control_2',
[0,t_trans,t_trans+t_sigma],
[0,0,applied_force[1]] ,
'sigma'
)

olc.interp_timeseries(
'struct_control_3',
[0,t_trans,t_trans+t_sigma],
[0,0,applied_force[2]] ,
'sigma'
)


ol_params = olc.write_input(os.path.join(run_dir,'open_loop_ballast.dat'))

controller_params = {}
controller_params['open_loop'] = ol_params
controller_params['StC_Mode'] = 2

# simulation set up
r = run_FAST_ROSCO()
Expand All @@ -73,16 +110,17 @@ def main():
r.wind_case_fcn = cl.power_curve
r.wind_case_opts = {
'U': [9],
'T_max': 100,
'TMax': t_max,
}
r.case_inputs = {}
r.fst_vt = reader.fst_vt
r.save_dir = run_dir
r.rosco_dir = rosco_dir
r.fst_vt = reader.fst_vt
r.save_dir = run_dir
r.rosco_dir = rosco_dir
r.controller_params = controller_params
r.openfast_exe = '/Users/dzalkind/opt/anaconda3/envs/rosco-env/bin/openfast'

r.run_FAST()



if __name__=="__main__":
main()
34 changes: 31 additions & 3 deletions ROSCO/src/Controllers.f90
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,8 @@ SUBROUTINE CableControl(avrSWAP, CntrPar, LocalVar, objInst, ErrVar)

! Internal Variables
Integer(IntKi) :: I_GROUP
CHARACTER(*), PARAMETER :: RoutineName = 'StructuralControl'



IF (CntrPar%CC_Mode == 1) THEN
Expand Down Expand Up @@ -751,31 +753,40 @@ SUBROUTINE CableControl(avrSWAP, CntrPar, LocalVar, objInst, ErrVar)

END DO

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

END SUBROUTINE CableControl

!-------------------------------------------------------------------------------------------------------------------------------
SUBROUTINE StructuralControl(avrSWAP, CntrPar, LocalVar, objInst)
SUBROUTINE StructuralControl(avrSWAP, CntrPar, LocalVar, objInst, ErrVar)
! Cable controller
! StC_Mode = 0, No cable control, this code not executed
! StC_Mode = 1, User-defined cable control
! StC_Mode = 2, Ballast-like control, not yet implemented
!
! Note that LocalVar%StC_Input() has a fixed max size of 12, which can be increased in rosco_types.yaml
!
USE ROSCO_Types, ONLY : ControlParameters, LocalVariables, ObjectInstances
USE ROSCO_Types, ONLY : ControlParameters, LocalVariables, ObjectInstances, ErrorVariables

REAL(ReKi), INTENT(INOUT) :: avrSWAP(*) ! The swap array, used to pass data to, and receive data from, the DLL controller.

TYPE(ControlParameters), INTENT(INOUT) :: CntrPar
TYPE(LocalVariables), INTENT(INOUT) :: LocalVar
TYPE(ObjectInstances), INTENT(INOUT) :: objInst
TYPE(ErrorVariables), INTENT(INOUT) :: ErrVar


! Internal Variables
Integer(IntKi) :: I_GROUP
CHARACTER(*), PARAMETER :: RoutineName = 'StructuralControl'



IF (CntrPar%StC_Mode == 1) THEN
! User defined control
! User defined control, step example

IF (LocalVar%Time > 500) THEN
! Step change in input of -4500 N
Expand All @@ -786,6 +797,18 @@ SUBROUTINE StructuralControl(avrSWAP, CntrPar, LocalVar, objInst)
END IF


ELSEIF (CntrPar%StC_Mode == 2) THEN


DO I_GROUP = 1,CntrPar%StC_Group_N
IF (CntrPar%Ind_StructControl(I_GROUP) > 0) THEN
LocalVar%StC_Input(I_GROUP) = interp1d(CntrPar%OL_Breakpoints, &
CntrPar%OL_StructControl(I_GROUP,:), &
LocalVar%Time,ErrVar)
ENDIF
ENDDO



END IF

Expand All @@ -795,6 +818,11 @@ SUBROUTINE StructuralControl(avrSWAP, CntrPar, LocalVar, objInst)
avrSWAP(CntrPar%StC_GroupIndex(I_GROUP)) = LocalVar%StC_Input(I_GROUP)
END DO

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

END SUBROUTINE StructuralControl
!-------------------------------------------------------------------------------------------------------------------------------
END MODULE Controllers
2 changes: 1 addition & 1 deletion ROSCO/src/DISCON.F90
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ SUBROUTINE DISCON(avrSWAP, aviFAIL, accINFILE, avcOUTNAME, avcMSG) BIND (C, NAME

! Structural control
IF (CntrPar%StC_Mode > 0) THEN
CALL StructuralControl(avrSWAP,CntrPar,LocalVar, objInst)
CALL StructuralControl(avrSWAP,CntrPar,LocalVar, objInst, ErrVar)
END IF

IF ( CntrPar%LoggingLevel > 0 ) THEN
Expand Down

0 comments on commit 02fea3e

Please sign in to comment.