How to Use WAVES#

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) analysis. For a complete API reference, please refer to the API documentation.

Configuring#

The Project Class#

class waves.project.Project(library_path, weather_profile, orbit_config=None, wombat_config=None, floris_config=None, orbit_start_date=None, orbit_weather_cols=['windspeed', 'wave_height'], floris_windspeed='windspeed', floris_wind_direction='wind_direction', floris_x_col='floris_x', floris_y_col='floris_y', connect_floris_to_layout=True, connect_orbit_array_design=True, offtake_price=None, fixed_charge_rate=0.0582, discount_rate=None, finance_rate=None, reinvestment_rate=None, loss_ratio=None, soft_capex_date=None, project_capex_date=None, system_capex_date=None, turbine_capex_date=None, report_config=None)[source]

The unified interface for creating, running, and assessing analyses that combine ORBIT, WOMBAT, and FLORIS.

Parameters:
  • library_path (str | pathlib.Path) -- The file path where the configuration data for ORBIT, WOMBAT, and FLORIS can be found.

  • weather_profile (str | pathlib.Path) --

    The file path where the weather profile data is located, with the following column requirements:

    • datetime: The timestamp column

    • orbit_weather_cols: see orbit_weather_cols

    • floris_windspeed: see floris_windspeed

    • floris_wind_direction: see floris_wind_direction

  • orbit_weather_cols (list[str]) -- The windspeed and wave height column names in weather to use for running ORBIT. Defaults to ["windspeed", "wave_height"].

  • floris_windspeed (str) -- The windspeed column in weather that will be used for the FLORIS wake analysis. Defaults to "windspeed_100m".

  • floris_wind_direction (str) -- The wind direction column in weather that will be used for the FLORIS wake analysis. Defaults to "wind_direction_100m".

  • floris_x_col (str) -- The column of x-coordinates in the WOMBAT layout file that corresponds to the Floris.farm.layout_x Defaults to "floris_x".

  • floris_y_col (str) -- The column of x-coordinates in the WOMBAT layout file that corresponds to the Floris.farm.layout_y Defaults to "floris_y".

  • orbit_config (str | pathlib.Path | dict | None) -- The ORBIT configuration file name or dictionary. If None, will not set up the ORBIT simulation component.

  • wombat_config (str | pathlib.Path | dict | None) -- The WOMBAT configuration file name or dictionary. If None, will not set up the WOMBAT simulation component.

  • floris_config (str | pathlib.Path | dict | None) -- The FLORIS configuration file name or dictionary. If None, will not set up the FLORIS simulation component.

  • connect_floris_to_layout (bool, optional) --

    If True, automatically connect the FLORIS and WOMBAT layout files, so that the simulation results can be linked. If False, don't connec the two models. Defaults to True.

    Note

    This should only be set to False if the FLORIS and WOMBAT layouts need to be connected in an additional step

  • connect_orbit_array_design (bool, optional) -- If True, the ORBIT array cable lengths will be calculated on initialization and added into the primary layout file.

  • offtake_price (float, optional) -- The price paid per MWh of energy produced. Defaults to None.

  • fixed_charge_rate (float, optional) -- Revenue per amount of investment required to cover the investment cost, with the default provided through the NREL 2021 Cost of Energy report [1]_. Defaults to 0.0582.

  • discount_rate (float, optional) -- The minimum acceptable rate of return, or the assumed return on an alternative investment of comparable risk. Defaults to None.

  • finance_rate (float, optional) -- Interest rate paid on the cash flows. Defaults to None.

  • reinvestment_rate (float, optional) -- Interest rate paid on the cash flows upon reinvestment. Defaults to None.

  • loss_ratio (float, optional) -- Additional non-wake losses to deduct from the total energy production. Should be represented as a decimal in the range of [0, 1]. Defaults to None.

  • orbit_start_date (str | None) -- The date to use for installation phase start timings that are set to "0" in the install_phases configuration. If None the raw configuration data will be used. Defaults to None.

  • soft_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT soft CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None

  • project_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT project CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None

  • system_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT system CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None.

  • turbine_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT turbine CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None.

  • report_config (dict[str, dict], optional) -- A dictionary that can be passed to generate_report(), and be used as the metrics_configuration dictionary. An additional field of name is required as input, which will be passed to simulation_name. Defaults to None.

References

report_config: dict[str, dict] | None
validate_report_config(attribute, value)[source]

Validates the user input for report_config.

Return type:

None

Parameters:
  • attribute (attrs.Attribute) -- The attrs Attribute information/metadata/configuration.

  • value (dict | None) -- _description_

Raises:
  • ValueError -- Raised if report_config is not a dictionary.

  • KeyError -- Raised if report_config does not contain a key, value pair for "name".

Working With Configurations#

