3. ROSCO Examples

Methods for reading turbine models, generating the control parameters of a DISCON.IN: file, and running aeroelastic simulations to test controllers Reading Turbine Models ———————- Control parameters depend on the turbine model. The rosco.toolbox uses OpenFAST inputs and an additional .yaml formatted file to set up a turbine object in python. Several OpenFAST inputs are located in Test_Cases/. The controller tuning .yaml are located in Tune_Cases/. A detailed description of the ROSCO control inputs and tuning .yaml are provided in The DISCON.IN file and ROSCO_Toolbox tuning .yaml, respectively.

  • 01_turbine_model.py loads an OpenFAST turbine model and displays a summary of its information

ROSCO requires the power and thrust coefficients for tuning control inputs and running the extended Kalman filter wind speed estimator.

  • 02_ccblade.py runs cc-blade, a blade element momentum solver from WISDEM, to generate a \(C_p\) surface.

The Cp_Cq_Ct.txt (or similar) file contains the rotor performance tables that are necessary to run the ROSCO controller. This file can be located wherever you desire, just be sure to point to it properly with the PerfFileName parameter in DISCON.IN.

3.1. Tuning Controllers and Generating DISCON.IN

The ROSCO turbine object, which contains turbine information required for controller tuning, along with control parameters in the tuning yaml and the \(C_p\) surface are used to generate control parameters and DISCON.IN files. To tune the PI gains of the torque control, set omega_vs and zeta_vs in the yaml. Similarly, set omega_pc and zeta_pc to tune the PI pitch controller; gain scheduling is automatically handled using turbine information. Generally omega_* increases the responsiveness of the controller, reducing generator speed variations, but an also increases loading on the turbine. zeta_* changes the damping of the controller and is generally less important of a tuning parameter, but could also help with loading. The default parameters in Tune_Cases/ are known to work well with the turbines in this repository.

  • 03_tune_controller.py loads a turbine and tunes the PI control gains

  • 04_simple_sim.py tunes a controller and runs a simple simualtion (not using OpenFAST)

  • 05_openfast_sim.py loads a turbine, tunes a controller, and runs an OpenFAST simulation

Each of these examples generates a DISCON.IN file, which is an input to libdiscon.*. When running the controller in OpenFAST, DISCON.IN must be appropriately named using the DLL_FileName parameter in ServoDyn.

OpenFAST can be installed from source or in a conda environment using:

conda install -c conda-forge openfast

ROSCO can implement peak shaving (or thrust clipping) by changing the minimum pitch angle based on the estimated wind speed:

  • 06_peak_shaving.py loads a turbine and tunes a controller with peak shaving.

By setting the ps_percent value in the tuning yaml, the minimum pitch versus wind speed table changes and is updated in the DISCON.IN file.

ROSCO also contains a method for distributed aerodynamic control (e.g., via trailing edge flaps):

  • 09_distributed_aero.py tunes a controller for distributed aerodynamic control

The ROSCO toolbox also contains methods for working with OpenFAST linear models * 10_linear_params.py exports a file of the parameters used for the simplified linear models used to tune ROSCO * 11_robust_tuning.py shows how linear models generated using OpenFAST can be used to tune controllers with robust stability properties. * 12_tune_ipc.py shows the tuning procedure for IPC

3.2. Running OpenFAST Simulations

To run an aeroelastic simulation with ROSCO, the ROSCO input (DISCON.IN) must point to a properly formatted Cp_Cq_Ct.txt file using the PerfFileName parameter. If called from OpenFAST, the main OpenFAST input points to the ServoDyn input, which points to the DISCON.IN file and the libdiscon.* dynamic library.

For example in Test_Cases/NREL-5MW:

  • NREL-5MW.fst has "NRELOffshrBsline5MW_Onshore_ServoDyn.dat" as the ServoFile input

  • NRELOffshrBsline5MW_Onshore_ServoDyn.dat has "../../ROSCO/build/libdiscon.dylib" as the DLL_FileName input and "DISCON.IN" as the DLL_InFile input. Note that these file paths are relative to the path of the main fast input (NREL-5MW.fst)

  • DISCON.IN has "Cp_Ct_Cq.NREL5MW.txt" as the PerfFileName input

