-
Notifications
You must be signed in to change notification settings - Fork 172
Add automatic benchmarking #1062
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
Changes from 4 commits
0c96135
5ed78a8
7e54dd4
faedbd4
2ff543f
38b34f6
9038446
5b34a5b
f7aec43
6640ddc
1a6eb6a
dc2743e
514cd8d
5b04bc5
e78de5d
9917835
62505c9
17d992f
6b4d203
77f18b5
148d50e
2642de9
41305a8
48932fa
3d29d75
eb45ab4
7309bfd
b769ad7
cdc2ebc
ff657e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
name: Floris Benchmark | ||
# on: | ||
|
||
on: | ||
schedule: | ||
- cron: '0 3 * * *' # Runs daily at 3am UTC | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
branches: | ||
- main | ||
workflow_dispatch: # Allows manual triggering of the workflow | ||
|
||
|
||
permissions: | ||
# deployments permission to deploy GitHub pages website | ||
deployments: write | ||
# contents permission to update benchmark contents in gh-pages branch | ||
contents: write | ||
|
||
jobs: | ||
benchmark: | ||
name: Run FLORIS benchmarks | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
python-version: ["3.13"] | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
- name: Install project | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install -e ".[develop]" | ||
- name: Run benchmark | ||
run: | | ||
cd benchmarks | ||
pytest bench.py --benchmark-json output.json | ||
- name: Store benchmark result | ||
uses: benchmark-action/github-action-benchmark@v1 | ||
with: | ||
name: Python Benchmark with pytest-benchmark | ||
tool: 'pytest' | ||
output-file-path: benchmarks/output.json | ||
# Use personal access token instead of GITHUB_TOKEN due to https://github.community/t/github-action-not-triggering-gh-pages-upon-push/16096 | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
auto-push: true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
from pathlib import Path | ||
|
||
import numpy as np | ||
import pytest | ||
|
||
from floris import ( | ||
FlorisModel, | ||
TimeSeries, | ||
) | ||
from floris.core.turbine.operation_models import POWER_SETPOINT_DEFAULT | ||
from floris.heterogeneous_map import HeterogeneousMap | ||
|
||
|
||
TEST_DATA = Path(__file__).resolve().parent / "data" | ||
YAML_INPUT = TEST_DATA / "input_full.yaml" | ||
|
||
N_Conditions = 100 | ||
|
||
|
||
def test_timing_small_farm_set(benchmark): | ||
"""Timing test for setting up a small farm""" | ||
fmodel = FlorisModel(configuration=YAML_INPUT) | ||
wind_directions = np.linspace(0, 360, N_Conditions) | ||
wind_speeds = np.ones(N_Conditions) * 8 | ||
turbulence_intensities = np.ones(N_Conditions) * 0.06 | ||
|
||
benchmark( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to mention how this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a comment above, that is a confusing practice but it's a pattern I've seen before, |
||
fmodel.set, | ||
wind_directions=wind_directions, | ||
wind_speeds=wind_speeds, | ||
turbulence_intensities=turbulence_intensities, | ||
) | ||
|
||
|
||
def test_timing_small_farm_run(benchmark): | ||
"""Timing test for running a small farm""" | ||
fmodel = FlorisModel(configuration=YAML_INPUT) | ||
wind_directions = np.linspace(0, 360, N_Conditions) | ||
wind_speeds = np.ones(N_Conditions) * 8 | ||
turbulence_intensities = np.ones(N_Conditions) * 0.06 | ||
|
||
fmodel.set( | ||
wind_directions=wind_directions, | ||
wind_speeds=wind_speeds, | ||
turbulence_intensities=turbulence_intensities, | ||
) | ||
|
||
benchmark(fmodel.run) | ||
|
||
|
||
def test_timing_large_farm_set(benchmark): | ||
"""Timing test for setting up a large farm""" | ||
fmodel = FlorisModel(configuration=YAML_INPUT) | ||
wind_directions = np.linspace(0, 360, N_Conditions) | ||
wind_speeds = np.ones(N_Conditions) * 8 | ||
turbulence_intensities = np.ones(N_Conditions) * 0.06 | ||
|
||
benchmark( | ||
fmodel.set, | ||
wind_directions=wind_directions, | ||
wind_speeds=wind_speeds, | ||
turbulence_intensities=turbulence_intensities, | ||
layout_x=np.linspace(0, 1000, 100), | ||
layout_y=np.linspace(0, 1000, 100), | ||
) | ||
|
||
|
||
def test_timing_large_farm_run(benchmark): | ||
"""Timing test for running a large farm""" | ||
fmodel = FlorisModel(configuration=YAML_INPUT) | ||
wind_directions = np.linspace(0, 360, N_Conditions) | ||
wind_speeds = np.ones(N_Conditions) * 8 | ||
turbulence_intensities = np.ones(N_Conditions) * 0.06 | ||
|
||
fmodel.set( | ||
wind_directions=wind_directions, | ||
wind_speeds=wind_speeds, | ||
turbulence_intensities=turbulence_intensities, | ||
layout_x=np.linspace(0, 1000, 100), | ||
layout_y=np.linspace(0, 1000, 100), | ||
) | ||
|
||
benchmark(fmodel.run) | ||
|
||
|
||
def test_timing_het_set(benchmark): | ||
"""Timing test for setting up a farm with a heterogeneous map""" | ||
|
||
# The side of the flow which is accelerated reverses for east versus west | ||
het_map = HeterogeneousMap( | ||
x=np.array([0.0, 0.0, 500.0, 500.0]), | ||
y=np.array([0.0, 500.0, 0.0, 500.0]), | ||
speed_multipliers=np.array( | ||
[ | ||
[1.0, 2.0, 1.0, 2.0], # Top accelerated | ||
[2.0, 1.0, 2.0, 1.0], # Bottom accelerated | ||
] | ||
), | ||
wind_directions=np.array([270.0, 90.0]), | ||
wind_speeds=np.array([8.0, 8.0]), | ||
) | ||
|
||
# Get the FLORIS model | ||
fmodel = FlorisModel(configuration=YAML_INPUT) | ||
|
||
time_series = TimeSeries( | ||
wind_directions=np.linspace(0, 360, N_Conditions), | ||
wind_speeds=8.0, | ||
turbulence_intensities=0.06, | ||
heterogeneous_map=het_map, | ||
) | ||
|
||
# Set the model to a turbines perpendicular to | ||
# east/west flow with 0 turbine closer to bottom and | ||
# turbine 1 closer to top | ||
benchmark( | ||
fmodel.set, | ||
wind_data=time_series, | ||
layout_x=[250.0, 250.0], | ||
layout_y=[100.0, 400.0], | ||
) | ||
|
||
|
||
def test_timing_het_run(benchmark): | ||
"""Timing test for running a farm with a heterogeneous map""" | ||
|
||
# The side of the flow which is accelerated reverses for east versus west | ||
het_map = HeterogeneousMap( | ||
x=np.array([0.0, 0.0, 500.0, 500.0]), | ||
y=np.array([0.0, 500.0, 0.0, 500.0]), | ||
speed_multipliers=np.array( | ||
[ | ||
[1.0, 2.0, 1.0, 2.0], # Top accelerated | ||
[2.0, 1.0, 2.0, 1.0], # Bottom accelerated | ||
] | ||
), | ||
wind_directions=np.array([270.0, 90.0]), | ||
wind_speeds=np.array([8.0, 8.0]), | ||
) | ||
|
||
# Get the FLORIS model | ||
fmodel = FlorisModel(configuration=YAML_INPUT) | ||
|
||
time_series = TimeSeries( | ||
wind_directions=np.linspace(0, 360, N_Conditions), | ||
wind_speeds=8.0, | ||
turbulence_intensities=0.06, | ||
heterogeneous_map=het_map, | ||
) | ||
|
||
# Set the model to a turbines perpendicular to | ||
# east/west flow with 0 turbine closer to bottom and | ||
# turbine 1 closer to top | ||
fmodel.set( | ||
wind_data=time_series, | ||
layout_x=[250.0, 250.0], | ||
layout_y=[100.0, 400.0], | ||
) | ||
|
||
benchmark(fmodel.run) |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it necessary to add another input file? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have a small chicken-egg thing with default, plan it to move to that when it catches up to main |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
|
||
name: test_input | ||
description: Single turbine for testing | ||
floris_version: v4 | ||
|
||
logging: | ||
console: | ||
enable: false | ||
level: WARNING | ||
file: | ||
enable: false | ||
level: WARNING | ||
|
||
solver: | ||
type: turbine_grid | ||
turbine_grid_points: 3 | ||
|
||
farm: | ||
layout_x: | ||
- 0.0 | ||
layout_y: | ||
- 0.0 | ||
turbine_type: | ||
- nrel_5MW | ||
|
||
flow_field: | ||
air_density: 1.225 | ||
reference_wind_height: 90.0 | ||
turbulence_intensities: | ||
- 0.06 | ||
wind_directions: | ||
- 270.0 | ||
wind_shear: 0.12 | ||
wind_speeds: | ||
- 8.0 | ||
wind_veer: 0.0 | ||
|
||
wake: | ||
model_strings: | ||
combination_model: sosfs | ||
deflection_model: gauss | ||
turbulence_model: crespo_hernandez | ||
velocity_model: gauss | ||
|
||
enable_secondary_steering: true | ||
enable_yaw_added_recovery: true | ||
enable_active_wake_mixing: true | ||
enable_transverse_velocities: true | ||
|
||
wake_deflection_parameters: | ||
gauss: | ||
ad: 0.0 | ||
alpha: 0.58 | ||
bd: 0.0 | ||
beta: 0.077 | ||
dm: 1.0 | ||
ka: 0.38 | ||
kb: 0.004 | ||
jimenez: | ||
ad: 0.0 | ||
bd: 0.0 | ||
kd: 0.05 | ||
|
||
wake_velocity_parameters: | ||
cc: | ||
a_s: 0.179367259 | ||
b_s: 0.0118889215 | ||
c_s1: 0.0563691592 | ||
c_s2: 0.13290157 | ||
a_f: 3.11 | ||
b_f: -0.68 | ||
c_f: 2.41 | ||
alpha_mod: 1.0 | ||
gauss: | ||
alpha: 0.58 | ||
beta: 0.077 | ||
ka: 0.38 | ||
kb: 0.004 | ||
jensen: | ||
we: 0.05 | ||
turboparkgauss: | ||
A: 0.04 | ||
include_mirror_wake: True | ||
|
||
wake_turbulence_parameters: | ||
crespo_hernandez: | ||
initial: 0.01 | ||
constant: 0.9 | ||
ai: 0.83 | ||
downstream: -0.25 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this would ultimately go into the docs, you might consider combining this whole job in the
deploy-pages
workflowThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You know, that would work! Nice idea, @misi9170 ok with you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah no issues for me