classmethod Project.from_file(library_path, config_file)[source]

Creates a Project object from either a JSON or YAML file. See Project for configuration requirements.

Return type:

Project

Parameters:
  • library_path (str | Path) -- The library path to be used in the simulation.

  • config_file (str | Path) -- The configuration file to create a Project object from, which should be located at: library_path / project / config / config_file.

Raises:
  • FileExistsError -- Raised if library_path is not a valid directory.

  • ValueError -- Raised if config_file is not a JSON or YAML file.

Returns:

Project -- An initialized Project object.

property Project.config_dict: dict

Generates a configuration dictionary that can be saved to a new file for later re/use.

Returns:

dict -- YAML-safe dictionary of a Project-loadable configuration.

Project.save_config(config_file)[source]

Saves a copy of the Project configuration settings to recreate the results of the current settings.

Return type:

None

Parameters:

config_file (str | Path) -- The name to use for saving to a YAML configuration file.

COWER 2022 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.

 1# Primary model configurations
 2orbit_config: base_fixed_bottom_2022_install.yaml
 3wombat_config: base_fixed_bottom_2022_operations.yaml
 4floris_config: base_fixed_bottom_2022_floris_jensen.yaml
 5weather_profile: era5_40.0N_72.5W_1990_2020.csv
 6
 7# Shared input connections
 8orbit_start_date: 1/1/1998
 9orbit_weather_cols:
10- windspeed_100m
11- windspeed_10m
12- waveheight
13floris_wind_direction: wind_direction_100m
14floris_windspeed: windspeed_100m
15floris_x_col: floris_x
16floris_y_col: floris_y
17
18# Create the necessary connections
19# NOTE: these are default values, but worth highlighting for an example
20connect_floris_to_layout: true
21conenct_orbit_array_design: true
22
23# High-level project financials
24discount_rate: 0.025
25fixed_charge_rate: 0.0648 # real FCR from national LCOE study, 25 year lifetime instead of 30
26loss_ratio: 0.1
27offtake_price: 83.30
28
29# Cash flow settings
30project_capex_date:
31- !!python/tuple
32  - 1996
33  - 1
34- !!python/tuple
35  - 1996
36  - 7

...

43soft_capex_date: !!python/tuple

...

46system_capex_date:

...

95turbine_capex_date:

...

141- !!python/tuple
142  - 1999
143  - 10

Connecting Configurations#

Also, see the configurations Project.connect_floris_to_layout and Project.connect_orbit_array_design to automatically run the below during project initialization.

The following method is run on intialization when Project.connect_floris_to_layout is set to True, which is the case in the COWER example.

Project.connect_floris_to_turbines(x_col='floris_x', y_col='floris_y')[source]

Generates floris_turbine_order from the WOMBAT Windfarm.layout_df.

Parameters:
  • x_col (str, optional) -- The column name in the layout corresponding to the FLORIS x poszitions, by default "floris_x".

  • y_col (str, optional) -- The column name in the layout corresponding to the FLORIS y positions, by default "floris_y".

Visually, this looks like the following workflow:

_images/input_flow.svg

Updating Configurations#

Sometimes, additional configurations may need to be connected prior to running an analysis. For instance, it may be cumbersome to manually compute the FLORIS layout from a traditional coordinate system, such as WGS-84, or a localized distance-based coordinate reference system. In the latter, WAVES can help with the generate_floris_positions_from_layout method. However, as can be seen below, the following generation method has to be run prior to connecting the FLORIS and ORBIT/WOMBAT layouts. As such, your workflow leading up to an analysis might look like the following.

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")
config["library_path"] = library_path  # add the library path

# Ensure FLORIS is not automatically connected
config["connect_floris_to_turbines"] = False

project = Project.from_dict(config)

# Generate the layout and connect FLORIS
project.generate_floris_positions_from_layout()  # note the defaults in the section below
project.connect_floris_to_turbines()
Project.generate_floris_positions_from_layout(x_col='easting', y_col='northing', update_config=True, config_fname=None)[source]

Updates the FLORIS layout_x and layout_y based on the relative coordinates from the WOMBAT layout file.

Return type:

None

Parameters:
  • x_col (str, optional) -- The relative, distance-based x-coordinate column name. Defaults to "easting".

  • y_col (str, optional) -- The relative, distance-based y-coordinate column name. Defaults to "northing".

  • update_config (bool, optional) -- Run FlorisInterface.reinitialize with the updated layout_x and layout_y values. Defaults to True.

  • config_fname (str | None, optional) -- Provide a file name if update_config and this new configuration should be saved. Defaults to None.

The following method allows users to connect the ORBIT-calculated cable lengths and insert them back into the layout configuration file. This is helpful if the base distance is to be computed, then reused later, without re-calculating, or after modifying, if desired.