The rosco.toolbox has methods for running OpenFAST (and other) binary executables using system calls, as well as post-processing tools in ofTools/.

Several example scripts are set up to quickly simulate ROSCO with OpenFAST:

  • 05_openfast_sim.py loads a turbine, tunes a controller, and runs an OpenFAST simulation

  • 07_openfast_outputs.py loads the OpenFAST output files and plots the results

  • 14_open_loop_control.py runs an OpenFAST simulation with ROSCO providing open loop control inputs

3.3. Testing ROSCO

The rosco.toolbox also contains tools for testing ROSCO in IEC design load cases (DLCs), located in ROSCO_testing/. The script run_Testing.py allows the user to set up their own set of tests. By setting testtype, the user can run a variety of tests:

  • lite, which runs DLC 1.1 simulations at 5 wind speed from cut-in to cut-out, in 330 second simulations

  • heavy, which runs DLC 1.3 from cut-in to cut-out in 2 m/s steps and 2 seeds for each, in 630 seconds, as well as DLC 1.4 simulations

  • binary-comp, where the user can compare libdiscon.* dynamic libraries (compiled ROSCO source code), with either a lite or heavy set of simulations

  • discon-comp, where the user can compare DISCON.IN controller tunings (and the complied ROSCO source is constant)

Setting the turbine2test allows the user to test either the IEA-15MW with the UMaine floating semisubmersible or the NREL-5MW reference onshore turbine.

3.4. List of Examples

A complete list of examples is given below:

3.4.1. 01_turbine_model

Interact with a ROSCO turbine model:

  • Read .yaml input file

  • Load an openfast turbine model

  • Read text file with rotor performance properties (Cp, Ct, and Cq surface)

  • Print some basic turbine properties

  • Save the turbine as a pickle

  • Plot the Cp surface

../_images/01_NREL5MW_Cp.png

Note: Uses the NREL 5MW included in the Test Cases and is a part of the OpenFAST distribution

3.4.2. 02_ccblade

Run CCblade, save a rotor performance text file. In this example:

  • Read .yaml input file

  • Load an openfast turbine model

  • Run ccblade to get rotor performance properties

  • Write a text file ('02_Cp_Ct_Cq.Ex03.txt') with rotor performance properties

3.4.3. 03_tune_controller

Load a turbine model and tune the controller In this example:

  • Read a .yaml file

  • Create a ROSCO turbine object fromt he OpenFAST model

  • Tune a ROSCO controller object

  • Write a controller input file ('03_DISCON.IN')

  • Plot gain schedule (PC_GS_KP and PC_GS_KI versus PS_GS_angles):

../_images/03_GainSched.png

3.4.4. 04_simple_sim

Demonstrate the simple 1-DOF wind turbine simulator with ROSCO

In this example:

  • Load turbine from saved pickle and tune a ROSCO controller

  • Run and plot a step wind simulation using 1-DOF model in rosco.toolbox.sim and the ROSCO dynamic library

../_images/03_GainSched.png

Notes:

  • You must have a compiled controller in ROSCO/rosco/lib/, and properly point to it using the lib_name variable.

  • Using wind speed estimators in this simple simulation is known to cause problems. We suggest using WE_Mode = 0 in the DISCON.IN or increasing sampling rate of simulation as workarounds.

  • The simple simulation is run twice to check that arrays are deallocated properly.

3.4.5. 05_openfast_sim

Load a turbine, tune a controller, and run an OpenFAST simulation. In this example:

  • Load a turbine from OpenFAST

  • Tune a controller

  • Run an OpenFAST simulation

Note

  • You must have a compiled controller in ROSCO/rosco/lib/

3.4.6. 06_peak_shaving

This example demonstrates the minimum pitch schedule of the NREL 5MW RWT. In the ROSCO controller, the minimum pitch is determined from a lookup table from the (estimated) wind speed to the limit. The ROSCO DISCON controller only has PS_Mode of 0 (disable) or 1 (enabled).

