-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from NREL/develop
WHOC v0.1
- Loading branch information
Showing
43 changed files
with
1,777 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
|
||
repos: | ||
|
||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v4.4.0 | ||
hooks: | ||
- id: trailing-whitespace | ||
- id: end-of-file-fixer | ||
- id: check-executables-have-shebangs | ||
- id: check-yaml | ||
args: [--unsafe] | ||
- id: check-merge-conflict | ||
- id: check-symlinks | ||
- id: mixed-line-ending | ||
|
||
- repo: https://github.com/astral-sh/ruff-pre-commit | ||
# Ruff version. | ||
rev: v0.1.7 | ||
hooks: | ||
# Run the linter. | ||
- id: ruff | ||
types_or: [ python, pyi, jupyter ] | ||
args: [ --fix ] | ||
# Run the formatter. | ||
- id: ruff-format | ||
types_or: [ python, pyi, jupyter ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Copyright 2021 NREL | ||
|
||
# Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
# use this file except in compliance with the License. You may obtain a copy of | ||
# the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations under | ||
# the License. | ||
|
||
# See https://nrel.github.io/wind-hybrid-open-controller for documentation | ||
|
||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
from whoc.controllers.wake_steering_actuatordisk_standin import WakeSteeringADStandin | ||
from whoc.interfaces.hercules_actuator_disk_yaw_interface import HerculesADYawInterface | ||
|
||
demo_hercules_dict = { | ||
"dt": 1.0, | ||
"hercules_comms": { | ||
"amr_wind": { | ||
"wind_farm_0": { | ||
"type": "amr_wind_local", | ||
"amr_wind_input_file": "amr_input.inp", | ||
} | ||
} | ||
}, | ||
"controller": {"num_turbines": 2, "initial_conditions": {"yaw": [10.0, 15.0]}}, | ||
} | ||
|
||
interface = HerculesADYawInterface(demo_hercules_dict) | ||
|
||
controller = WakeSteeringADStandin(interface, demo_hercules_dict) | ||
|
||
# Create a little loop to demonstrate how the controller works | ||
wd_base = np.linspace(280, 300, 50) | ||
np.random.seed(0) | ||
wind_dir = np.tile(wd_base, (2, 1)).T + np.random.normal(scale=5.0, size=(len(wd_base), 2)) | ||
|
||
yaw_angles = [] | ||
for i in range(wind_dir.shape[0]): | ||
demo_hercules_dict["hercules_comms"]["amr_wind"]["wind_farm_0"][ | ||
"turbine_wind_directions" | ||
] = wind_dir[i, :] | ||
demo_hercules_dict["hercules_comms"]["amr_wind"]["wind_farm_0"]["turbine_wind_speeds"] = 8 | ||
demo_hercules_dict["hercules_comms"]["amr_wind"]["wind_farm_0"]["turbine_powers"] = 2000 | ||
demo_hercules_dict["time"] = float(i) | ||
|
||
demo_hercules_dict = controller.step(hercules_dict=demo_hercules_dict) | ||
|
||
yaw_angles.append( | ||
demo_hercules_dict["hercules_comms"]["amr_wind"]["wind_farm_0"]["turbine_yaw_angles"] | ||
) | ||
|
||
yaw_angles = np.array(yaw_angles) | ||
fig, ax = plt.subplots(2, 1, sharex=True, sharey=True) | ||
for i in range(2): | ||
ax[i].plot(range(wind_dir.shape[0]), wind_dir[:, i], color="C0", label="wd") | ||
ax[i].plot(range(wind_dir.shape[0]), yaw_angles[:, i], color="black", label="yaw stpt") | ||
ax[i].set_ylabel("Direction, T{0} [deg]".format(i)) | ||
ax[i].grid() | ||
ax[1].set_xlabel("Time") | ||
ax[1].set_xlim([0, wind_dir.shape[0]]) | ||
ax[0].legend() | ||
|
||
plt.show() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Code development | ||
To contribute to WHOC, please consider forking the main github repository, | ||
with the [NREL repo](https://github.com/NREL/wind-hybrid-open-controller) as an | ||
upstream remote. See the [Installation instructions](install_instructions) | ||
for details about how to set up your repository as a developer. | ||
|
||
To submit a new feature or bug fix, create a new branch | ||
in your fork and submit a pull request back to the `develop` branch in the | ||
main repo. The pull request will be reviewed by other WHOC maintainers and | ||
merged (using "squash and merge") into the `develop` branch. Periodically, | ||
the `develop` branch will be merged into the `main` branch and a version | ||
number will be assigned. | ||
|
||
Unless an existing controller or interface exist to suit your needs, most | ||
users will need to generate: | ||
- A new interface class inheriting from `InterfaceBase` | ||
- A new controller class, implementing the desired control algorithm and | ||
inheriting from `ControllerBase` | ||
|
||
Additionally, if you'd like to contribute to this base repository, please | ||
include in your pull request: | ||
- Unit tests for the implemented controller | ||
- Possibly unit tests for the implemented interface, if needed |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Controllers | ||
|
||
The `whoc.controllers` module contains a library of wind and hybrid power plant | ||
controllers. Each controller must inherit from `ControllerBase` (see | ||
controller_base.py) and implement a | ||
mandatory `compute_controls()` method, which contains the relevant control | ||
algorithm and writes final control signals to the `controls_dict` attribute | ||
as key-value pairs. `compute_controls()` is, in turn, called in the `step()` | ||
method of `ControllerBase`. | ||
|
||
## Available controllers | ||
|
||
### WakeSteeringADStandin | ||
For yaw controller of actuator disk-type turbines (as a stand-in, will be | ||
updated). | ||
|
||
### WakeSteeringROSCOStandin | ||
May be combined into a universal simple wake steeringcontroller. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Installation | ||
|
||
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. | ||
|
||
## General users | ||
|
||
If you intend to use WHOC, but not contribute, the following lines should | ||
be sufficient to install WHOC (presumably, after activating your conda | ||
environment): | ||
|
||
``` | ||
git clone https://github.com/NREL/wind-hybrid-open-controller | ||
pip install wind-hybrid-open-controller/ | ||
``` | ||
|
||
## Developers | ||
|
||
If you intend to contribute to WHOC, we request that your fork the WHOC | ||
repository on github. You can then install WHOC (again, assuming you have | ||
already activated your conda environment) according to: | ||
|
||
``` | ||
git clone https://github.com/your-github-id/wind-hybrid-open-controller | ||
pip install -e "wind-hybrid-open-controller/[develop]" | ||
``` | ||
To contribute back to the base repository | ||
https://github.com/NREL/wind-hybrid-open-controller, please do the following: | ||
- Create a branch from the base repository's `develop` branch on your fork | ||
containing your code changes (e.g. `your-github-id:feature/your-new-feature`) | ||
- Open a pull request into the base repository's `NREL:develop` branch, and provide | ||
a description of the new/updated capabilities | ||
- The maintainers will review your pull request and provide feedback before | ||
possibly merging the pull request (via the "squash and merge" method) into the | ||
`NREL:develop` branch | ||
- At the next release, `NREL:develop` will be merged into `NREL:main`, and your changes | ||
contributions will appear there | ||
|
||
For more information on what your pull request should contain, see | ||
[Code development](code_development.md). | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Interfaces | ||
|
||
The `whoc.interfaces` module contains a library of interfaces for connecting | ||
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 | ||
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 | ||
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. | ||
|
||
These methods will all be called in the `step()` method of `ControllerBase`. | ||
|
||
## Available interfaces | ||
|
||
### HerculesADYawInterface | ||
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. | ||
|
||
### ROSCO_ZMQInterface | ||
For sending and receiving communications from one or more ROSCO instances | ||
(which are likely connected to OpenFAST and FAST.Farm). Uses ZeroMQ to pass | ||
messages between workers. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,36 @@ | ||
# Wind Hybrid Open Controller (WHOC) | ||
|
||
Wind Hybrid Open Controller | ||
The Wind Hybrid Open Controller (WHOC) is a python-based tool for real-time | ||
plant-level wind farm control and wind-based hybrid plant control. | ||
WHOC will primarily be run in simulation, although we intend that it could be | ||
used for physical plants in future. | ||
|
||
Online documentation for Wind Hybrid Open Controller | ||
The graphic below demonstrates the organization of the WHOC repository and | ||
the controller objects that it contains. | ||
![](graphics/main_attribution_inheritance.png) | ||
|
||
More info | ||
`ControllerBase` is the core underlying class, which newly implemented | ||
controllers should inherit from. Inheritance is shown using arrows in the | ||
diagram above. The key method of `ControllerBase` is the `step()` method, | ||
which progresses the controller by receiving plant measurements; computing | ||
controls (which must be implemented in the children of | ||
`ControllerBase`); and sending the controls back to the plant. Children of | ||
`ControllerBase` should inherit `step()` rather than overloading it. | ||
Additionally, on instantiation, `ControllerBase` expects to receive an | ||
instantiated `interface` object (discussed next). For information can be | ||
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` | ||
objects should inherit from `InterfaceBase`. More information can be found in | ||
interfaces.md. | ||
|
||
|
||
We anticipate that, in future, multiple levels of inheritance may be useful | ||
when defining top-level controllers that operate hybrid power plants with | ||
various different assets. This situation is shown below, and we intend to | ||
support such usage of WHOC. | ||
|
||
![](graphics/second-level_attribution_inheritance.png) |
Oops, something went wrong.