diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml new file mode 100644 index 000000000..b9a8f0316 --- /dev/null +++ b/.github/workflows/benchmark.yaml @@ -0,0 +1,61 @@ +name: Floris Benchmark +on: + schedule: + - cron: '0 3 * * *' # Runs daily at 3am UTC + workflow_dispatch: # Allows manual triggering of the workflow + +permissions: + contents: write + deployments: write + +jobs: + benchmark: + name: Run FLORIS benchmarks + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.9, 3.10, 3.11] # Or whichever versions you support + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + 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 + # Show alert with commit comment on detecting possible performance regression + # alert-threshold: '200%' + # comment-on-alert: true + # fail-on-alert: true + # alert-comment-cc-users: '@ktrz' + + - name: Store benchmark result - separate results repo + 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.BENCHMARK_ACTION_BOT_TOKEN }} + auto-push: true + # Show alert with commit comment on detecting possible performance regression + # alert-threshold: '200%' + # comment-on-alert: true + # fail-on-alert: true + # alert-comment-cc-users: '@ktrz' + # gh-repository: 'github.com/benchmark-action/github-action-benchmark-results' diff --git a/benchmarks/bench.py b/benchmarks/bench.py new file mode 100644 index 000000000..e31934384 --- /dev/null +++ b/benchmarks/bench.py @@ -0,0 +1,44 @@ + +from pathlib import Path + +import numpy as np +import pytest + +from floris import ( + FlorisModel, +) +from floris.core.turbine.operation_models import POWER_SETPOINT_DEFAULT + + +TEST_DATA = Path(__file__).resolve().parent / "data" +YAML_INPUT = TEST_DATA / "input_full.yaml" + +N = 100 + +def test_benchmark_set(benchmark): + fmodel = FlorisModel(configuration=YAML_INPUT) + wind_directions = np.linspace(0, 360, N) + wind_speeds = np.ones(N) * 8 + turbulence_intensities = np.ones(N) * 0.06 + + benchmark( + fmodel.set, + wind_directions=wind_directions, + wind_speeds=wind_speeds, + turbulence_intensities=turbulence_intensities, + ) + + +def test_benchmark_run(benchmark): + fmodel = FlorisModel(configuration=YAML_INPUT) + wind_directions = np.linspace(0, 360, N) + wind_speeds = np.ones(N) * 8 + turbulence_intensities = np.ones(N) * 0.06 + + fmodel.set( + wind_directions=wind_directions, + wind_speeds=wind_speeds, + turbulence_intensities=turbulence_intensities, + ) + + benchmark(fmodel.run) diff --git a/benchmarks/data/input_full.yaml b/benchmarks/data/input_full.yaml new file mode 100644 index 000000000..49c41273d --- /dev/null +++ b/benchmarks/data/input_full.yaml @@ -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 diff --git a/setup.py b/setup.py index b3532ffd5..b8531cc31 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ }, "develop": { "pytest", + "pytest-benchmark" "pre-commit", "ruff", "isort",