When creating a DISCON using the ROSCO toolbox, a few more options are available. For PS_Mode = 1, the minimum pitch limit is calculated to limit the maximum thrust to a fraction of the un-limited maximum thrust, computed from the rotor’s Ct table. The ps_percent input (to the tuning yaml) is the fraction of the allowed thrust to the maximum, un-limited thrust. For example, if the maximum thrust is 1e5 N, and we want to limite the maximum thrust to 8e4 N, ps_percent = 0.8. Note that “percent” is a bit of a misnomer.

For PS_Mode = 2, the minimum pitch limit is calculated to maximize the Cp surface in below rated; this usually results in a non-zero pitch at low wind speeds. For large rotors, sometimes a minimum rotor speed is enforced to avoid resonance between the rotor period and the tower natural frequency; this results in a non-constant TSR across the below-rated operating points. In this case, different pitch angles will be required to maximize Cp.

For PS_Mode = 3, both the thrust limiting and the power maximizing tuning routines determine the minimum pitch limit. This example demonstrates PS_Mode = 3 as follows, compared to the steady state blade pitch operating points of the turbine. The ROSCO toolbox uses Cp and Ct tables to compute these inputs to the ROSCO controller.

../_images/06_MinPitch.png

3.4.7. 07_openfast_outputs

Demonstrate the ROSCO routines for reading OpenFAST I/O files. Nearly all the figures in the example documentation rely on a version of these scripts, which can also be used to load ROSCO .dbg files, including

# .dbg files output basic ROSCO internal variables, like the inputs and outputs to the wind speed estimator # .dbg2 files output all the ROSCO LocalVariables. If the variable is an array, only the first entry is recorded. # .dbg3 files output the avrSWAP array at each timestep that is transfered between ROSCO and the multi-physics solver

Note: this example relies on the previous running of the OpenFAST model in ‘Test_Cases/NREL-5MW/’ to plot.

3.4.8. 09_distributed_aero

Tune a controller for distributed aerodynamic control In this example:

  • Read .yaml input file

  • Load an openfast turbine model

  • Read text file with rotor performance properties

  • Load blade information

  • Tune controller with flap actuator

Note

  • You will need a turbine model with DAC capabilites in order to run this. The curious user can contact Nikhar Abbas (nikhar.abbas@nrel.gov) for available models, if they do not have any themselves.

3.4.9. 10_linear_params

Load a turbine, tune a controller, export linear model In this example:

  • Load a turbine from OpenFAST

  • Tune a controller

  • Use tuning parameters to export linear model

3.4.10. 11_robust_tuning

Controller tuning to satisfy a robustness criteria

Note that this example necessitates the mbc3 through either pyFAST or WEIS pyFAST is the easiest to install by cloning https://github.com/OpenFAST/openfast_toolbox and running python setup.py develop from your conda environment

In this example:

  • setup ROSCO’s robust tuning methods for the IEA15MW on the UMaine Semi-sub

  • run a the standard tuning method to find k_float

  • run robust tuning to find omega_pc schedule satisfy a prescribed stability margin

  • Tune ROSCO’s pitch controller using omega_pc schedule

  • Plot gain schedule

The example is put in a function call to show the ability to load linear models in parallel

3.4.11. 12_tune_ipc

Load a turbine, tune a controller with IPC In this example:

  • Load a turbine from OpenFAST

  • Tune a controller with IPC

  • Run simple simulation with open loop control

3.4.12. 14_open_loop_control

Load a turbine, tune a controller with open loop control commands In this example:

  • Load a turbine from OpenFAST

  • Tune a controller

  • Write open loop inputs

  • Run simple simulation with open loop control

3.4.13. 15_pass_through

Use the runFAST scripts to set up an example, use pass through in yaml In this example:

  • use run_FAST_ROSCO class to set up a test case

3.4.14. 16_external_dll

Run openfast with ROSCO and external control interface IEA-15MW will call NREL-5MW controller and read control inputs

3.4.15. 17a_zeromq_simple

Run ROSCO using the ROSCO toolbox control interface and execute communication with ZeroMQ.

A demonstrator for ZeroMQ communication. Instead of using ROSCO with with control interface, one could call ROSCO from OpenFAST, and communicate with ZeroMQ through that. this_dir

