Skip to content

Fixed Blade Pitch Control Updates for MHKs - #508

Merged
dzalkind merged 22 commits into
developfrom
mhk_fpb_review
Sep 24, 2026
Merged

dzalkind merged 22 commits into
developfrom
mhk_fpb_review

Conversation

@dzalkind

Copy link
Copy Markdown
Collaborator

Description and Purpose

Review and harden the fixed-blade-pitch (FBP) MHK control path, and document it properly. Came out of a review of the MHK/FBP feature while setting up tidal DLCs in WEIS.

Cavitation check on the operating schedule

  • New Controller.cavitation_speed_limit() estimates the rotor speed at which tip cavitation begins, from the cavitation number criterion sigma > -Cp_min with the hydrostatic head at the blade tip's shallowest point. Turbine now loads Patm, Pvap, MSL2SWL, the tip depth, and sigma_v = -Cp_min from the outboard (>=70% span) AeroDyn polars.
  • tune_controller warns when the tuned speed schedule crosses that limit. Overspeed schedules raise rotor speed while lowering torque, so the existing torque check cannot catch them. This is a tip, attached-flow screening estimate at a fixed hub depth — the docstring and docs say so, and point at AeroDyn's CavitCheck for confirmation.

FBP configuration checks

  • The toolbox now fails on the mode conflicts that ReadSetParameters.f90 aborts on at runtime (PC_ControlMode != 0, VS_ConstPower != 0, PRC_Mode == 1 with VS_FBP > 0), rather than writing a DISCON that cannot run.
  • Warns when VS_ControlMode is not the Region 2 mode paired with the selected VS_FBP (1→1, 2→2, 3→4), since both regions drive the same actuator and the references have to agree through the transition.
  • VS_FBP = 1 follows a fixed control law and ignores the power curve; the toolbox now says so and generates the schedule ROSCO will actually follow instead of a schedule it silently discards.
  • Clearer message on the VS_FBP = 3 non-invertible torque schedule failure.

Soft start for FBP

  • VS_MaxTq is now de-rated by PRC_R_Torque in the FBP branch of Controllers.f90, so an open-loop R_Torque ramp can phase in the torque limit while the rotor spins up. PRC_R_Torque defaults to 1, so existing configurations are unaffected.
  • PRC_Mode = 2 (de-rating only) is now allowed alongside VS_FBP; only PRC_Mode = 1, whose speed-setpoint lookup would override the FBP reference, is still rejected. Example 31 uses this for a 100 s sigma ramp on all six configurations.

Bug fixes

  • Below rated, FBP tracks TSR_operational regardless of the requested power curve, so Cp_op is now held on the Cp surface at that TSR. Previously the (Cp, TSR) pair was not an equilibrium and the resulting speed and torque setpoints were unreachable. Warns when the power curve asks for below-rated curtailment, which FBP cannot do.
  • Minimum rotor speed limits (vs_minspd, pc_minspd) are now set before the operating schedule saturates against them, instead of after, so they apply in all cases rather than only the ones that happened to run later.
  • PRC_WindSpeeds/PRC_GenSpeeds defaults in utilities.py were hard-coded to 3–25 m/s and a 7.56 rpm reference; they now derive from turbine.v_min/v_max and PC_RefSpd, which matters for MHK speed ranges.
  • VS_ControlMode is documented as the below rated torque mode everywhere (schema, DISCON writer, regenerated DISCON files). It was labeled "above rated" in every one of those places.

Examples and case generation

  • Examples/31_fixed_pitch_mhk.py reorganized around three verified case studies (constant power overspeed, linear increasing power, generic user-defined curve), each stating its VS_FBP and paired VS_ControlMode explicitly, followed by three experimental configurations that exercise the rest of the input space. Sweeps all cases rather than selecting one by hand.
  • CaseLibrary.sweep_control_params accepts a param_sweeps list of full controller_params overrides, not just one parameter at a time. The existing control_param/discon_param path is unchanged, except that a discon_param sweep no longer mutates the caller's nested DISCON dict.
  • RM1_MHK_FBP.yaml: v_rated corrected to 1.72 m/s (the rated speed point where the rotor reaches 1.204 rad/s at TSR 7 and the FBP lookup engages, not a rated power point), VS_ControlMode = 4 to pair with VS_FBP = 3. RM1_MHK.yaml: v_max 3.0 → 4.0, WE_Mode → 2 (EKF), and the VS_ConstPower comment corrected.

Documentation

  • docs/source/marine_hydro.rst substantially expanded: a variable-pitch MHK section, over/underspeed reference setpoints and their dynamics, alternate Region 3 operating schedules, rotor speed limits and cavitation, toolbox and ROSCO implementation notes, simulation verification of the three case studies, recommendations, and future work.
  • docs/index.rst: how to build the docs locally.
  • .readthedocs.yaml: mamba install with fewer solves, to speed up the docs build.

Type of change

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Documentation update
  • Maintenance update

TODO Items General:

  • Add example/test for new feature
  • Update registry — no new DISCON parameters, nothing to register
  • Run testing

