Skip to content

Commit

Permalink
Merge pull request #1073 from NREL/develop
Browse files Browse the repository at this point in the history
FLORIS v4.3
  • Loading branch information
misi9170 authored Mar 4, 2025
2 parents fd0e599 + ba63a9a commit c50389c
Show file tree
Hide file tree
Showing 26 changed files with 974 additions and 149 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/check-working-examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
os: [ubuntu-latest] #, macos-latest, windows-latest]
fail-fast: False

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/continuous-integration-workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
os: [ubuntu-latest] #, macos-latest, windows-latest]
fail-fast: False
env:
Expand Down
59 changes: 51 additions & 8 deletions .github/workflows/deploy-pages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ on:
push:
branches:
- develop
paths:
- docs/**


workflow_dispatch: # Allows manual triggering of the workflow

# This job installs dependencies, builds the book, and pushes it to `gh-pages`
jobs:
Expand All @@ -22,7 +23,7 @@ jobs:

- name: Install dependencies
run: |
pip install -e ".[docs]"
pip install -e ".[docs, develop]"
# Make a copy of the examples folder within the docs folder
- name: Copy examples to docs
Expand All @@ -35,12 +36,8 @@ jobs:
- name: Convert examples to notebooks
working-directory: ${{runner.workspace}}/floris/docs/examples/
run: |
# Print the working directory
pwd
# Show the contents
ls
python _convert_examples_to_notebooks.py
# Build the book
Expand All @@ -51,7 +48,53 @@ jobs:
# Push the book's HTML to github-pages
- name: GitHub Pages action
uses: peaceiris/actions-gh-pages@v3.6.1
uses: peaceiris/actions-gh-pages@v4.0.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/_build/html

# Stash changes before benchmark action
- name: Stash changes
working-directory: ${{runner.workspace}}/floris/
run: |
git stash
- name: Run benchmark
working-directory: ${{runner.workspace}}/floris/
run: |
ls -lah
cd benchmarks
pytest bench.py --benchmark-json output.json
# Store benchmark result and create the benchmark pages
# Update the index.html and data.js files in the
# dev/bench folder of the benches branch
# dev/bench is the default folder for pytest-benchmark
- 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
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
gh-pages-branch: benches

# Add bench mark files to the gh-pages branch
- name: Add benchmark files to gh-pages
working-directory: ${{runner.workspace}}/floris/
run: |
ls -lah
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
git fetch origin benches
git checkout benches
rsync -av dev/bench /tmp/bench
git fetch origin gh-pages
git checkout gh-pages
mkdir -p dev
rsync -av /tmp/bench/ dev/
ls -lah dev/bench
git add dev
git commit -m "Add bench folder to gh-pages"
git push origin gh-pages
4 changes: 2 additions & 2 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
pip install build twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
python -m build
twine upload dist/*
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ repos:
- id: mixed-line-ending

- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.241
rev: v0.9.6
hooks:
- id: ruff

Expand Down
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
FLORIS is a controls-focused wind farm simulation software incorporating
steady-state engineering wake models into a performance-focused Python
framework. It has been in active development at NREL since 2013 and the latest
release is [FLORIS v4.2.2](https://github.com/NREL/floris/releases/latest).
release is [FLORIS v4.3](https://github.com/NREL/floris/releases/latest).
Online documentation is available at https://nrel.github.io/floris.

The software is in active development and engagement with the development team
Expand All @@ -13,9 +13,6 @@ the conversation in [GitHub Discussions](https://github.com/NREL/floris/discussi

## Installation

**WARNING:**
Support for python version 3.8 will be dropped in FLORIS v4.3. See [Installation documentation](https://nrel.github.io/floris/installation.html#installation) for details.

**If upgrading from a previous version, it is recommended to install FLORIS v4 into a new virtual environment**.
If you intend to use [pyOptSparse](https://mdolab-pyoptsparse.readthedocs-hosted.com/en/latest/) with FLORIS,
it is recommended to install that package first before installing FLORIS.
Expand Down Expand Up @@ -82,7 +79,7 @@ PACKAGE CONTENTS
wind_data

VERSION
4.2.2
4.3

FILE
~/floris/floris/__init__.py
Expand Down
163 changes: 163 additions & 0 deletions benchmarks/bench.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
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


N_Conditions = 100

# These tests are run automatically by pytest-benchmark. The benchmark
# object is passed to the test function.

def test_timing_small_farm_set(benchmark):
"""Timing test for setting up a small farm"""
fmodel = FlorisModel(configuration="defaults")
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, 3),
layout_y=np.linspace(0, 1000, 3),
)


def test_timing_small_farm_run(benchmark):
"""Timing test for running a small farm"""
fmodel = FlorisModel(configuration="defaults")
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, 3),
layout_y=np.linspace(0, 1000, 3),
)

benchmark(fmodel.run)


def test_timing_large_farm_set(benchmark):
"""Timing test for setting up a large farm"""
fmodel = FlorisModel(configuration="defaults")
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, 10000, 100),
layout_y=np.linspace(0, 10000, 100),
)


def test_timing_large_farm_run(benchmark):
"""Timing test for running a large farm"""
fmodel = FlorisModel(configuration="defaults")
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, 10000, 100),
layout_y=np.linspace(0, 10000, 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="defaults")

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="defaults")

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)
Loading

0 comments on commit c50389c

Please sign in to comment.