3.4.16. 17b_zeromq_multi_openfast

Run multiple openfast simulations and execute communication with ZeroMQ.

3.4.17. 17c_zeromq_fastfarm

This example demonstrates the wind farm controls capability of ROSCO using ZeroMQ based communication with a FAST.Farm simulation.

Note that in order to use the wind farm control capability of ROSCO, the ZMQ_Mode must be set to 1 and unique identifiers must be set under ZMQ_ID for each turbine in the :code. Wind farm level controller should be defined under a class called wfc_controller which should implement a method called update_setpoints. This method should take as arguments the unique turbine identifier, the current time and measurements, and return the setpoints for the particular turbine. Please see, the file rosco/controller/rosco_registry/wfc_interface.yaml for the list of available measurements and setpoints. A ZeroMQ server and FAST.Farm simulation are run in parallel as separate processes. The wfc_controller property of the server must be set to the wfc_controller class containing the wind farm controller logic. Note that FAST.Farm requires separate ROSCO libraries for each set of OpenFAST files. The nacelle yaw positions outputs of the two turbines in the wind farm are shown below.

../_images/17c_fastfarm_yaw_demo.png

3.4.18. 18_pitch_offsets

Demosntrate two kinds of pitch faults using ROSCO:

3.4.18.1. 1. Pitch offsets

When PF_Mode is set to 1, the pitch controller will apply a constant offset to the pitch angles of the blades. The offsets are set in the PF_Offsets array in the DISCON file.

../_images/18_pitch_offsets.png

3.4.18.2. 2. Stuck pitch actuator

When PF_Mode is set to 2, the pitch actuator will become stuck at its current position at time PF_TimeStuck.

../_images/18_pitch_stuck.png

3.4.19. 19_update_discon_version

Test and demonstrate update_discon_version() function for converting an old ROSCO input to the current version

3.4.20. 20_active_wake_control

Run openfast with ROSCO and active wake control Set up and run simulation with AWC, check outputs Active wake control (AWC) with blade pitching is implemented in this example with two approaches as detailed in the python script.

3.4.21. 21_optional_inputse_discon_version

Test and demonstrate update_discon_version() function for converting an old ROSCO input to the current version

3.4.22. 22_cable_control

Run openfast with ROSCO and cable control Set up and run simulation with pitch offsets, check outputs

ROSCO currently supports user-defined hooks for cable control actuation, if CC_Mode = 1. The control logic can be determined in Controllers.f90 with the CableControl subroutine. The CableControl subroutine takes an array of CC_DesiredL (length) equal to the ChannelIDs set in MoorDyn and determines the length and change in length needed for MoorDyn using a 2nd order actuator model (CC_ActTau). In the DISCON input, users must specify CC_GroupIndex relating to the deltaL of each 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 -10 m on line 1 is applied at 50 sec.

3.4.23. 23_structural_control

Run openfast with ROSCO and structural control Set up and run simulation with pitch offsets, check outputs

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, we implement a smooth step change mimicing the exchange of ballast from the upwind column to the down wind columns

OpenFAST v3.5.0 is required to run this example

3.4.24. 24_floating_feedback

Run openfast with ROSCO and all the floating feedback methods Floating feedback methods available in ROSCO/ROSCO_Toolbox

  1. Automated tuning, constant for all wind speeds

  2. Automated tuning, varies with wind speed

  3. Direct tuning, constant for all wind speeds

  4. Direct tuning, varies with wind speeds

3.4.25. 25_rotor_position_control

Run ROSCO with rotor position control Run a steady simulation, use the azimuth output as an input to the next steady simulation, with different ICs

3.4.26. 26_marine_hydro

Run MHK turbine in OpenFAST with ROSCO torque controller

3.4.27. 27_soft_cut_out

Set up a control input to do a soft cut-out of a wind turbine at high wind speeds. This example uses the first power reference control implementation (PRC_Mode of 1), where the user specifies the speed setpoint versus wind speed. We can use this to track specific rotor speeds based on the wind speed, or de-rate/power boost using by changing the speed. With PRC_Mode of 2, we can do this but also change the power rating with pitch and torque.