TODO Items API Change:

  • Update docs with API change
  • Run update_rosco_discons.py in Test_Cases/
  • Update DISCON schema — VS_ControlMode description corrected; no parameters added or removed

Github issues addressed, if one exists

None.

Examples/Testing, if applicable

Examples/31_fixed_pitch_mhk.py now tunes and simulates all six fixed-pitch configurations in one run, and produces the schedule and simulation figures used in the verification section of the MHK docs. The three verified case studies are compared against ROSCO simulation results there.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved findings remain in cavitation handling, FBP validation and scheduling, case-sweep isolation, and generated DISCON consistency.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 3 Medium severity

Open (3)
What changed in this PR

This PR hardens fixed-blade-pitch MHK control with cavitation screening, validation, scheduling fixes, expanded examples, and updated documentation.

Changes:

  • Adds FBP validation, torque de-rating, and cavitation checks.
  • Updates controller configurations, case sweeps, and generated inputs.
  • Expands MHK documentation and adjusts documentation workflows.
File Reviewed change
rosco/​toolbox/​utilities.py Updates controller descriptions and PRC defaults.
rosco/​toolbox/​turbine.py Loads MHK cavitation properties.
rosco/​toolbox/​ofTools/​case_gen/​CaseLibrary.py Adds full controller sweep support.
rosco/​toolbox/​inputs/​toolbox_schema.yaml Corrects VS_ControlMode documentation.
rosco/​toolbox/​controller.py Adds FBP validation, scheduling, and cavitation checks.
rosco/​controller/​src/​ReadSetParameters.f90 Allows PRC de-rating with FBP.
rosco/​controller/​src/​Controllers.f90 Applies torque de-rating to FBP limits.
Examples/​Tune_Cases/​RM1_MHK.yaml Updates MHK operating-range and estimator settings.
Examples/​Tune_Cases/​RM1_MHK_FBP.yaml Corrects FBP rated-speed configuration.
Examples/​Tune_Cases/​NREL5MW.yaml Reviews controller configuration documentation.
Examples/​Tune_Cases/​NREL5MW_PassThrough.yaml Reviews controller configuration documentation.
Examples/​Tune_Cases/​IEA15MW.yaml Reviews controller configuration documentation.
Examples/​Tune_Cases/​IEA15MW_robust.yaml Reviews controller configuration documentation.
Examples/​Tune_Cases/​IEA15MW_PRC.yaml Reviews PRC configuration documentation.
Examples/​Tune_Cases/​IEA15MW_OL.yaml Reviews open-loop configuration documentation.
Examples/​Tune_Cases/​IEA15MW_MultiOmega.yaml Reviews controller configuration documentation.
Examples/​Tune_Cases/​IEA15MW_FOCAL.yaml Reviews controller configuration documentation.
Examples/​Tune_Cases/​IEA15MW_ExtInterface.yaml Reviews controller configuration documentation.
Examples/​Tune_Cases/​IEA15MW_cable.yaml Reviews controller configuration documentation.
Examples/​Tune_Cases/​IEA15MW_ballast.yaml Reviews controller configuration documentation.
Examples/​Tune_Cases/​BAR.yaml Reviews controller configuration documentation.
Examples/​Test_Cases/​NREL-5MW/​DISCON.IN Updates generated controller inputs.
Examples/​Test_Cases/​NREL_2p8_127/​NREL-2p8-127_DISCON.IN Updates generated controller inputs.
Examples/​Test_Cases/​MHK_RM1/​MHK_RM1_DISCON.IN Updates generated MHK controller inputs.
Examples/​Test_Cases/​IEA-15-240-RWT/​IEA-15-240-RWT-UMaineSemi/​IEA-15-240-RWT-UMaineSemi_ROSCO.yaml Updates generated ROSCO configuration.
Examples/​Test_Cases/​IEA-15-240-RWT/​IEA-15-240-RWT-UMaineSemi/​IEA-15-240-RWT-UMaineSemi_DISCON.IN Updates generated controller inputs.
Examples/​Test_Cases/​IEA-15-240-RWT/​IEA-15-240-RWT-Monopile/​IEA-15-240-RWT-Monopile_ROSCO.yaml Updates generated ROSCO configuration.
Examples/​Test_Cases/​IEA-15-240-RWT/​IEA-15-240-RWT-Monopile/​IEA-15-240-RWT-Monopile_DISCON.IN Updates generated controller inputs.
Examples/​Test_Cases/​BAR_10/​BAR_10_DISCON.IN Updates generated controller inputs.
Examples/​31_fixed_pitch_mhk.py Adds six FBP configurations and simulations.
Examples/​26_marine_hydro.py Updates the example description.
docs/​source/​marine_hydro.rst Expands MHK and FBP documentation.
docs/​index.rst Adds local documentation build instructions.
.readthedocs.yaml Simplifies documentation dependency installation.
.github/​workflows/​Publish_ROSCO.yml Adjusts workflow compiler setup.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread rosco/toolbox/ofTools/case_gen/CaseLibrary.py
Comment thread rosco/toolbox/turbine.py
Comment thread rosco/toolbox/turbine.py

