waves.project#
Provides the Project
class that ties to together ORBIT (CapEx), WOMBAT (OpEx), and
FLORIS (AEP) simulation libraries for a simplified modeling workflow.
Functions
|
Converts year and month tuple(s) into a pandas MultiIndex. |
|
Loads in the weather file using PyArrow, but returing a |
Classes
|
The unified interface for creating, running, and assessing analyses that combine ORBIT, WOMBAT, and FLORIS. |
- waves.project.convert_to_multi_index(date_tuples, name)[source]#
Converts year and month tuple(s) into a pandas MultiIndex.
- Return type:
MultiIndex
- Parameters:
date_tuples (tuple[int, int] | list[tuple[int, int]] | pd.MultiIndex | None) -- A single (
tuple
), or many combinations (list
oftuple``s) of ``int
year andint
month. If aMultiIndex
orNone
is passed, it will be returned as-is.name (str) -- The name of the variable to ensure that a helpful error is raised in case of invalid inputs.
- Returns:
pd.MultiIndex -- A pandas MultIndex with index columns: "year" and "month", or None, if None is passed.
- Raises:
ValueError -- Raised if the year, month combinations are not length 2 and are not tuples
- waves.project.load_weather(value)[source]#
Loads in the weather file using PyArrow, but returing a
pandas.DataFrame
object. Must have the column "datetime", which can be converted to apandas.DatetimeIndex
.- Return type:
DataFrame
- Parameters:
value (str | Path | DataFrame) -- str | Path | pd.DataFrame The input file name and path, or a
pandas.DataFrame
(gets passed back without modification).- Returns:
- pd.DataFrame
The full weather profile with the column "datetime" as a
pandas.DatetimeIndex
.
- 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 Noneproject_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 Nonesystem_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 themetrics_configuration
dictionary. An additional field ofname
is required as input, which will be passed tosimulation_name
. Defaults to None.
References
-
library_path:
Path
#
-
weather_profile:
str
#
-
orbit_config:
str
|Path
|dict
|None
#
-
wombat_config:
str
|Path
|dict
|None
#
-
floris_config:
str
|Path
|dict
|None
#
-
orbit_start_date:
str
|None
#
-
orbit_weather_cols:
list
[str
]#
-
floris_windspeed:
str
#
-
floris_wind_direction:
str
#
-
floris_x_col:
str
#
-
floris_y_col:
str
#
-
connect_floris_to_layout:
bool
#
-
connect_orbit_array_design:
bool
#
-
offtake_price:
float
|int
#
-
fixed_charge_rate:
float
#
-
discount_rate:
float
#
-
finance_rate:
float
#
-
reinvestment_rate:
float
#
-
loss_ratio:
float
#
-
soft_capex_date:
tuple
[int
,int
] |list
[tuple
[int
,int
]] |None
#
-
project_capex_date:
tuple
[int
,int
] |list
[tuple
[int
,int
]] |None
#
-
system_capex_date:
tuple
[int
,int
] |list
[tuple
[int
,int
]] |None
#
-
turbine_capex_date:
tuple
[int
,int
] |list
[tuple
[int
,int
]] |None
#
-
report_config:
dict
[str
,dict
] |None
#
-
weather:
DataFrame
#
-
orbit_config_dict:
dict
#
-
wombat_config_dict:
dict
#
-
floris_config_dict:
dict
#
-
wombat:
Simulation
#
-
orbit:
ProjectManager
#
-
floris:
FlorisInterface
#
-
project_wind_rose:
WindRose
#
-
monthly_wind_rose:
WindRose
#
-
floris_turbine_order:
list
[str
]#
-
turbine_potential_energy:
DataFrame
#
-
turbine_production_energy:
DataFrame
#
-
project_potential_energy:
DataFrame
#
-
project_production_energy:
DataFrame
#
-
_fi_dict:
dict
[tuple
[int
,int
],FlorisInterface
]#
-
floris_results_type:
str
#
-
operations_start:
Timestamp
#
-
operations_end:
Timestamp
#
-
operations_years:
int
#
- library_exists(attribute, value)[source]#
Validates that the user input to
library_path
is a valid directory.- Return type:
None
- Parameters:
attribute (attrs.Attribute) -- The attrs Attribute information/metadata/configuration.
value (Path) -- The user input.
- Raises:
FileNotFoundError -- Raised if
value
does not exist.ValueError -- Raised if the
value
exists, but is not a directory.
- 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".
- classmethod from_file(library_path, config_file)[source]#
Creates a
Project
object from either a JSON or YAML file. SeeProject
for configuration requirements.- Return type:
- 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 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.
- 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.
- setup_orbit()[source]#
Creates the ORBIT Project Manager object and readies it for running an analysis.
- Return type:
None
- setup_wombat()[source]#
Creates the WOMBAT Simulation object and readies it for running an analysis.
- Return type:
None
- setup_floris()[source]#
Creates the FLORIS FlorisInterface object and readies it for running an analysis.
- Return type:
None
- connect_floris_to_turbines(x_col='floris_x', y_col='floris_y')[source]#
Generates
floris_turbine_order
from the WOMBATWindfarm.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".
- 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"]
andlibrary_path
/cables/wombat_config_dict["layout"]
for WOMBAT and ORBIT compatibility, respectively.
- 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 updatedlayout_x
andlayout_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.
- preprocess_monthly_floris(reinitialize_kwargs=None, run_kwargs=None, cut_in_wind_speed=None, cut_out_wind_speed=None)[source]#
Creates the monthly chunked inputs to run a parallelized FLORIS time series analysis.
- Return type:
tuple
[list
[tuple
[FlorisInterface
,DataFrame
,tuple
[int
,int
],dict
,dict
]],ndarray
]- Parameters:
reinitialize_kwargs (dict | None, optional) -- Any keyword arguments to be assed to
FlorisInterface.reinitialize()
. Defaults to None.run_kwargs (dict | None, optional) -- Any keyword arguments to be assed to
FlorisInterface.calculate_wake()
. Defaults to None.cut_in_wind_speed (float, optional) -- The wind speed, in m/s, at which a turbine will start producing power.
cut_out_wind_speed (float, optional) -- The wind speed, in m/s, at which a turbine will stop producing power.
- Returns:
tuple[list[tuple[FlorisInterface, pd.DataFrame, tuple[int, int], dict, dict]], np.ndarray] --
- A list of tuples of:
a copy of the
FlorisInterface
objecttuple of year and month
a copy of
reinitialize_kwargs
c copy of
run_kwargs
- run_wind_rose_aep(full_wind_rose=False, run_kwargs=None)[source]#
Runs the custom FLORIS WindRose AEP methodology that allows for gathering of intermediary results.
- Parameters:
full_wind_rose (bool, optional) -- If True, the full wind profile will be used, otherwise, if False, the wind profile will be limited to just the simulation period. Defaults to False.
run_kwargs (dict | None, optional) --
Arguments that are provided to
FlorisInterface.get_farm_AEP_wind_rose_class()
. Defaults to None.From FLORIS:
- cut_in_wind_speed (float, optional): Wind speed in m/s below which
any calculations are ignored and the wind farm is known to produce 0.0 W of power. Note that to prevent problems with the wake models at negative / zero wind speeds, this variable must always have a positive value. Defaults to 0.001 [m/s].
- cut_out_wind_speed (float, optional): Wind speed above which the
wind farm is known to produce 0.0 W of power. If None is specified, will assume that the wind farm does not cut out at high wind speeds. Defaults to None.
- yaw_angles (NDArrayFloat | list[float] | None, optional):
The relative turbine yaw angles in degrees. If None is specified, will assume that the turbine yaw angles are all zero degrees for all conditions. Defaults to None.
- turbine_weights (NDArrayFloat | list[float] | None, optional):
weighing terms that allow the user to emphasize power at particular turbines and/or completely ignore the power from other turbines. This is useful when, for example, you are modeling multiple wind farms in a single floris object. If you only want to calculate the power production for one of those farms and include the wake effects of the neighboring farms, you can set the turbine_weights for the neighboring farms' turbines to 0.0. The array of turbine powers from floris is multiplied with this array in the calculation of the objective function. If None, this is an array with all values 1.0 and with shape equal to (n_wind_directions, n_wind_speeds, n_turbines). Defaults to None.
- no_wake: (bool, optional): When True updates the turbine
quantities without calculating the wake or adding the wake to the flow field. This can be useful when quantifying the loss in AEP due to wakes. Defaults to False.
- run_floris(which, reinitialize_kwargs=None, run_kwargs=None, full_wind_rose=False, cut_in_wind_speed=0.001, cut_out_wind_speed=None, nodes=-1)[source]#
Runs either a FLORIS wind rose analysis for a simulation-level AEP value (
which="wind_rose"
) or a turbine-level time series for the WOMBAT simulation period (which="time_series"
).- Return type:
None
- Parameters:
which (str) -- One of "wind_rose" or "time_series" to run either a simulation-level wind rose analysis or hourly time-series analysis for the base AEP model.
reinitialize_kwargs (dict | None, optional) -- Any keyword arguments to be assed to
FlorisInterface.reinitialize()
. Defaults to None.run_kwargs (dict | None, optional) -- Any keyword arguments to be assed to
FlorisInterface.calculate_wake()
. 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.cut_in_wind_speed (float, optional) -- The wind speed, in m/s, at which a turbine will start producing power. Should only be a value if running 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. Should only be a value if running 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
is not one of "wind_rose" or "time_series".:
- 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
orFlorisInterface.calculate_wake()
keyword arguments, depending onwhich_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".
- 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.
- 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 asnx.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) theFigure
andAxes
objects are returned.
- 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.
- 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.
- n_substations()[source]#
Calculates the number of subsations in the project.
- Return type:
int
- Returns:
int -- The number of substations in the 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.
- 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 ifbreakdown
is True, otherwise, a float total.
- 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
norCustomArraySystem
design were created in ORBIT.
- 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.
- 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
.
- 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
orProject.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
.
- 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
orProject.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
.
- 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".
- 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
orProject.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.
- 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.
- 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.
- 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 asorbit_start_date
, an installation starting date that is parseable from a string by Pandas may be provided here. Defaults to Nonesoft_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 Noneproject_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 Nonesystem_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.
- 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 asorbit_start_date
, an installation starting date that is parseable from a string by Pandas may be provided here. Defaults to Nonesoft_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 Noneproject_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 Nonesystem_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.
- 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
Note
NPV is implemented via https://numpy.org/numpy-financial/latest/npv.html#numpy_financial.npv.
- 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
- 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 thereinvestment_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
- 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 Nonecapex (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".
- 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 populatesimulation_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