3.4.28. 28_tower_resonance

Demonstrate tower resonance avoidance controller Set up and run simulation with tower resonance avoidance

3.4.29. 29_power_control

This example demonstrates an advanced method for controlling the power output of a turbine. Users may want to reduce the power output, or de-rate the turbine to reduce loads, increase wind speeds deeper in the farm, or for grid support functions. Users might also want to increase the power output when it’s safe to do so. Future advanced control methods can make use of these inputs to directly account for the trade off between power and loads.

There are a few ways to control the turbine power output

The power rating (R) is the controlled power relative to the rated power (or available power below rated). For example R = 0.9, will produce 90% of the rated power (or available power below rated).

  • Speed (R_Speed) will change the rated speed, or the speed setpoint relative to the optimal tip speed ratio (below rated).

  • Torque (R_Torque): will change the rated torque. In constant power operation (VS_ConstPower of 1), the torque is non-constant, but the rated power used to calcualte the torque demand is adapted accordingly.

  • Pitch (R_Pitch): will change the minimum pitch angle of the turbine. When using peak shaving, the min pitch is the maximum of the minimum pitch for peak shaving (PS_Min_Pitch) and the minimum pitch for power control (PRC_Min_Pitch). The ROSCO toolbox can generate a lookup table from R_Pitch to PRC_Min_Pitch using the Cp surface.

The three methods are compared in the following figure:

../_images/29_PRC_Methods.png

The power rating can be controlled with three different “communication” methods (PRC_Comm), via:

  1. Constant settings in the DISCON: R_Speed, R_Torque, and R_Pitch.

  2. Open-loop control inputs with time or wind speed breakpoints. Two applications will be shown in the example below.

  3. The ZeroMQ interface. A simple example is provided in 17b_zeromq_multi_openfast.py.

This example shows users how to set up open loop control inputs for

  1. A start up routine that ramps the turbine rating using R_Torque in steps over 400 seconds.

  2. A soft cut-out routine for high wind speeds.

  3. Active wake control for above rated operation, using a sinusoidal input for R_speed.

3.4.29.1. Start Up Demo

../_images/29_StartUp.png

The turbine is started in a parked configuration with the blades pitched to 90 degrees. R_Torque is increased from 0 to 0.2, then from 0.2 to 1.0, simulating a startup routine. The torque, because it is saturated at the max torque, which is scaled by R_Torque follows the trajectory of PRC_R_Torque. PRC_R_Torque is the variable name inside ROSCO and the .dbg2 file. The blade pitch controller is active throughout the simulation, regulating the generator to the rated speed as usual.

3.4.29.2. Soft Cut-out Demo

../_images/29_Soft_Cutout.png

The turbine starts in above-rated operation and a ramp wind input goes well beyond the normal cut-out wind speed of 25 m/s. In this demonstration, we use both R_Speed and R_Torque to ramp the turbine rating from 1.0 at 20 m/s to 0.5 at 30 m/s and 0.0 at 40 m/s. The signals PRC_R_Speed and PRC_R_Torque ramp towards 0 following the R versus wind speed table. Both GenTq and GenSpeed drop to 0 following the reference signals and the power follows.

3.4.29.3. Active Wake Control Demo

../_images/29_AWC.png

In active wake control, the goal is to change the rotor thrust through low frequency changes to the blade pitch. Since the blade pitch must be used to control the rotor speed in above rated operation, we can insteady vary the generator speed reference (via R_Speed) to create similar blade pitch variations.

3.4.30. 30_shutdown

This example demonstrates turbine shutdown using collective blade pitch threshold mode.

ROSCO allows for four shutdown trigger options:

  • collective blade pitch exceeds a threshold

  • yaw error exceeds a threshold

  • generator speed exceeds a threshold

  • Shutdown at a predefined time

There are two methods of shutdown: 1. Timed stages (SD_Method = 1): The user specifies a pitch (SD_MaxPitchRate) and torque (SD_MaxTorqueRate) rate for each stage, and the stage lasts for a specified time (SD_Stage_Time). 2. Pitch-based stages (SD_Method = 2): The user specifies a pitch and torque rate for each stage, and the stage lasts until the pitch is above the specified thresholds (SD_Stage_Pitch).

