Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: pre-commit

on:
pull_request:
push:
branches: [main, develop]

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# CHANGELOG

## v0.7 - 12 January 2026

- Supports WOMBAT v0.13.1+ to ensure the latest bug fixes and data updates are available to all users.
- Supports ORBIT v.1.2.6+ to ensure the latest bug fixes, features, data updates are available to all users.
- Updates the COWER example for the 2025 reporting cycle.
- Removes `library/base_2022` in favor of a `libray/base` for base assumptions and scenarios that
can be updated annually as needed.
- A pre-commit workflow is added to be run against PRs into the main and develop branches to ensure
code quality checks are passed.

## v0.6.2 - 1 December 2025

- Pins `jupyter-book` to "<2" to avoid v2 migration issues prior to testing.
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,20 @@ reference guide, and examples.

## Requirements

Python 3.10+, preferably 3.12
Python 3.10+

## Environment Setup

Download the latest version of [Miniconda](https://docs.conda.io/en/latest/miniconda.html)
for the appropriate OS. Follow the remaining [steps](https://conda.io/projects/conda/en/latest/user-guide/install/index.html#regular-installation)
for the appropriate OS version.

Using conda, create a new virtual environment:
Using conda, create a new virtual environment and replace "waves" with a different environment
name, if preferred:

```console
conda create -n <environment_name> python=3.12
conda activate <environment_name>
conda create -n waves python=3.14
conda activate waves
conda install -c anaconda pip
conda config --set pip_interop_enabled true

Expand Down
22 changes: 11 additions & 11 deletions docs/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
```

This section will provide a guided overview of all the components of the `Project` class that are
relevant to users, and demonstrate inputs used for the 2022 Cost of Wind Energy Review (COWER)
relevant to users, and demonstrate inputs used for the Cost of Wind Energy Review (COWER)
analysis. For a complete API reference, please refer to the [API documentation](./api.md).

## Configuring
Expand Down Expand Up @@ -55,22 +55,22 @@ analysis. For a complete API reference, please refer to the [API documentation](
:noindex:
```

### COWER 2022 Configuration
### COWER Configuration

Aligning with COWER, we have the following inputs. It should be noted that each model's
configuration is a pointer to another file to keep each configuration as tidy as possible. However,
each of `orbit_config`, `wombat_config`, and `floris_config` allow for a direct dictionary
configuration input.

```{literalinclude} ../library/base_2022/project/config/base_fixed_bottom_2022.yaml
```{literalinclude} ../library/base/project/config/base_osw_fixed.yaml
:language: yaml
:lines: 1-36
:linenos:
```

...

```{literalinclude} ../library/base_2022/project/config/base_fixed_bottom_2022.yaml
```{literalinclude} ../library/base/project/config/base_osw_fixed.yaml
:language: yaml
:linenos:
:lineno-start: 43
Expand All @@ -79,7 +79,7 @@ configuration input.

...

```{literalinclude} ../library/base_2022/project/config/base_fixed_bottom_2022.yaml
```{literalinclude} ../library/base/project/config/base_osw_fixed.yaml
:language: yaml
:linenos:
:lineno-start: 46
Expand All @@ -88,7 +88,7 @@ configuration input.

...

```{literalinclude} ../library/base_2022/project/config/base_fixed_bottom_2022.yaml
```{literalinclude} ../library/base/project/config/base_osw_fixed.yaml
:language: yaml
:linenos:
:lineno-start: 95
Expand All @@ -97,7 +97,7 @@ configuration input.

...

```{literalinclude} ../library/base_2022/project/config/base_fixed_bottom_2022.yaml
```{literalinclude} ../library/base/project/config/base_osw_fixed.yaml
:language: yaml
:linenos:
:lineno-start: 141
Expand Down Expand Up @@ -140,8 +140,8 @@ from pathlib import Path
from waves import Project
from waves.utilities import load_yaml

library_path = Path("../library/base_2022/")
config = load_yaml(library_path / "project/config", "base_fixed_bottom_2022.yaml")
library_path = Path("../library/base/")
config = load_yaml(library_path / "project/config", "base_osw_fixed.yaml")
config["library_path"] = library_path # add the library path

# Ensure FLORIS is not automatically connected
Expand Down Expand Up @@ -234,7 +234,7 @@ Visually, the following is a general flow of operations for combining each model

To quickly produce any of the high-level outputs to a single `DataFrame`, the below method can be
used in place of individually calculating each metric and combining into a report. Additionally,
users can refer to the [COWER 2022 example](example_cower_2022:results) for the reported results,
users can refer to the [COWER example](example_cower:results) for the reported results,
which relies on the `generate_report` method and accessing the ORBIT `ProjectManager` directly for
further CapEx breakdowns.

Expand Down Expand Up @@ -400,7 +400,7 @@ defined in the configuration file. The [provided example](./waves_example.md) is
be run through the CLI. Below is an example of the additional configurations

```{eval-rst}
.. literalinclude:: ../library/base_2022/project/config/base_fixed_bottom_2022.yaml
.. literalinclude:: ../library/base/project/config/base_osw_fixed.yaml
:language: yaml
:linenos:
:lineno-start: 146
Expand Down
83 changes: 39 additions & 44 deletions docs/waves_example.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ kernelspec:
name: python3
---

(example_cower_2022)=
# Cost of Wind Energy Review 2022
(example_cower)=
# Cost of Wind Energy Review: 2025 Edition

[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/NREL/WAVES/main?filepath=examples)

Be sure to install `pip install "waves[examples]"` (or `pip install ".[examples]"`) to work with
this example.

This example will walk through the process of running a subset of the 2022 Cost of Wind Energy
Review (COWER) analysis to demonstrate an analysis workflow. Please note, that this is not the exact
workflow because it has been broken down to highlight some of the key features of WAVES. Similarly,
this will stay up to date with WAVES's dependencies, namely ORBIT, WOMBAT, and FLORIS, so results
may change slightly between this *example* relying on the configurations and the published results.
This example will walk through the process of running a subset of the current year's Cost of Wind
Energy Review (COWER) analysis to demonstrate an analysis workflow. Please note, that this is not
the exact workflow because it has been broken down to highlight some of the key features of WAVES.
Similarly, this will stay up to date with WAVES's dependencies, namely ORBIT, WOMBAT, and FLORIS,
so results may change slightly between this *example* relying on the configurations and the
published results.

````{note}
To run these examples from the command line, the below command can be used, which will dipslay and
Expand All @@ -30,10 +33,10 @@ information in the command line wherever WAVES is installed.
# NOTE: This is run from the top level of WAVES/

# Run one example
waves library/base_2022 base_fixed_bottom_2022.yaml
waves library/base base_osw_fixed.yaml

# Run both examples, but don't save the results
waves library/base_2022 base_fixed_bottom_2022.yaml base_floating_2022.yaml --no-save-report
waves library/base base_osw_fixed.yaml base_osw_floating.yaml --no-save-report
```
````

Expand Down Expand Up @@ -63,22 +66,22 @@ the configurations. For a complete guide and definition, please see either the

````{warning}
If your FLORIS installation is <3.6, then the FLORIS configuration files in
`library/base_2022/project/config/` will have to be updated so that line 107 (same line number for
`library/base/project/config/` will have to be updated so that line 107 (same line number for
fixed bottom and floating) is using an absolute path like the example below.

```yaml
# original, set to work with FLORIS >= 3.6
turbine_library_path: ../../turbines

# updated absolute path, replace <path_to_waves> in your own files
turbine_library_path: <path_to_waves>/WAVES/library/base_2022/turbines/
turbine_library_path: <path_to_waves>/WAVES/library/base/turbines/
```
````

```{code-cell} ipython3
library_path = Path("../library/base_2022/")
config_fixed = load_yaml(library_path / "project/config", "base_fixed_bottom_2022.yaml")
config_floating = load_yaml(library_path / "project/config", "base_floating_2022.yaml")
library_path = Path("../library/base")
config_fixed = load_yaml(library_path / "project/config", "base_osw_fixed.yaml")
config_floating = load_yaml(library_path / "project/config", "base_osw_floating.yaml")

# This example was designed prior to the FLORIS 3.6 release, so the path to the turbine library in
# FLORIS must be manually updated, but this example must work for all users, so a dynamic method
Expand All @@ -100,19 +103,19 @@ WAVES command line interface (CLI).
config_fixed.update({"library_path": library_path,})
config_floating.update({"library_path": library_path,})

start1 = perf_counter()
start = perf_counter()

project_fixed = Project.from_dict(config_fixed)

end1 = perf_counter()
end = perf_counter()
print(f"Fixed bottom loading time: {(end-start):,.2f} seconds")

start2 = perf_counter()
start = perf_counter()

project_floating = Project.from_dict(config_floating)

end2 = perf_counter()
print(f"Fixed bottom loading time: {(end1-start1):,.2f} seconds")
print(f"Floating loading time: {(end2-start2):,.2f} seconds")
end = perf_counter()
print(f"Floating loading time: {(end-start):,.2f} seconds")
```

### Visualize the wind farm
Expand All @@ -137,37 +140,34 @@ of the year, for a more accurate energy output. However, we're using just the we
in the O&M phase: `full_wind_rose=False`.

```{code-cell} ipython3
start1 = perf_counter()
start = perf_counter()
project_fixed.run(
which_floris="wind_rose", # month-based wind rose wake analysis
full_wind_rose=False, # use the WOMBAT date range
floris_reinitialize_kwargs={"cut_in_wind_speed": 3.0, "cut_out_wind_speed": 25.0} # standard ws range
floris_kwargs={"cut_in_wind_speed": 3.0, "cut_out_wind_speed": 25.0} # standard ws range
)
project_fixed.wombat.env.cleanup_log_files() # Delete logging data from the WOMBAT simulations
end1 = perf_counter()
end = perf_counter()
print(f"Fixed run time: {end - start:,.2f} seconds")

start2 = perf_counter()
start = perf_counter()
project_floating.run(
which_floris="wind_rose",
full_wind_rose=False,
floris_reinitialize_kwargs=dict(cut_in_wind_speed=3.0, cut_out_wind_speed=25.0)
floris_kwargs=dict(cut_in_wind_speed=3.0, cut_out_wind_speed=25.0)
)
project_floating.wombat.env.cleanup_log_files() # Delete logging data from the WOMBAT simulations
end2 = perf_counter()
end = perf_counter()

print("-" * 29) # separate our timing from the ORBIT and FLORIS run-time warnings
print(f"Fixed run time: {end1 - start1:,.2f} seconds")
print(f"Floating run time: {end2 - start2:,.2f} seconds")
print(f"Floating run time: {end - start:,.2f} seconds")
```

Both of these examples can also be run via the CLI, though the FLORIS `turbine_library_path`
configuration will have to be manually updated in each file to ensure the examples run.

```console
waves path/to/library/base_2022/ base_fixed_bottom_2022.yaml base_floating_bottom_2022.yaml --no-save-report
waves path/to/library/base/ base_osw_fixed.yaml base_osw_floating.yaml --no-save-report
```

(example_cower_2022:results)=
(example_cower:results)=
## Gather the results

Another of the conveniences with using WAVES to run all three models is that some of the core
Expand Down Expand Up @@ -213,20 +213,16 @@ metrics_configuration = {
"OpEx per kW ($/kW)": {"metric": "opex", "kwargs": {"per_capacity": "kw"}},
"AEP (MWh)": {
"metric": "energy_production",
"kwargs": {"units": "mw", "aep": True, "with_losses": True}
"kwargs": {"units": "mw", "aep": True}
},
"AEP per kW (MWh/kW)": {
"metric": "energy_production",
"kwargs": {"units": "mw", "per_capacity": "kw", "aep": True, "with_losses": True}
"kwargs": {"units": "mw", "per_capacity": "kw", "aep": True}
},
"Net Capacity Factor With Wake Losses (%)": {
"Net Capacity Factor (%)": {
"metric": "capacity_factor",
"kwargs": {"which": "net"}
},
"Net Capacity Factor With All Losses (%)": {
"metric": "capacity_factor",
"kwargs": {"which": "net", "with_losses": True}
},
"Gross Capacity Factor (%)": {
"metric": "capacity_factor",
"kwargs": {"which": "gross"}
Expand Down Expand Up @@ -256,8 +252,7 @@ metrics_order = [
"Annual OpEx per kW ($/kW)",
"Energy Availability (%)",
"Gross Capacity Factor (%)",
"Net Capacity Factor With Wake Losses (%)",
"Net Capacity Factor With All Losses (%)",
"Net Capacity Factor (%)",
"AEP (MWh)",
"AEP per kW (MWh/kW)",
"LCOE ($/MWh)",
Expand Down Expand Up @@ -319,8 +314,8 @@ df_capex
Now, let's generate the report, and then add in some additional reporting variables.

```{code-cell} ipython3
project_name_fixed = "COE 2022 - Fixed"
project_name_floating = "COE 2022 - Floating"
project_name_fixed = "Fixed"
project_name_floating = "Floating"

# Generate the reports using WAVES and the above configurations
# NOTE: the results are transposed to view them more easily for the example, otherwise
Expand Down
Loading