Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUGFIX] Force yaw_angles to zero in FlorisStandin when power_setpoints passed #109

Merged
merged 12 commits into from
Jul 30, 2024
5 changes: 2 additions & 3 deletions .github/workflows/continuous-integration-workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
fail-fast: False
matrix:
python-version: ["3.9", "3.10", "3.11"]
os: [ubuntu-latest]
os: [ubuntu-latest, macos-latest]

steps:
- uses: actions/checkout@v3
Expand All @@ -24,11 +24,10 @@ jobs:
pip install -e ".[develop]"
pip install git+https://github.com/NREL/electrolyzer.git
pip install https://github.com/NREL/SEAS/blob/main/SEAS.tar.gz?raw=true
pip install git+https://github.com/NREL/floris.git@v4
# - 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
20 changes: 20 additions & 0 deletions hercules/floris_standin.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,26 @@ def get_step(self, sim_time_s, yaw_angles=None, power_setpoints=None):

turbine_wind_directions = [amr_wind_direction] * self.num_turbines

if power_setpoints is None or yaw_angles is None:
pass # No conflict with yaw angles
elif (
(((np.array(power_setpoints) == 1e9)
| (np.array([ps is None for ps in power_setpoints])))
| ((np.array(yaw_angles) == -1000) | (np.array([ya is None for ya in yaw_angles])) |
(np.array(yaw_angles) == amr_wind_direction))
).all()
):
pass # No conflict with yaw angles
else:
# Cannot currently handle both power setpoints and nonzero yaw angles.
# If power setpoints are provided, overwrite any yaw angles.
logger.warning((
"Received combination of power_setpoints and nonzero yaw_angles for some turbines, "
+"which can not currently be handled by the FlorisStandin. Setting yaw_angles to "
+"None."
))
yaw_angles = None

if yaw_angles is None or (np.array(yaw_angles) == -1000).any():
# Note: -1000 is the "no value" flag for yaw_angles (NaNs not handled well)
yaw_misalignments = None # Floris will remember the previous yaw angles
Expand Down
12 changes: 7 additions & 5 deletions tests/floris_standin_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
from pathlib import Path

import numpy as np
import pytest
from floris import FlorisModel
from hercules.amr_wind_standin import AMRWindStandin
from hercules.floris_standin import (
Expand Down Expand Up @@ -121,7 +121,7 @@ def test_FlorisStandin_get_step_yaw_angles():
[260.0, 230.0]
)

def test_FlorisStandin_get_step_power_setpoints():
def test_FlorisStandin_get_step_power_setpoints(caplog):
floris_standin = FlorisStandin(CONFIG, AMR_INPUT, smoothing_coefficient=0.0)

# Get FLORIS equivalent, match layout and turbines
Expand Down Expand Up @@ -155,10 +155,12 @@ def test_FlorisStandin_get_step_power_setpoints():
fmodel_true_tp = fmodel_true.get_turbine_powers() / 1000
assert np.allclose(fs_tp, fmodel_true_tp.flatten().tolist())

# Test with invalid combination of yaw angles and power setpoints
with pytest.raises(ValueError):
# Test warning raise with invalid combination of yaw angles and power setpoints
with caplog.at_level(logging.WARNING):
floris_standin.get_step(5.0, yaw_angles=[230.0, 240.0], power_setpoints=[1e3, 1e3])

assert caplog.text != "" # Checking not empty
caplog.clear()

# Test with valid combination of yaw angles and power setpoints
yaw_angles = [260.0, 240.0]
power_setpoints = [None, 1e3]
Expand Down
Loading