Project.connect_orbit_cable_lengths(save_results=True)[source]

Runs the ORBIT design phases, so that the array system has computed the necessary cable length and distance measures, then attaches the cable length calculations back to the layout file, saves the results to the layout files, and reloads both ORBIT and WOMBAT with this data.

Return type:

None

Parameters:

save_results (bool, optional) -- Save the resulting, updated layout table to both library_path/project/plant/wombat_config_dict["layout"] and library_path/cables/wombat_config_dict["layout"] for WOMBAT and ORBIT compatibility, respectively.

Project.reinitialize(orbit_config=None, wombat_config=None, floris_config=None)[source]

Enables a user to reinitialize one or multiple of the CapEx, OpEx, and AEP models.

Return type:

None

Parameters:
  • orbit_config (str | Path | dict | None, optional) -- ORBIT configuration file or dictionary. Defaults to None.

  • wombat_config (str | Path | dict | None, optional) -- WOMBAT configuation file or dictionary. Defaults to None.

  • floris_config ((str | Path | dict | None, optional) -- FLORIS configuration file or dictionary. Defaults to None.

Viewing the Wind Farm Properties#

For the following set of methods, users only need to create a Project object in order to use.

Project.plot_farm(figure_kwargs=None, draw_kwargs=None, return_fig=False)[source]

Plot the graph representation of the windfarm as represented through WOMBAT.

Return type:

None | tuple[figure, axes]

Parameters:
  • figure_kwargs (dict | None, optional) -- Customized keyword arguments for matplotlib figure instantiation that will passed as plt.figure(**figure_kwargs). Defaults to None.

  • draw_kwargs (dict | None, optional) -- Customized keyword arguments for networkx.draw() that can will passed as nx.draw(**figure_kwargs). Defaults to None.

  • return_fig (bool, optional) -- Whether or not to return the figure and axes objects for further editing and/or saving. Defaults to False.

Returns:

None | tuple[plt.figure, plt.axes] -- If return_fig is False, then None is returned, otherwise (True) the Figure and Axes objects are returned.

Project.n_turbines()[source]

Returns the number of turbines from either ORBIT, WOMBAT, or FLORIS depending on which model is available internally.

Return type:

int

Returns:

int -- The number of turbines in the project.

Raises:

RuntimeError -- Raised if no model configurations were provided on initialization.

Project.n_substations()[source]

Calculates the number of subsations in the project.

Return type:

int

Returns:

int -- The number of substations in the project.

Project.capacity(units='mw')[source]

Calculates the project's capacity in the desired units of kW, MW, or GW.

Return type:

float

Parameters:

units (str, optional) -- One of "kw", "mw", or "gw". Defaults to "mw".

Returns:

float -- The project capacity, returned in the desired units

Raises:
  • RuntimeError -- Raised if no model configurations were provided on initialization.

  • ValueError -- Raised if an invalid units input was provided.

Project.turbine_rating()[source]

Calculates the average turbine rating, in MW, of all the turbines in the project.

Return type:

float

Returns:

float -- The average rating of the turbines, in MW.

Raises:

RuntimeError -- Raised if no model configurations were provided on initialization.

Running the Models#

Project.run(which_floris=None, floris_reinitialize_kwargs=None, floris_run_kwargs=None, full_wind_rose=False, skip=None, cut_in_wind_speed=0.001, cut_out_wind_speed=None, nodes=-1)[source]

Run all three models in serial, or a subset if skip is used.

Return type:

None

Parameters:
  • which_floris (str | None, optional) -- One of "wind_rose" or "time_series" if computing the farm's AEP based on a wind rose, or based on time series corresponding to the WOMBAT simulation period, respectively. Defaults to None.

  • floris_reinitialize_kwargs (dict | None) -- Any additional FlorisInterface.reinitialize keyword arguments. Defaults to None.

  • floris_run_kwargs (dict | None) -- Any additional FlorisInterface.get_farm_AEP or FlorisInterface.calculate_wake() keyword arguments, depending on which_floris is used. Defaults to None.

  • full_wind_rose (bool, optional) -- Indicates, for "wind_rose" analyses ONLY, if the full weather profile from weather (True) or the limited, WOMBAT simulation period (False) should be used for analyis. Defaults to False.

  • skip (list[str] | None, optional) -- A list of models to be skipped. This is intended to be used after a model is reinitialized with a new or modified configuration. Defaults to None.

  • cut_in_wind_speed (float, optional) -- The wind speed, in m/s, at which a turbine will start producing power. Can also be provided in floris_reinitialize_kwargs for a wind rose analysis, but must be provided here for a time series analysis. Defaults to 0.001.

  • cut_out_wind_speed (float, optional) -- The wind speed, in m/s, at which a turbine will stop producing power. Can also be provided in floris_reinitialize_kwargs for a wind rose analysis, but must be provided here for a time series analysis. Defaults to None.

  • nodes (int, optional) -- The number of nodes to parallelize over. If -1, then it will use the floor of 80% of the available CPUs on the computer. Defaults to -1.

Raises:

ValueError -- Raised if which_floris is not one of "wind_rose" or "time_series".

Results#

Visually, the following is a general flow of operations for combining each model's outputs:

_images/results_flow.svg

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 for the reported results, which relies on the generate_report method and accessing the ORBIT ProjectManager directly for further CapEx breakdowns.

Project.generate_report(metrics_configuration=None, simulation_name=None)[source]

Generates a single row dataframe of all the desired resulting metrics from the project. :rtype: DataFrame

Note

This assumes all results will be a single number, and not a Pandas DataFrame

Parameters:
  • metrics_dict (dict[str, dict], optional) --

    The dictionary of dictionaries containing the following key, value pair pattern:

    {
        "Descriptive Name (units)": {
            "metric": "metric_method_name",
            "kwargs": {"kwarg1": "kwarg_value_1"}  # Exclude if not needed
        }
    }
    

    For metrics that have no keyword arguments, or where the default parameter values are desired, either an empty dictionary or no dictionary input for "kwargs" is allowed. If no input is provided, then report_config will be used to populate

  • simulation_name (str) -- The name that should be given to the resulting index.

  • metrics_configuration (dict[str, dict] | None)

Returns:

pd.DataFrame -- A pandas.DataFrame containing all of the provided outputs defined in metrics_dict.

Raises:

ValueError -- Raised if any of the keys of metrics_dict aren't implemented methods.

Return type:

DataFrame

All the models can be individually accessed to calculate results that are not integrated into WAVES officially, but it should be noted that they should be used with caution in case there are any interdependencies between model outputs.

Project.orbit: ProjectManager
Project.wombat: Simulation
Project.floris: FlorisInterface

Balance of Systems Costs and Properties#

Project.capex(breakdown=False, per_capacity=None)[source]

Provides a thin wrapper to ORBIT's ProjectManager CapEx calculations that can provide a breakdown of total or normalize it by the project's capacity, in MW.

Return type:

DataFrame | float

Parameters:
  • breakdown (bool, optional) -- Provide a detailed view of the CapEx breakdown, and a total, which is the sum of the BOS, turbine, project, and soft CapEx categories. Defaults to False.

  • per_capacity (str, optional) -- Provide the CapEx normalized by the project's capacity, in the desired units. If None, then the unnormalized CapEx is returned, otherwise it must be one of "kw", "mw", or "gw". Defaults to None.

Returns:

pd.DataFrame | float -- Project CapEx, normalized by per_capacity, if using, as either a pandas DataFrame if breakdown is True, otherwise, a float total.

Project.capex_breakdown(frequency='month-year', installation_start_date=None, soft_capex_date=None, project_capex_date=None, system_capex_date=None, turbine_capex_date=None, breakdown=False)[source]

Calculates the monthly CapEx breakdwon into a DataFrame, that is returned at the desired frequency, allowing for custom starting dates for the varying CapEx costs.

Return type:

DataFrame

Parameters:
  • frequency (str, optional) -- The desired frequency of the outputs, where "month-year" is the monthly total over the course of a project's life. Must be one of: "project", "annual", "month-year". Defaults to "month-year"

  • installation_start_date (str | None, optional) -- If not provided in the Project configuration as orbit_start_date, an installation starting date that is parseable from a string by Pandas may be provided here. Defaults to None

  • soft_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT soft CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None

  • project_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT project CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None

  • system_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT system CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None.

  • turbine_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT turbine CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None.

  • offtake_price (int | float | None, optional) -- The price paid for the energy produced, by default None.

  • breakdown (bool, optional) -- If True, all the CapEx categories will be provided as a column, in addition to the OpEx and Revenue columns, and the total cost in "cash_flow", othwerwise, only the "cash_flow" column will be provided. Defaults to False.

Returns:

pd.DataFrame -- Returns the pandas DataFrame of the cashflow with a fixed monthly or annual interval, or a project total for the desired categories.

Raises:
  • ValueError -- Raised if frequency is not one of: "project", "annual", "month-year".

  • TypeError -- Raised if a valid starting date can't be found for the installation.

Project.array_system_total_cable_length()[source]

Calculates the total length of the cables in the array system, in km.

Returns:

float -- Total length, in km, of the array system cables.

Raises:

ValueError -- Raised if neither ArraySystemDesign nor CustomArraySystem design were created in ORBIT.

Project.export_system_total_cable_length()[source]

Calculates the total length of the cables in the export system, in km.

Returns:

float -- Total length, in km, of the export system cables.

Raises:

ValueError -- Raised if ExportSystemDesign was not created in ORBIT.

Operations and Maintenance Costs#

Project.opex(frequency='project', per_capacity=None)[source]

Calculates the operational expenditures of the project.

Return type:

DataFrame | float

Parameters:
  • (str (frequency) -- Defaults to "project".

  • optional) (One of "project", "annual", "monthly", "month-year".) -- Defaults to "project".

  • per_capacity (str, optional) -- Provide the OpEx normalized by the project's capacity, in the desired units. If None, then the unnormalized OpEx is returned, otherwise it must be one of "kw", "mw", or "gw". Defaults to None.

  • frequency (str)

Returns:

pd.DataFrame | float -- The resulting OpEx DataFrame at the desired frequency, if more granular than the project frequency, otherwise a float. This will be normalized by the capacity, if per_capacity is not None.

Project.availability(which, frequency='project', by='windfarm')[source]

Calculates the availability based on either a time or energy basis. This is a thin wrapper around self.wombat.metrics.time_based_availability() or self.wombat.metrics.production_based_availability().

Return type:

DataFrame | float

Parameters:
  • which (str) -- One of "energy" or "time" to indicate which basis to use for the availability calculation. For "energy", this indicates the operating capacity of the project, and for "time", this is the ratio of any level operational to all time.

  • frequency (str, optional) -- One of "project" (project total), "annual" (annual total), or "month-year" (monthly totals for each year).

  • by (str, optional) -- One of "windfarm" (project level) or "turbine" (turbine level) to indicate what level to calculate the availability.

Returns:

pd.DataFrame | float -- The appropriate availability metric, as a DataFrame unless it's calculated at the project/windfarm level.

Raises:

ValueError -- Raised if which is not one of "energy" or "time".

Project.capacity_factor(which, frequency='project', by='windfarm', with_losses=False, loss_ratio=None)[source]

Calculates the capacity factor over a project's lifetime as a single value, annual average, or monthly average for the whole windfarm or by turbine.

Return type:

DataFrame | float

Parameters:
  • which (str) -- One of "net" (realized energy / capacity) or "gross" (potential energy production / capacity).

  • frequency (str) -- One of "project", "annual", "monthly", or "month-year". Defaults to "project".

  • by (str) -- One of "windfarm" or "turbine". Defaults to "windfarm".

  • with_losses (bool, optional) --

    Use the loss_ratio or Project.loss_ratio to post-hoc consider non-wake and non-availability losses in the energy production aggregation. Defaults to False.

    Note

    This will only be checked for which = "net".

  • loss_ratio (float, optional) --

    The decimal non-wake and non-availability losses ratio to apply to the energy production. If None, then it will attempt to use the loss_ratio provided in the Project configuration. Defaults to None.

    Note

    This will only be used when for which = "net".

Returns:

pd.DataFrame | float -- The capacity factor at the desired aggregation level.

Energy Production#

Project.energy_potential(frequency='project', by='windfarm', units='gw', per_capacity=None, aep=False)[source]

Computes the potential energy production, or annual potential energy production, in GWh, for the simulation by extrapolating the monthly contributions to AEP if FLORIS (wtihout wakes) results were computed by a wind rose, or using the time series results.

Return type:

DataFrame | float

Parameters:
  • frequency (str, optional) -- One of "project" (project total), "annual" (annual total), or "month-year" (monthly totals for each year).

  • by (str, optional) -- One of "windfarm" (project level) or "turbine" (turbine level) to indicate what level to calculate the energy production.

  • per_capacity (str, optional) -- Provide the energy production normalized by the project's capacity, in the desired units. If None, then the unnormalized energy production is returned, otherwise it must be one of "kw", "mw", or "gw". Defaults to None.

  • aep (bool, optional) -- Flag to return the energy production normalized by the number of years the plan is in operation. Note that frequency must be "project" for this to be computed.

  • units (str)

Raises:

ValueError -- Raised if frequency is not one of: "project", "annual", "month-year".

Returns:

pd.DataFrame | float -- The wind farm-level energy prodcution, in GWh, for the desired frequency.

Project.energy_production(frequency='project', by='windfarm', units='gw', per_capacity=None, with_losses=False, loss_ratio=None, aep=False)[source]

Computes the energy production, or annual energy production, in GWh, for the simulation by extrapolating the monthly contributions to AEP if FLORIS (with wakes) results were computed by a wind rose, or using the time series results, and multiplying it by the WOMBAT monthly availability (Metrics.production_based_availability).

Return type:

DataFrame | float

Parameters:
  • frequency (str, optional) -- One of "project" (project total), "annual" (annual total), or "month-year" (monthly totals for each year).

  • by (str, optional) -- One of "windfarm" (project level) or "turbine" (turbine level) to indicate what level to calculate the energy production.

  • per_capacity (str, optional) -- Provide the energy production normalized by the project's capacity, in the desired units. If None, then the unnormalized energy production is returned, otherwise it must be one of "kw", "mw", or "gw". Defaults to None.

  • with_losses (bool, optional) -- Use the loss_ratio or Project.loss_ratio to post-hoc consider non-wake and non-availability losses in the energy production aggregation. Defaults to False.

  • loss_ratio (float, optional) -- The decimal non-wake and non-availability losses ratio to apply to the energy production. If None, then it will attempt to use the loss_ratio provided in the Project configuration. Defaults to None.

  • aep (bool, optional) -- Flag to return the energy production normalized by the number of years the plan is in operation. Note that frequency must be "project" for this to be computed.

  • units (str)

Raises:

ValueError -- Raised if frequency is not one of: "project", "annual", "month-year".

Returns:

pd.DataFrame | float -- The wind farm-level energy prodcution, in GWh, for the desired frequency.

Project.energy_losses(frequency='project', by='windfarm', units='gw', per_capacity=None, with_losses=False, loss_ratio=None, aep=False)[source]

Computes the energy losses for the simulation by subtracting the energy production from the potential energy production.

Return type:

DataFrame

Parameters:
  • frequency (str, optional) -- One of "project" (project total), "annual" (annual total), or "month-year" (monthly totals for each year).

  • by (str, optional) -- One of "windfarm" (project level) or "turbine" (turbine level) to indicate what level to calculate the energy production.

  • per_capacity (str, optional) -- Provide the energy production normalized by the project's capacity, in the desired units. If None, then the unnormalized energy production is returned, otherwise it must be one of "kw", "mw", or "gw". Defaults to None.

  • with_losses (bool, optional) -- Use the loss_ratio or Project.loss_ratio to post-hoc consider non-wake and non-availability losses in the energy production aggregation. Defaults to False.

  • loss_ratio (float, optional) -- The decimal non-wake and non-availability losses ratio to apply to the energy production. If None, then it will attempt to use the loss_ratio provided in the Project configuration. Defaults to None.

  • aep (bool, optional) -- AEP for the annualized losses. Only used for frequency = "project".

  • units (str)

Raises:

ValueError -- Raised if frequency is not one of: "project", "annual", "month-year".

Returns:

pd.DataFrame | float -- The wind farm-level energy prodcution, in GWh, for the desired frequency.

Project Financials#

Project.capex(breakdown=False, per_capacity=None)[source]

Provides a thin wrapper to ORBIT's ProjectManager CapEx calculations that can provide a breakdown of total or normalize it by the project's capacity, in MW.

Return type:

DataFrame | float

Parameters:
  • breakdown (bool, optional) -- Provide a detailed view of the CapEx breakdown, and a total, which is the sum of the BOS, turbine, project, and soft CapEx categories. Defaults to False.

  • per_capacity (str, optional) -- Provide the CapEx normalized by the project's capacity, in the desired units. If None, then the unnormalized CapEx is returned, otherwise it must be one of "kw", "mw", or "gw". Defaults to None.

Returns:

pd.DataFrame | float -- Project CapEx, normalized by per_capacity, if using, as either a pandas DataFrame if breakdown is True, otherwise, a float total.

Project.capex_breakdown(frequency='month-year', installation_start_date=None, soft_capex_date=None, project_capex_date=None, system_capex_date=None, turbine_capex_date=None, breakdown=False)[source]

Calculates the monthly CapEx breakdwon into a DataFrame, that is returned at the desired frequency, allowing for custom starting dates for the varying CapEx costs.

Return type:

DataFrame

Parameters:
  • frequency (str, optional) -- The desired frequency of the outputs, where "month-year" is the monthly total over the course of a project's life. Must be one of: "project", "annual", "month-year". Defaults to "month-year"

  • installation_start_date (str | None, optional) -- If not provided in the Project configuration as orbit_start_date, an installation starting date that is parseable from a string by Pandas may be provided here. Defaults to None

  • soft_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT soft CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None

  • project_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT project CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None

  • system_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT system CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None.

  • turbine_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT turbine CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None.

  • offtake_price (int | float | None, optional) -- The price paid for the energy produced, by default None.

  • breakdown (bool, optional) -- If True, all the CapEx categories will be provided as a column, in addition to the OpEx and Revenue columns, and the total cost in "cash_flow", othwerwise, only the "cash_flow" column will be provided. Defaults to False.

Returns:

pd.DataFrame -- Returns the pandas DataFrame of the cashflow with a fixed monthly or annual interval, or a project total for the desired categories.

Raises:
  • ValueError -- Raised if frequency is not one of: "project", "annual", "month-year".

  • TypeError -- Raised if a valid starting date can't be found for the installation.

Project.opex(frequency='project', per_capacity=None)[source]

Calculates the operational expenditures of the project.

Return type:

DataFrame | float

Parameters:
  • (str (frequency) -- Defaults to "project".

  • optional) (One of "project", "annual", "monthly", "month-year".) -- Defaults to "project".

  • per_capacity (str, optional) -- Provide the OpEx normalized by the project's capacity, in the desired units. If None, then the unnormalized OpEx is returned, otherwise it must be one of "kw", "mw", or "gw". Defaults to None.

  • frequency (str)

Returns:

pd.DataFrame | float -- The resulting OpEx DataFrame at the desired frequency, if more granular than the project frequency, otherwise a float. This will be normalized by the capacity, if per_capacity is not None.

Project.revenue(frequency='project', offtake_price=None, per_capacity=None)[source]

Calculates the revenue stream using the WOMBAT availabibility, FLORIS energy production, and WAVES energy pricing.

Return type:

DataFrame | float

Parameters:
  • frequency (str, optional) -- One of "project", "annual", "monthly", or "month-year". Defaults to "project".

  • offtake_price (float, optional) -- Price paid per MWh of energy produced. Defaults to None.

  • per_capacity (str, optional) -- Provide the revenue normalized by the project's capacity, in the desired units. If None, then the unnormalized revenue is returned, otherwise it must be one of "kw", "mw", or "gw". Defaults to None.

Returns:

pd.DataFrame | float -- The revenue stream of the wind farm at the provided frequency.

Project.cash_flow(frequency='month-year', installation_start_date=None, soft_capex_date=None, project_capex_date=None, system_capex_date=None, turbine_capex_date=None, offtake_price=None, breakdown=False)[source]

Calculates the monthly cashflows into a DataFrame, that is returned at the desired frequency, and with or without a high level breakdown, allowing for custom starting dates for the varying CapEx costs.

Return type:

DataFrame

Parameters:
  • frequency (str, optional) -- The desired frequency of the outputs, where "month-year" is the monthly total over the course of a project's life. Must be one of: "project", "annual", "month-year". Defaults to "month-year"

  • installation_start_date (str | None, optional) -- If not provided in the Project configuration as orbit_start_date, an installation starting date that is parseable from a string by Pandas may be provided here. Defaults to None

  • soft_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT soft CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None

  • project_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT project CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None

  • system_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT system CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None.

  • turbine_capex_date (tuple[int, int] | list[tuple[int, int]] | None, optional) -- The date(s) where the ORBIT turbine CapEx costs should be applied as a tuple of year and month, for instance: (2020, 1) for January 2020. Alternatively multiple dates can be set, which evenly divides the cost over all the dates, by providing a list of year and month combinations, for instance, a semi-annual 2 year cost starting in 2020 would look like: [(2020, 1), (2020, 7), (2021, 1), (2021, 7)]. If None is provided, then the CapEx date will be the same as the start of the installation. Defaults to None.

  • offtake_price (int | float | None, optional) -- The price paid for the energy produced, by default None.

  • breakdown (bool, optional) -- If True, all the CapEx categories will be provided as a column, in addition to the OpEx and Revenue columns, and the total cost in "cash_flow", othwerwise, only the "cash_flow" column will be provided. Defaults to False.

Returns:

pd.DataFrame -- Returns the pandas DataFrame of the cashflow with a fixed monthly or annual interval, or a project total for the desired categories.

Raises:
  • ValueError -- Raised if frequency is not one of: "project", "annual", "month-year".

  • TypeError -- Raised if a valid starting date can't be found for the installation.

Project.npv(frequency='project', discount_rate=None, offtake_price=None, cash_flow=None, **kwargs)[source]

Calculates the net present value of the windfarm at a project, annual, or monthly resolution given a base discount rate and offtake price. :rtype: DataFrame

Parameters:
  • frequency (str) -- One of "project", "annual", "monthly", or "month-year".

  • discount_rate (float, optional) -- The rate of return that could be earned on alternative investments. Defaults to None.

  • offtake_price (float, optional) -- Price of energy, per MWh. Defaults to None.

  • cash_flow (pd.DataFrame, optional) -- A modified cash flow DataFrame for custom workflows. Must have the "cash_flow" column with consistent time steps (monthly, annually, etc.). Defaults to None.

  • kwargs (dict, optional) -- See cash_flow() for details on starting date options.

Returns:

pd.DataFrame -- The project net prsent value at the desired time resolution.

Return type:

DataFrame

Project.irr(offtake_price=None, finance_rate=None, reinvestment_rate=None, cash_flow=None, **kwargs)[source]

Calculates the Internal Rate of Return using the ORBIT CapEx as the initial investment in conjunction with the WAVES monthly cash flows. :rtype: float

Note

This method allows for the caluclation of the modified internal rate of return through https://numpy.org/numpy-financial/latest/mirr.html#numpy_financial.mirr if both the finance_rate and the reinvestment_rate are provided.

Parameters:
  • offtake_price (float, optional) -- Price of energy, per MWh. Defaults to None.

  • finance_rate (float, optional) -- Interest rate paid on the cash flows. Only used if reinvestment_rate is also provided. Defaults to None.

  • reinvestment_rate (float, optional) -- Interest rate received on the cash flows upon reinvestment. Only used if finance_rate is also provided.

  • cash_flow (pd.DataFrame, optional) -- A modified cash flow DataFrame for custom workflows. Must have the "cash_flow" column with consistent time steps (monthly, annually, etc.). Defaults to None.

  • kwargs (dict, optional) -- See cash_flow() for details on starting date options.

Returns:

float -- The IRR.

Return type:

float

Project.lcoe(fixed_charge_rate=None, capex=None, opex=None, aep=None)[source]

Calculates the levelized cost of energy (LCOE) as the following: LCOE = (CapEx * FCR + OpEx) / AEP, in $/MWh.

Return type:

float

Parameters:
  • fixed_charge_rate (float, optional) -- Revenue per amount of investment required to cover the investment cost. Required if no value was provided in the Project configuration. Defaults to None

  • capex (float, optional) -- Custom CapEx value, in $/kW. Defaults to None.

  • opex (float, optional) -- Custom OpEx value, in $/kW/year. Defaults to None.

  • aep (float, optional) -- Custom AEP value, in MWh/MW/year. Defaults to None.

Returns:

float -- The levelized cost of energy.

Raises:

ValueError -- Raised if the input to units is not one of "kw", "mw", or "gw".

Command Line Interface (CLI)#

Run one or multiple WAVES analyses given a configuration dictionary, and optionally output and save the results.

Usage:

waves [OPTIONS] LIBRARY_PATH CONFIGURATION...

Arguments:

  • LIBRARY_PATH: The relative or absolute path to the simulation data library.

  • CONFIGURATION...: The configuration file name(s) to run. These should be located in LIBRARY_PATH/project/config/.

Options:

  • --report / --no-report: [default: report] Generate a table of metrics; report_config must be configured in the configuration. See the API for Project.generate_report() for details. Use --no-report to just run the simulation.

  • --save-report / --no-save-report: [default: save-report] Save the output report metrics to a CSV file. Use no-save-report to only display the results.

  • --install-completion: Install completion for the current shell.

  • --show-completion: Show completion for the current shell, to copy it or customize the installation.

  • --help: Show this message and exit.

Additional Configurations#

Running one or many analyses from the command line can be used with a few additional parameters defined in the configuration file. The provided example is configured to also be run through the CLI. Below is an example of the additional configurations

146# CLI Arguments
147run:
148  which_floris: wind_rose  # month-based wind rose wake analysis
149  full_wind_rose: False  # use the WOMBAT date range
150  floris_reinitialize_kwargs:
151      cut_in_wind_speed: 3.0
152      cut_out_wind_speed: 25.0  # standard ws range
153report_config:
154  name: Base Fixed Bottom 2022
155  "# Turbines":
156    metric: n_turbines
157  Turbine Rating (MW):
158    metric: turbine_rating
159  Project Capacity (MW):
160    metric: capacity
161    kwargs:
162      units: mw
163  "# OSS":
164    metric: n_substations
165  Total Export Cable Length (km):
166    metric: export_system_total_cable_length
167  Total Array Cable Length (km):
168    metric: array_system_total_cable_length
169  CapEx ($):
170    metric: capex
171  CapEx per kW ($/kW):
172    metric: capex
173    kwargs:
174      per_capacity: kw
175  OpEx ($):
176    metric: opex
177  OpEx per kW ($/kW):
178    metric: opex
179    kwargs:
180      per_capacity: kw
181  AEP (MWh):
182    metric: energy_production
183    kwargs:
184      units: mw
185      aep: True
186      with_losses: True
187  AEP per kW (MWh/kW):
188    metric: energy_production
189    kwargs:
190      units: mw
191      per_capacity: kw
192      aep: True
193      with_losses: True
194  Net Capacity Factor With Wake Losses (%):
195    metric: capacity_factor
196    kwargs:
197      which: net
198  Net Capacity Factor With All Losses (%):
199    metric: capacity_factor
200    kwargs:
201      which: net
202      with_losses: True
203  Gross Capacity Factor (%):
204    metric: capacity_factor
205    kwargs:
206      which: gross
207  Energy Availability (%):
208    metric: availability
209    kwargs:
210      which: energy
211  LCOE ($/MWh):
212    metric: lcoe