Skip to content

Commit

Permalink
Merge pull request #37 from NREL/develop
Browse files Browse the repository at this point in the history
WHOC v0.2
  • Loading branch information
misi9170 authored Jul 26, 2024
2 parents 7ebdd0b + 8ba8a41 commit 723339f
Show file tree
Hide file tree
Showing 64 changed files with 88,052 additions and 334 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/continuous-integration-workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
# - uses: pre-commit/action@v3.0.0
- name: Run ruff
run: |
ruff .
ruff check .
ruff format
- name: Run tests and collect coverage
run: |
Expand Down
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ slices
# Data files
*.csv
*.log
examples/*/logstandin
examples/*/loghercules
examples/*/logstandin*
examples/*/loghercules*
examples/*/logfloris*

# Exceptions
!examples/lookup-based_wake_steering_florisstandin/amr_standin_data.csv
!examples/wind_farm_power_tracking_florisstandin/amr_standin_data.csv
!examples/wind_farm_power_tracking_florisstandin/wind_power_reference_data.csv

# macOS files
.DS_Store
Expand Down
36 changes: 1 addition & 35 deletions docs/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
title: Wind Hybrid Open Controller
author: National Renewable Energy Laboratory
# logo: herc.png
copyright: '2023'
copyright: '2024'
only_build_toc_files: false

# Force re-execution of notebooks on each build.
Expand Down Expand Up @@ -36,37 +36,3 @@ html:
google_analytics_id: G-BJZY823DHG


# Sphinx for API doc generation
sphinx:
extra_extensions:
- 'sphinx.ext.autodoc'
- 'sphinx.ext.autosummary'
- 'sphinx.ext.viewcode'
- 'sphinx_autodoc_typehints'
- 'sphinxcontrib.autoyaml'
- 'sphinx.ext.napoleon' # Formats google and numpy docstring styles
- 'sphinxcontrib.mermaid'
config:
html_theme: sphinx_book_theme
templates_path:
- '_templates'
language: 'python'
autoyaml_level: 3
autosummary_generate: true

# Autodoc config reference
# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#configuration
autodoc_default_options:
members: true
member-order: bysource
undoc-members: true
private-members: true
# special-members: true
# inherited-members
# show-inheritance
# ignore-module-all
# imported-members: true
# exclude-members
# class-doc-from
# no-value
autodoc_typehints: both
34 changes: 0 additions & 34 deletions docs/_templates/custom-class-template.rst

This file was deleted.

66 changes: 0 additions & 66 deletions docs/_templates/custom-module-template.rst

This file was deleted.

3 changes: 3 additions & 0 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ parts:
- caption: Interfaces
chapters:
- file: interfaces
- caption: Examples
chapters:
- file: examples
# - file: order_of_op
48 changes: 44 additions & 4 deletions docs/controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,49 @@ method of `ControllerBase`.

## Available controllers

### WakeSteeringADStandin
For yaw controller of actuator disk-type turbines (as a stand-in, will be
updated).
### LookupBasedWakeSteeringController
Yaw controller that implements wake steering based on a lookup table.
Requires a `df_opt` object produced by a FLORIS yaw optimization routine. See example
lookup-based_wake_steering_florisstandin for example usage.

Currently, yaw angles are set based purely on the (local turbine) wind direction. The lookup table
is sampled at a hardcoded wind speed of 8 m/s. This will be updated in future when an interface is
developed for a simulator that provides wind turbine wind speeds also.

### WakeSteeringROSCOStandin
May be combined into a universal simple wake steeringcontroller.
Not yet developed. May be combined into a universal simple LookupBasedWakeSteeringController.

### WindBatteryController
Placeholder for a controller that manages both a wind power plant and colocated
battery.

### WindFarmPowerDistributingController

Wind farm-level power controller that simply distributes a farm-level power
reference between wind turbines evenly, without checking whether turbines are
able to produce power at the requested level. Not expected to perform well when
wind turbines are waked or cannot produce the desired power for other reasons.
However, is a useful comparison case for the WindFarmPowerTrackingController
(described below).

### WindFarmPowerTrackingController

Closed-loop wind farm-level power controller that distributes a farm-level
power reference among the wind turbines in a farm and adjusts the requests made
from each turbine depending on whether the power reference has been met.
Developed under the [A2e2g project](https://github.com/NREL/a2e2g), with
further details provided in
[Sinner et al.](https://pubs.aip.org/aip/jrse/article/15/5/053304/2913100).

Integral action, as well as gain scheduling based on turbine saturation, has been disabled as
simple proportional control appears sufficient currently. However, these may be enabled at a
later date if needed. The `proportional_gain` for the controller may be provided on instantiation,
and defaults to `proportional_gain = 1`.

### HybridSupervisoryControllerBaseline

Simple closed-loop supervisory controller for a hybrid wind/solar/battery plant.
Reads in current power production from wind, solar, and battery, as well as a plant power reference. Contains logic to determine technology set points for wind, solar and battery technologies to follow the plant power reference. The control is based on a proportional gain based on the error between the wind and solar production and the plant power reference. The controller increases the power references sent to wind, solar, and battery if the power reference is not met. If there is a power surplus from wind and solar, the controller adjusts the power reference values to charge the battery up to the battery capacity.

The power reference values for wind, solar and battery technologies are then handled by the operational controllers for wind, solar, and battery, which are assigned to the `HybridSupervisoryControllerBaseline` on instantiation to distribute the bulk references to each asset amongst the individual generators. Currently, only wind actually distributes the power.
Intended as a baseline for comparison to more advanced supervisory controllers.
51 changes: 51 additions & 0 deletions docs/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Examples

The `examples` subdirectory contains a series of examples that can be run to test the functionality
of certain controllers and interfaces.

### lookup-based_wake_steering_florisstandin
2-turbine example of lookup-based wake steering control, run using Hercules with the FLORIS standin
in place of AMR-Wind for exposition purposes. To run this example, navigate to the
examples/lookup-based_wake_steering_florisstandin folder and then run the following.
```
python construct_yaw_offsets.py
```

Not that, currently, construct_yaw_offsets.py requires FLORIS version 3, whereas the rest of the
example requires FLORIS version 4. As a result, we provide the generated offsets in
yaw_offsets.pkl. To avoid regenerating yaw_offsets.pkl (and therefore avoid the current need for
floris v3), set `optimize_yaw_offsets = False` at the beginning of construct_yaw_offsets.py before
running.

Next, run
```
./bash_script.sh
```
You will need to have and up-to-date Hercules (possibly on the develop branch) in your conda
environment to run this. You may also need to changed permissions to run bash_script.sh as an
executable (`chmod +x bash_script.sh`).

Finally, run the post-processing script
```
python plot_output_data.py
```
This should produce the following plot.
![Results of lookup-based_wake_steering_florisstandin example](
graphics/lookup-table-example-plot.png
)

## wind_farm_power_tracking_florisstandin
2-turbine example of wind-farm-level power reference tracking, run using Hercules with the FLORIS
standin in place of AMR-Wind for exposition purposes. To run this example, navigate to the
examples/wind_farm_power_tracking_florisstandin folder and run the following:
```
./bash_script.sh
```

This will run both a closed-loop controller, which compensates for underproduction at individual
turbines, and an open-loop controller, which simply distributes the farm-wide reference evenly
amongst the turbines of the farm without feedback. The resulting trajectories are plotted,
producing:
![Results of wind_farm_power_tracking_florisstandin example](
graphics/wf-power-tracking-plot.png
)
Binary file added docs/graphics/lookup-table-example-plot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/graphics/wf-power-tracking-plot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docs/install_instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
WHOC is _not_ designed to be used as a stand-alone package. Most likely,
you'll want to add WHOC to an existing conda environment that contains your
simulation testbed, such as [Hercules](https://github.com/NREL/hercules).
For example, see the [Hercules installation instuctions](\
https://nrel.github.io/hercules/install_instructions.html) for how to set up
an appropriate conda environment.
For example, see the
[Hercules installation instructions](https://nrel.github.io/hercules/install_instructions.html)
for how to set up an appropriate conda environment.

## General users

Expand Down
17 changes: 13 additions & 4 deletions docs/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ WHOC with various simulation platforms and other repositories. Each controller
run will require an `interface`, which is an instantiated object of a class
in this library. All interface classes should inherit from `InterfaceBase`,
which can be found n interface_base.py, and should implement three methods:
- `get_measurements()`: Recieve measurements from simulation assets and
- `get_measurements()`: Receive measurements from simulation assets and
organize into a dictionary that the calling controller can utilize. Optionally,
receives a large dictionary (for example, the Hercules `main_dict`), from which
useable measurements can be extracted/repackaged for easy use in the controller.
- `check_controls()`: Check that the keys in `controls_dict` are viable for
the receiving plant.
- `send_controls()`: Send controls to the simulation assets. Controls are
created as specific keyword arguements, which match those controls generated
created as specific keyword arguments, which match those controls generated
by the calling controller. Optionally, receives a large dictionary
(for example, the Hercules `main_dict`), which can be written to and returned
with controls as needed.
Expand All @@ -21,11 +21,20 @@ These methods will all be called in the `step()` method of `ControllerBase`.

## Available interfaces

### HerculesADYawInterface
### HerculesADInterface
For direct python communication with Hercules. This should be instantiated
in a runscript that is running Hercules; used to generate a `controller` from
the WHOC controllers submodule; and that `controller` should be passed to the
Hercules `Emulator` upon its instantiation.
Hercules `Emulator` upon its instantiation. Support transmitting yaw angles
and power setpoints to wind turbines.

### HerculesHybridADInterface
For direct python communication with Hercules, when simulating a hybrid
wind/solar/battery plant. Currently, intended for use with the
`HybridSupervisoryControllerBaseline`, while full closed-loop supervisory
controllers for hybrid power plants are built out. Supports sending power
reference signals to each wind turbine in a wind farm, as well as a bulk power
signal to the solar farm and a bulk power signal to the battery.

### ROSCO_ZMQInterface
For sending and receiving communications from one or more ROSCO instances
Expand Down
2 changes: 1 addition & 1 deletion docs/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ found in controllers.md.
The `interface` object handles communications with the plant simulator,
allowing WHOC to be used with various simulation platforms (e.g. Hercules,
FAST.Farm) while keeping the controllers agnostic to the simulation platform
and the boilderplate code needed to handle different platforms. `interface`
and the boilerplate code needed to handle different platforms. `interface`
objects should inherit from `InterfaceBase`. More information can be found in
interfaces.md.

Expand Down
Loading

0 comments on commit 723339f

Please sign in to comment.