3.4.30.1. Pitch Threshold Demo

The following plot demonstrates turbine shutdown when blade pitch exceeds a threshold of 30 degrees. This shutdown mode can provide protection against high wind speeds.

../_images/30_shutdown_pitch_demo.png

3.4.30.2. Yaw Error Threshold Demo

The following plot demonstrates turbine shutdown when turbine yaw error pitch exceeds a threshold of 25 degrees. This demonstration uses the extreme coherent gust with direction change wind inflow used in DLC 1.4.

../_images/30_shutdown_yaw_demo.png

3.4.30.3. Generator Speed Threshold Demo

The following plot demonstrates turbine shutdown when generator speed exceeds a threshold of 8.5 rpm. This also compares the use of SD_TimeActive to enable shutdown at 0 seconds and 10 seconds.

../_images/30_shutdown_gen_demo.png

3.4.30.4. Time Demo

The following plot demonstrates turbine shutdown at 20 second time.

../_images/30_shutdown_time_demo.png

3.4.31. 31_fixed_pitch_mhk

This example demonstrates the fixed-pitch control of a marine hydrodkinetic (MHK) turbine.

There are several ways to control the power output of a turbine in above-rated conditions. In this example we demonstrate the following control configurations:

  1. Constant power underspeed (should be the default)

  2. Constant power overspeed

  3. Linear increasing power

  4. Linear increasing power, leveling out

  5. Generic numeric function

  6. Constant power overspeed, nonlinear lookup table control

More details about the controller methods can be found in ROSCO Control of Marine Hydrokinetic Turbines (MHKs).

The desired power curves of each configuration are as follows:

../_images/31_fixed_pitch_mhk_sched.png

In the first case, the reference generator speed is decreased (underspeed) to maintain a constant rated power above rated. To slow down the generator, a higher torque must be used:

../_images/31_fixed_pitch_mhk_sim.png

3.4.32. 32_Startup

This example demonstrates turbine startup procedure. The startup occurs in various stages depending on the provided input. The states are as follows:

  • Stage 1: Free-Wheeling of rotor

    In this stage the generator torque is 0 (set using PRC_R_Torque = 0) and the rotor is free to rotate. The rotor continues to free-wheel until the rotor speed exceeds 0.95 * SU_RotorSpeedThresh and stay above it for at least SU_FW_MinDuration seconds. Once both these criteria are met, the startup procedure enters the next stage.

  • Stage 2 - [SU_LoadStages_N + 2]:

    In the next stage(s), the startup procedure relinquishes the control of the blade pitch angles to the normal speed controller. The power and load on the rotor is increased in stages by changing PRC_R_Torque. ROSCO reads an array of desired power loads as SU_LoadStages. It also reads ramp-duration and hold-duration for each load stage as SU_LoadRampDuration and SU_LoadHoldDuration respectively. At each stage, the startup procedure increases PRC_R_Torque from its previous value to its current value using a smooth ramp in the form of a sigma function. The duration of the ramp is determined by the SU_LoadRampDuration array. Then, the PRC_R_Torque held constant at the current level for a period of time (SU_LoadHoldDuration).

The stage is stored in a ROSCO local variable SU_LoadStage. After the startup procedure is complete, SU_LoadStage resets to 0.

The following figure demonstrate the startup procedure

../_images/32_startup.png

3.4.33. 33_yaw_control

This example demonstrates how to run the ROSCO yaw controller. Details of the controller can be found and referenced here: https://wes.copernicus.org/articles/5/451/2020/

The nacelle wind vane signal (NacVane) is filtered and, along with offsets either from Y_MErrSet or ZMQ_YawOffset, a target (NacHeadingTarget) is defined. The error (Yaw_Err) is the difference between the target and the current nacelle heading. The wind speed dependent deadband (Y_ErrThresh) determines when the yaw controller will activate. A state machine will yaw the turbine at a constant rate (Y_Rate) until the target is reached.

The following time series should be generated by the example:

../_images/33_yaw_control.png