Example 5: Getting Turbine and Farm Power

Example 5: Getting Turbine and Farm Power#

After setting the FlorisModel and running, the next step is typically to get the power outputof the turbines. FLORIS has several methods for getting power:1. get_turbine_powers(): Returns the power output of each turbine in the farm for each findex (n_findex, n_turbines)2. get_farm_power(): Returns the total power output of the farm for each findex (n_findex)3. get_expected_farm_power(): Returns the combination of the farm power over each findex with the frequency of each findex to get the expected farm power4. get_farm_AEP(): Multiplies the expected farm power by the number of hours in a year to get the expected annual energy production (AEP) of the farm

import matplotlib.pyplot as plt
import numpy as np

from floris import (
    FlorisModel,
    TimeSeries,
    WindRose,
)


fmodel = FlorisModel("inputs/gch.yaml")

# Set to a 3-turbine layout
fmodel.set(layout_x=[0, 126 * 5, 126 * 10], layout_y=[0, 0, 0])

######################################################
# Using TimeSeries
######################################################

# Set up a time series in which the wind speed and TI are constant but the wind direction
# sweeps the range from 250 to 290 degrees
wind_directions = np.arange(250, 290, 1.0)
time_series = TimeSeries(
    wind_directions=wind_directions, wind_speeds=9.9, turbulence_intensities=0.06
)
fmodel.set(wind_data=time_series)

# Run the model
fmodel.run()

# Get the turbine powers
turbine_powers = fmodel.get_turbine_powers()

# Turbines powers will have shape (n_findex, n_turbines) where n_findex is the number of unique
# wind conditions and n_turbines is the number of turbines in the farm
print(f"Turbine power has shape {turbine_powers.shape}")

# It is also possible to get the farm power directly
farm_power = fmodel.get_farm_power()

# Farm power has length n_findex, and is the sum of the turbine powers
print(f"Farm power has shape {farm_power.shape}")

# It's possible to get these powers with wake losses disabled, this can be useful
# for computing total wake losses
fmodel.run_no_wake()
farm_power_no_wake = fmodel.get_farm_power()

# Plot the results
fig, axarr = plt.subplots(1, 3, figsize=(15, 5))

# Plot the turbine powers
ax = axarr[0]
for i in range(turbine_powers.shape[1]):
    ax.plot(wind_directions, turbine_powers[:, i] / 1e3, label=f"Turbine {i+1}  ")
ax.set_xlabel("Wind Direction (deg)")
ax.set_ylabel("Power (kW)")
ax.grid(True)
ax.legend()
ax.set_title("Turbine Powers")

# Plot the farm power
ax = axarr[1]
ax.plot(wind_directions, farm_power / 1e3, label="Farm Power With Wakes", color="k")
ax.plot(wind_directions, farm_power_no_wake / 1e3, label="Farm Power No Wakes", color="r")
ax.set_xlabel("Wind Direction (deg)")
ax.set_ylabel("Power (kW)")
ax.grid(True)
ax.legend()
ax.set_title("Farm Power")

# Plot the percent wake losses
ax = axarr[2]
percent_wake_losses = 100 * (farm_power_no_wake - farm_power) / farm_power_no_wake
ax.plot(wind_directions, percent_wake_losses, label="Percent Wake Losses", color="k")
ax.set_xlabel("Wind Direction (deg)")
ax.set_ylabel("Percent Wake Losses")
ax.grid(True)
ax.legend()
ax.set_title("Percent Wake Losses")


######################################################
# Using WindRose
######################################################

# When running FLORIS using a wind rose, that is when a WindRose or WindTIRose object is
# passed into the set function.  The functions get_expected_farm_power and get_farm_AEP
# will operate the same as above, however the functions get_turbine_powers and get_farm_power
# will be reshaped from (n_findex, n_turbines) and
# (n_findex) to (n_wind_dir, n_wind_speed, n_turbines)
# and (n_wind_dir, n_wind_speed) respectively.  This is make the powers align more easily with the
# provided wind rose.

# Declare a WindRose object of 2 wind directions and 3 wind speeds and constant turbulence intensity
wind_rose = WindRose(
    wind_directions=np.array([270.0, 280.0]), wind_speeds=np.array([8.0, 9.0, 10.0]), ti_table=0.06
)

fmodel.set(wind_data=wind_rose)

print("==========Wind Rose==========")
print(f"Number of conditions to simulate (2 x 3): {fmodel.n_findex}")

fmodel.run()

turbine_powers = fmodel.get_turbine_powers()

print(f"Shape of turbine powers: {turbine_powers.shape}")

farm_power = fmodel.get_farm_power()

print(f"Shape of farm power: {farm_power.shape}")


# Plot the farm power
fig, ax = plt.subplots()

for w_idx, wd in enumerate(wind_rose.wind_directions):
    ax.plot(wind_rose.wind_speeds, farm_power[w_idx, :] / 1e3, label=f"WD: {wd}")

ax.set_xlabel("Wind Speed (m/s)")
ax.set_ylabel("Power (kW)")
ax.grid(True)
ax.legend()
ax.set_title("Farm Power (from Wind Rose)")

plt.show()
import warnings
warnings.filterwarnings('ignore')
Turbine power has shape (40, 3)
Farm power has shape (40,)
==========Wind Rose==========
Number of conditions to simulate (2 x 3): 6
Shape of turbine powers: (2, 3, 3)
Shape of farm power: (2, 3)
../_images/44c0763e1d191c18a3604935f56d136fc81e6978cbf8020e74e0de0b56f2f6f8.png ../_images/0af5ddad7ce39b165a32aff2e0e49c48bbe125a967e28022444994a962fbe361.png