@abhineet-gupta abhineet-gupta left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.


.. [Stockhouse2025] Stockhouse, D. *Fixed-Blade-Pitch Control in ROSCO for MHK
Turbines.* National Renewable Energy Laboratory presentation, 2025.
(Source material for this page.)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this line need to be replaced by the DOI of the document?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was an unpublished presentation, so we don't have a DOI.

@dzalkind
dzalkind merged commit 8294a23 into develop Sep 24, 2026
35 checks passed
@dzalkind dzalkind mentioned this pull request Sep 28, 2026
8 of 14 tasks
dzalkind added a commit that referenced this pull request Sep 29, 2026
* Increase number of available instances of filters, etc to 1024

* WindIO Support (#492)

* Clean up examples to clarify inputs/outputs

* Change default ss_pcgain

* Add tuning input to change setpoint separation when tuning

* Fix directories in ex 06

* Bug fix: Use LSS speed throughout TRA subroutine

* Add setpoint separation to DISCON_dict

* Test build on macos-latest and not 13, those runners being depreciated

* Clarify DISCON description for SD_TimeActivate

* Remove macos-13 from publish CI

* Tidy example 02

* Increment version

* Update discons

* Add script for creating windio input yamls

* Create rosco vt from windio and functionize

* Add windio schema conversion to own file

* Make example self-contained in ROSCO

* Update inputs for openfast 4.2.0 (#491)

* Update inputs for openfast 4.2.0

* Update openfast versions in environment

* Pull windIO yamls from their repos for example

* Revert to windIO versions because they have the updated control inputs

* Account for gearbox ratio in windio conversion (#498)

* Account for gearbox ratio in windio conversion

* Pin openfast_io pip install

* Add windio yaml for nrel-5mw

* Fix typo while here

* OpenFAST 5.0 Support (#503)

* Update RM1 model and control

* Update RM1 tuning yaml and SeaState input

* Add discon parameter sweep to CaseLibrary

* Make shorter MHK example

* Update inputs for openfast 4.2.0

* Update openfast versions in environment

* Disable cavitcheck, shutdown at 9999

* Tidy MHK example

* Increase generator inertia

* Set new tuning parameters for RM1

* Update DISCONs

* Update input files to openfast v5

* Update environment yaml

* Add discon_param sweep to CaseLibrary

* Update output file reader so it can grab partial lines without failing

* Read elastodyn file more robustly

* Skip blade input reading, unused

* Increase toml version

* Re-generate discons

* Add note about getting pre-compiled libraries from conda

* Re-generate registry

* Update NREL-5MW, RM1 models to OF 5.0

* Update NREL 2.8 MW

* Update toml, discons

* Update StC_DOF_MODE for OF5, add TEST_MODE

* Update FAST.Farm for OF5.0

* Pip install with no-deps

* Set default DISCON dict

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Restore explicit GenDOF setting in base_op_case

* Use generic DLL_Filename

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Use generic DISCON_LIB_PATH for external users with generic flag

* Update StC mode description

* Update python versions to >=3.11

* Try manylinux_2_28

* Skip 32-bit linux, not supported with numpy 2.5

* Fix toml format

---------

Co-authored-by: dzalkind <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>

* Update documentation errors (#506)

* Update yaw/rad errors

* remove accidental mispelling

---------

Co-authored-by: dzalkind <[email protected]>

* Fixed Blade Pitch Control Updates for MHKs (#508)

* Account for gearbox ratio in windio conversion

* Add docs for building the docs

* Add more generic param_sweeps

* Clean up and sweep all cases in ex 31

* Add a few more checks to FBP modes

* Review MHK control docs

* Add cavitation check and docs

* Align VS_ControlMode with docs

* Try mamba install with fewer solves

* Re-organize example and docs to follow three main examples

* Add soft-start to FBP modes

* Update comment, defaults for MHK settings, VS_ControlMode

* Add variable-pitch section

* Copy-edit the marine_hydro docs

* Clarify 2- vs. 3-bladed remarks

* Fix and document v_rated change for FBP

* Fix Cp_op in below rated FBP

* Relocate min rotor speed limits to before they are used in all cases

* Fix comment, FULL_TEST

* Fix output name

* Try skipping the compiler on macoc-14

---------

Co-authored-by: dzalkind <[email protected]>

* Deep-copy controller params for each sweep case

Controller.__init__ writes per-case OL_* DISCON overrides into the nested
open_loop dict, which was shared across sweep cases by the shallow merge,
so later cases could inherit an earlier case's open-loop file or indices.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Remove toolbox cavitation check

The check needed the steady angle of attack at each blade section to be
more than a heuristic, which the toolbox does not have without CCBlade.
AeroDyn's CavitCheck does this properly, so drop the toolbox check and
keep the cavitation speed limit in the docs as design guidance.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: dzalkind <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: Skylar A Gering <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants