Example: Layout optimization with heterogeneous inflow

Example: Layout optimization with heterogeneous inflow#

"""Example: Layout optimization with heterogeneous inflow
This example shows a layout optimization using the geometric yaw option. It
combines elements of layout optimization and heterogeneous
inflow for demonstrative purposes.

Heterogeneity in the inflow provides the necessary driver for coupled yaw
and layout optimization to be worthwhile. First, a layout optimization is
run without coupled yaw optimization; then a coupled optimization is run to
show the benefits of coupled optimization when flows are heterogeneous.
"""


import os

import matplotlib.pyplot as plt
import numpy as np

from floris import FlorisModel, WindRose
from floris.optimization.layout_optimization.layout_optimization_scipy import (
    LayoutOptimizationScipy,
)


# Initialize FLORIS
fmodel = FlorisModel("../inputs/gch.yaml")

# Setup 2 wind directions (due east and due west)
# and 1 wind speed with uniform probability
wind_directions = np.array([270.0, 90.0])
n_wds = len(wind_directions)
wind_speeds = [8.0] * np.ones_like(wind_directions)
turbulence_intensities = 0.06 * np.ones_like(wind_directions)
# Shape frequency distribution to match number of wind directions and wind speeds
freq_table = np.ones((len(wind_directions), len(wind_speeds)))
freq_table = freq_table / freq_table.sum()


# The boundaries for the turbines, specified as vertices
D = 126.0  # rotor diameter for the NREL 5MW
size_D = 12
boundaries = [(0.0, 0.0), (size_D * D, 0.0), (size_D * D, 0.1), (0.0, 0.1), (0.0, 0.0)]

# Set turbine locations to 4 turbines at corners of the rectangle
# (optimal without flow heterogeneity)
layout_x = [0.1, 0.3 * size_D * D, 0.6 * size_D * D]
layout_y = [0, 0, 0]

# Generate exaggerated heterogeneous inflow (same for all wind directions)
speed_multipliers = np.repeat(np.array([0.5, 1.0, 0.5, 1.0])[None, :], n_wds, axis=0)
x_locs = [0, size_D * D, 0, size_D * D]
y_locs = [-D, -D, D, D]

# Create the configuration dictionary to be used for the heterogeneous inflow.
heterogeneous_inflow_config_by_wd = {
    "speed_multipliers": speed_multipliers,
    "wind_directions": wind_directions,
    "x": x_locs,
    "y": y_locs,
}

# Establish a WindRose object
wind_rose = WindRose(
    wind_directions=wind_directions,
    wind_speeds=wind_speeds,
    freq_table=freq_table,
    ti_table=0.06,
    heterogeneous_inflow_config_by_wd=heterogeneous_inflow_config_by_wd,
)


fmodel.set(
    layout_x=layout_x,
    layout_y=layout_y,
    wind_data=wind_rose,
)

# Setup and solve the layout optimization problem without heterogeneity
maxiter = 100
layout_opt = LayoutOptimizationScipy(
    fmodel, boundaries, min_dist=2 * D, optOptions={"maxiter": maxiter}
)

# Run the optimization
np.random.seed(0)
sol = layout_opt.optimize()

# Get the resulting improvement in AEP
print("... calcuating improvement in AEP")

fmodel.run()
base_aep = fmodel.get_farm_AEP() / 1e6
fmodel.set(layout_x=sol[0], layout_y=sol[1])
fmodel.run()
opt_aep = fmodel.get_farm_AEP() / 1e6

percent_gain = 100 * (opt_aep - base_aep) / base_aep

# Print and plot the results
print(f"Optimal layout: {sol}")
print(
    f"Optimal layout improves AEP by {percent_gain:.1f}% "
    f"from {base_aep:.1f} MWh to {opt_aep:.1f} MWh"
)
layout_opt.plot_layout_opt_results()
ax = plt.gca()
fig = plt.gcf()
sm = ax.tricontourf(x_locs, y_locs, speed_multipliers[0], cmap="coolwarm")
fig.colorbar(sm, ax=ax, label="Speed multiplier")
ax.legend(["Initial layout", "Optimized layout", "Optimization boundary"])
ax.set_title("Geometric yaw disabled")


# Rerun the layout optimization with geometric yaw enabled
print("\nReoptimizing with geometric yaw enabled.")
fmodel.set(layout_x=layout_x, layout_y=layout_y)
layout_opt = LayoutOptimizationScipy(
    fmodel, boundaries, min_dist=2 * D, enable_geometric_yaw=True, optOptions={"maxiter": maxiter}
)

# Run the optimization
np.random.seed(0)
sol = layout_opt.optimize()

# Get the resulting improvement in AEP
print("... calcuating improvement in AEP")

fmodel.set(yaw_angles=np.zeros_like(layout_opt.yaw_angles))
fmodel.run()
base_aep = fmodel.get_farm_AEP() / 1e6
fmodel.set(layout_x=sol[0], layout_y=sol[1], yaw_angles=layout_opt.yaw_angles)
fmodel.run()
opt_aep = fmodel.get_farm_AEP() / 1e6

percent_gain = 100 * (opt_aep - base_aep) / base_aep

# Print and plot the results
print(f"Optimal layout: {sol}")
print(
    f"Optimal layout improves AEP by {percent_gain:.1f}% "
    f"from {base_aep:.1f} MWh to {opt_aep:.1f} MWh"
)
layout_opt.plot_layout_opt_results()
ax = plt.gca()
fig = plt.gcf()
sm = ax.tricontourf(x_locs, y_locs, speed_multipliers[0], cmap="coolwarm")
fig.colorbar(sm, ax=ax, label="Speed multiplier")
ax.legend(["Initial layout", "Optimized layout", "Optimization boundary"])
ax.set_title("Geometric yaw enabled")

print(
    "Turbine geometric yaw angles for wind direction {0:.2f}".format(wind_directions[1])
    + " and wind speed {0:.2f} m/s:".format(wind_speeds[0]),
    f"{layout_opt.yaw_angles[1, :]}",
)

plt.show()
import warnings
warnings.filterwarnings('ignore')
=====================================================
Optimizing turbine layout...
Number of parameters to optimize =  6
=====================================================
  NIT    FC           OBJFUN            GNORM
    1     8    -2.212410E+00     2.629932E+00
    2    15    -2.242661E+00     3.547760E+00
    3    22    -2.143406E+00     3.843797E+00
    4    30    -2.247379E+00     3.886024E+00
    5    37    -2.247343E+00     3.977168E+00
    6    54    -2.247350E+00     3.977160E+00
    7    71    -2.247350E+00     3.977151E+00
    8    88    -2.247350E+00     3.977143E+00
    9   105    -2.247350E+00     3.977135E+00
   10   122    -2.247350E+00     3.977127E+00
   11   139    -2.247350E+00     3.977118E+00
   12   156    -2.247350E+00     3.977110E+00
   13   173    -2.247350E+00     3.977102E+00
   14   190    -2.247350E+00     3.977094E+00
   15   207    -2.247350E+00     3.977086E+00
   16   224    -2.247350E+00     3.977078E+00
   17   241    -2.247350E+00     3.977071E+00
   18   258    -2.247350E+00     3.977063E+00
   19   275    -2.247350E+00     3.977055E+00
   20   292    -2.247350E+00     3.977048E+00
   21   309    -2.247350E+00     3.977040E+00
   22   326    -2.247350E+00     3.977032E+00
   23   343    -2.247350E+00     3.977025E+00
   24   360    -2.247350E+00     3.977017E+00
   25   377    -2.247350E+00     3.977010E+00
   26   394    -2.247350E+00     3.977003E+00
   27   411    -2.247350E+00     3.976995E+00
   28   428    -2.247350E+00     3.976988E+00
   29   445    -2.247350E+00     3.976981E+00
   30   462    -2.247350E+00     3.976974E+00
   31   479    -2.247350E+00     3.976966E+00
   32   496    -2.247350E+00     3.976959E+00
   33   513    -2.247350E+00     3.976952E+00
   34   530    -2.247350E+00     3.976945E+00
   35   547    -2.247350E+00     3.976938E+00
   36   564    -2.247350E+00     3.976931E+00
   37   581    -2.247350E+00     3.976925E+00
   38   598    -2.247350E+00     3.976918E+00
Optimization terminated successfully    (Exit mode 0)
            Current function value: -2.247378947225584
            Iterations: 38
            Function evaluations: 608
            Gradient evaluations: 38
Optimization complete.
... calcuating improvement in AEP
Optimal layout: [[292.59583871603314, 704.3387065923789, 1511.9999999999893], [1.3342253732452536e-09, 4.82634845501135e-10, 5.690297624297925e-09]]
Optimal layout improves AEP by 124.7% from 6198.3 MWh to 13930.0 MWh

Reoptimizing with geometric yaw enabled.
=====================================================
Optimizing turbine layout...
Number of parameters to optimize =  6
=====================================================
  NIT    FC           OBJFUN            GNORM
    1     8    -2.365430E+00     2.961907E+00
    2    15    -2.498460E+00     3.815898E+00
    3    22    -4.022027E+00     3.448231E+00
    5    29    -3.500884E+00     2.123034E+02
    6    42    -2.534787E+00     2.123034E+02
    7    59    -2.411855E+00     2.123034E+02
    8    66    -3.550245E+00     3.437672E+00
    9    75    -2.515631E+00     3.300989E+00
   10    82    -2.574165E+00     6.377456E+00
   11    90    -2.660793E+00     4.588374E+00
   12    97    -2.661877E+00     4.609823E+00
   14   104    -2.598354E+00     4.619920E+00
   15   112    -2.662405E+00     4.716649E+00
   16   120    -2.662589E+00     4.685435E+00
   17   127    -4.345299E+00     7.324759E+00
   19   134    -2.203584E+00     2.425742E+02
   20   151    -2.239965E+00     2.010962E+02
   21   168    -2.279566E+00     2.010959E+02
   22   175    -2.571612E+00     3.354666E+00
   23   182    -2.367076E+00     4.358893E+00
   24   190    -2.365764E+00     5.647083E+00
   25   199    -2.581811E+00     6.377595E+00
   26   208    -2.539621E+00     4.473524E+00
   27   219    -2.650893E+00     4.826031E+00
   28   227    -2.654484E+00     4.478846E+00
   29   234    -2.423173E+00     4.958384E+00
   30   251    -2.654513E+00     5.008351E+00
   31   258    -2.596941E+00     6.940706E+00
   32   267    -2.633805E+00     7.417251E+00
   33   284    -2.575890E+00     3.225501E+00
   34   291    -2.654761E+00     1.028703E+01
   35   298    -2.654828E+00     7.416705E+00
   36   305    -2.654829E+00     4.512198E+00
   37   312    -2.597017E+00     6.904396E+00
   38   320    -2.634682E+00     4.733280E+00
   39   329    -2.655505E+00     4.733243E+00
   40   336    -2.655506E+00     4.509499E+00
   41   343    -2.655516E+00     4.954092E+00
   42   350    -2.634737E+00     4.509437E+00
   43   358    -2.655642E+00     4.509410E+00
   44   365    -2.655643E+00     9.663361E+00
   45   372    -2.655646E+00     4.508760E+00
   46   379    -2.655654E+00     4.953615E+00
   47   386    -2.634818E+00     6.590202E+00
   48   394    -2.655656E+00     1.098597E+01
   49   400    -2.655656E+00     6.590199E+00
Optimization terminated successfully    (Exit mode 0)
            Current function value: -2.655656447889527
            Iterations: 49
            Function evaluations: 400
            Gradient evaluations: 46
Optimization complete.
... calcuating improvement in AEP
Optimal layout: [[1512.0, 967.357791585612, 442.5964943654864], [0.09999999998985194, 0.0, 4.2511595964914314e-12]]
Optimal layout improves AEP by 165.6% from 6198.3 MWh to 16460.6 MWh
Turbine geometric yaw angles for wind direction 90.00 and wind speed 8.00 m/s: [ 0.         24.80798657 24.99750908]
../../_images/0b3684bebdc642b0a33264609a8edc61b4e423186973456e8bf7ae43fac3e0a1.png ../../_images/efe7aa0711c231230e817a5933388f1cafe17cff6d25672ecf6e179e38069db8.png