Example: Compare yaw optimizers

Example: Compare yaw optimizers#

"""Example: Compare yaw optimizers
This example compares the SciPy-based yaw optimizer with the Serial-Refine optimizer
and geometric optimizer.

First, we initialize Floris, and then generate a 3 turbine wind farm.
Next, we create two yaw optimization objects, `yaw_opt_sr` and `yaw_opt_scipy` for the
Serial-Refine and SciPy methods, respectively.
We then perform the optimization using both methods.
Finally, we compare the time it took to find the optimal angles and plot the optimal yaw angles
and resulting wind farm powers.

The example now also compares the Geometric Yaw optimizer, which is fast
a method to find approximately optimal yaw angles based on the wind farm geometry. Its
main use case is for coupled layout and yaw optimization.
see floris.optimization.yaw_optimization.yaw_optimizer_geometric.py and the paper online
at https://wes.copernicus.org/preprints/wes-2023-1/. See also example 16c.

"""

from time import perf_counter as timerpc

import matplotlib.pyplot as plt
import numpy as np

from floris import FlorisModel
from floris.optimization.yaw_optimization.yaw_optimizer_geometric import (
    YawOptimizationGeometric,
)
from floris.optimization.yaw_optimization.yaw_optimizer_scipy import YawOptimizationScipy
from floris.optimization.yaw_optimization.yaw_optimizer_sr import YawOptimizationSR


# Load the default example floris object
fmodel = FlorisModel("../inputs/gch.yaml")

# Reinitialize as a 3-turbine farm with range of WDs and 1 WS
D = 126.0 # Rotor diameter for the NREL 5 MW
wd_array = np.arange(0.0, 360.0, 3.0)
ws_array = 8.0 * np.ones_like(wd_array)
turbulence_intensities = 0.06 * np.ones_like(wd_array)
fmodel.set(
    layout_x=[0.0, 5 * D, 10 * D],
    layout_y=[0.0, 0.0, 0.0],
    wind_directions=wd_array,
    wind_speeds=ws_array,
    turbulence_intensities=turbulence_intensities,
)

print("Performing optimizations with SciPy...")
start_time = timerpc()
yaw_opt_scipy = YawOptimizationScipy(fmodel)
df_opt_scipy = yaw_opt_scipy.optimize()
time_scipy = timerpc() - start_time

print("Performing optimizations with Serial Refine...")
start_time = timerpc()
yaw_opt_sr = YawOptimizationSR(fmodel)
df_opt_sr = yaw_opt_sr.optimize()
time_sr = timerpc() - start_time

print("Performing optimizations with Geometric Yaw...")
start_time = timerpc()
yaw_opt_geo = YawOptimizationGeometric(fmodel)
df_opt_geo = yaw_opt_geo.optimize()
time_geo = timerpc() - start_time



# Print time spent
print("\n Time spent, Geometric Yaw: {:.2f} s.".format(time_geo))
print(" Time spent, Serial Refine: {:.2f} s.".format(time_sr))
print(" Time spent, SciPy (SLSQP): {:.2f} s.\n".format(time_scipy))

# Split out the turbine results
yaw_angles_opt_geo = np.vstack(df_opt_geo.yaw_angles_opt)
yaw_angles_opt_sr = np.vstack(df_opt_sr.yaw_angles_opt)
yaw_angles_opt_scipy = np.vstack(df_opt_scipy.yaw_angles_opt)


# Yaw results
for t in range(3):
    fig, ax = plt.subplots()
    ax.plot(df_opt_geo.wind_direction, yaw_angles_opt_geo[:, t],color='m',label='Geometric')
    ax.plot(df_opt_sr.wind_direction, yaw_angles_opt_sr[:, t],color='r',label='Serial Refine')
    ax.plot(df_opt_scipy.wind_direction, yaw_angles_opt_scipy[:, t],'--', color='g', label='SciPy')
    ax.grid(True)
    ax.set_ylabel('Yaw Offset (deg')
    ax.legend()
    ax.grid(True)
    ax.set_title("Turbine {:d}".format(t))

# Power results ==============

# Before plotting results, need to compute values for GEOOPT since it doesn't compute
# power within the optimization
fmodel.set(yaw_angles=yaw_angles_opt_geo)
fmodel.run()
geo_farm_power = fmodel.get_farm_power().squeeze()


fig, ax = plt.subplots()
ax.plot(
    df_opt_sr.wind_direction,
    df_opt_sr.farm_power_baseline,
    color='k',
    label='Baseline'
)
ax.plot(
    df_opt_geo.wind_direction,
    geo_farm_power,
    color='m',
    label='Optimized, Gemoetric'
)
ax.plot(
    df_opt_sr.wind_direction,
    df_opt_sr.farm_power_opt,
    color='r',
    label='Optimized, Serial Refine'
)
ax.plot(
    df_opt_scipy.wind_direction,
    df_opt_scipy.farm_power_opt,
    '--',
    color='g',
    label='Optimized, SciPy'
)
ax.set_ylabel('Wind Farm Power (W)')
ax.set_xlabel('Wind Direction (deg)')
ax.legend()
ax.grid(True)

# Finally, compare the overall the power gains

fig, ax = plt.subplots()

ax.plot(
    df_opt_geo.wind_direction,
    geo_farm_power - df_opt_sr.farm_power_baseline,
    color='m',
    label='Optimized, Gemoetric'
)
ax.plot(
    df_opt_sr.wind_direction,
    df_opt_sr.farm_power_opt - df_opt_sr.farm_power_baseline,
    color='r',
    label='Optimized, Serial Refine'
)
ax.plot(
    df_opt_scipy.wind_direction,
    df_opt_scipy.farm_power_opt - df_opt_scipy.farm_power_baseline,
    '--',
    color='g',
    label='Optimized, SciPy'
)
ax.set_ylabel('Increase in Wind Farm Power (W)')
ax.set_xlabel('Wind Direction (deg)')
ax.legend()
ax.grid(True)


# Finally, make a quick bar plot comparing nomimal power and nomimal uplift
total_power_uplift_geo = np.sum(geo_farm_power - df_opt_sr.farm_power_baseline)
total_power_uplift_sr = np.sum(df_opt_sr.farm_power_opt - df_opt_sr.farm_power_baseline)
total_power_uplift_scipy = np.sum(df_opt_scipy.farm_power_opt - df_opt_scipy.farm_power_baseline)

# Plot on the left subplot a barplot comparing the uplift normalized to scipy and on the right
# subplot a barplot of total time normalzed to scipy
fig, axarr = plt.subplots(1,2,figsize=(10,5))

ax = axarr[0]
ax.bar(
    [0, 1, 2],
    [
        total_power_uplift_geo / total_power_uplift_scipy,
        total_power_uplift_sr / total_power_uplift_scipy,
        1.0,
    ],
    color=['m', 'r', 'g'],
)
ax.set_xticks([0, 1, 2])
ax.set_xticklabels(['Geometric', 'Serial Refine', 'SciPy'])
ax.set_ylabel('Normalized Power Gain')
ax.grid(True)

ax = axarr[1]
ax.bar(
    [0, 1, 2],
    [
        time_geo / time_scipy,
        time_sr / time_scipy,
        1.0,
    ],
    color=['m', 'r', 'g'],
)
ax.set_xticks([0, 1, 2])
ax.set_xticklabels(['Geometric', 'Serial Refine', 'SciPy'])
ax.set_ylabel('Normalized Computation Time')
ax.grid(True)

# Change to semi-logy
axarr[1].set_yscale('log')

plt.show()
import warnings
warnings.filterwarnings('ignore')
Performing optimizations with SciPy...
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.362152E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.365698E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.454492E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     9.711141E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     2.217228E-02
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     7.129374E-02
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     1.419861E-01
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     2.180748E-01
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     2.208611E-01
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     4    -1.003155E+00     6.242130E-02
    2     7    -1.093049E+00     1.020444E-01
    3    10    -1.203810E+00     1.954488E-01
    4    13    -1.211961E+00     1.281127E-01
    5    16    -1.214226E+00     1.153093E-01
    6    19    -1.214237E+00     1.015314E-01
    7    22    -1.214237E+00     1.013118E-01
    8    24    -1.214237E+00     1.013095E-01
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.2142370269715685
            Iterations: 8
            Function evaluations: 24
            Gradient evaluations: 8
  NIT    FC           OBJFUN            GNORM
    1     4    -1.077700E+00     2.636250E-01
    2     7    -1.240651E+00     3.181902E-01
    3    10    -1.245722E+00     6.558203E-02
    4    13    -1.254002E+00     5.362665E-02
    5    16    -1.254090E+00     1.319603E-02
    6    19    -1.254067E+00     1.309625E-02
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.254089791882447
            Iterations: 6
            Function evaluations: 29
            Gradient evaluations: 6
  NIT    FC           OBJFUN            GNORM
    1     4    -1.041029E+00     2.069800E-01
    2     7    -1.123711E+00     1.859063E-01
    3    10    -1.126458E+00     4.218585E-02
    4    13    -1.126780E+00     2.116581E-02
    5    16    -1.125994E+00     1.612383E-02
    6    20    -1.126860E+00     1.533901E-02
    7    25    -1.126833E+00     1.311498E-02
    8    29    -1.128280E+00     8.142882E-03
    9    32    -1.126762E+00     2.579974E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.1282800408328353
            Iterations: 9
            Function evaluations: 42
            Gradient evaluations: 9
  NIT    FC           OBJFUN            GNORM
    1     4    -1.017900E+00     1.295852E-01
    2     7    -1.046548E+00     9.997854E-02
    3    10    -1.046487E+00     8.887290E-03
    4    23    -1.046525E+00     8.887263E-03
    5    28    -1.046624E+00     7.099863E-03
    6    31    -1.046658E+00     1.033764E-03
    7    34    -1.046683E+00     4.341467E-04
    8    37    -1.046685E+00     3.729168E-05
    9    40    -1.046685E+00     2.824111E-06
   10    42    -1.046685E+00     6.047025E-08
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0466852786523977
            Iterations: 10
            Function evaluations: 42
            Gradient evaluations: 10
  NIT    FC           OBJFUN            GNORM
    1     4    -1.002993E+00     4.975943E-02
    2     7    -1.006900E+00     3.378644E-02
    3    10    -1.007674E+00     1.032241E-02
    4    13    -1.007874E+00     3.814488E-03
    5    16    -1.007914E+00     2.517815E-03
    6    19    -1.007945E+00     2.060119E-03
    7    22    -1.007921E+00     7.695137E-04
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.007944748375735
            Iterations: 7
            Function evaluations: 32
            Gradient evaluations: 7
  NIT    FC           OBJFUN            GNORM
    1     4    -1.000005E+00     8.565508E-04
    2     7    -1.000025E+00     7.819653E-04
    3    10    -1.000035E+00     5.322843E-04
    4    12    -1.000035E+00     4.924128E-04
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0000354608371065
            Iterations: 4
            Function evaluations: 12
            Gradient evaluations: 4
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     7.483173E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.306803E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.359719E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.361989E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.362152E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.365698E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.454492E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     9.711141E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     2.217228E-02
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     7.129374E-02
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     1.419861E-01
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     2.180748E-01
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     2.208611E-01
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     4    -1.003155E+00     6.242130E-02
    2     7    -1.093049E+00     1.020444E-01
    3    10    -1.203810E+00     1.954488E-01
    4    13    -1.211961E+00     1.281127E-01
    5    16    -1.214226E+00     1.153093E-01
    6    19    -1.214237E+00     1.015314E-01
    7    22    -1.214237E+00     1.013118E-01
    8    24    -1.214237E+00     1.013095E-01
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.2142370269715692
            Iterations: 8
            Function evaluations: 24
            Gradient evaluations: 8
  NIT    FC           OBJFUN            GNORM
    1     4    -1.077700E+00     2.636250E-01
    2     7    -1.240651E+00     3.181902E-01
    3    10    -1.245722E+00     6.558203E-02
    4    13    -1.254002E+00     5.362665E-02
    5    16    -1.254090E+00     1.319603E-02
    6    19    -1.254067E+00     1.309625E-02
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.254089791882446
            Iterations: 6
            Function evaluations: 29
            Gradient evaluations: 6
  NIT    FC           OBJFUN            GNORM
    1     4    -1.041029E+00     2.069800E-01
    2     7    -1.123711E+00     1.859063E-01
    3    10    -1.126458E+00     4.218585E-02
    4    13    -1.126780E+00     2.116581E-02
    5    16    -1.125994E+00     1.612383E-02
    6    20    -1.126860E+00     1.533901E-02
    7    25    -1.126833E+00     1.311498E-02
    8    29    -1.128280E+00     8.142882E-03
    9    32    -1.126762E+00     2.579974E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.1282800408328355
            Iterations: 9
            Function evaluations: 42
            Gradient evaluations: 9
  NIT    FC           OBJFUN            GNORM
    1     4    -1.017900E+00     1.295852E-01
    2     7    -1.046548E+00     9.997854E-02
    3    10    -1.046487E+00     8.887290E-03
    4    23    -1.046525E+00     8.887263E-03
    5    28    -1.046624E+00     7.099863E-03
    6    31    -1.046658E+00     1.033765E-03
    7    34    -1.046683E+00     4.341468E-04
    8    37    -1.046685E+00     3.729169E-05
    9    40    -1.046685E+00     2.824112E-06
   10    42    -1.046685E+00     6.047028E-08
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0466852786523961
            Iterations: 10
            Function evaluations: 42
            Gradient evaluations: 10
  NIT    FC           OBJFUN            GNORM
    1     4    -1.002993E+00     4.975943E-02
    2     7    -1.006900E+00     3.378644E-02
    3    10    -1.007674E+00     1.032241E-02
    4    13    -1.007874E+00     3.814488E-03
    5    16    -1.007914E+00     2.517815E-03
    6    19    -1.007945E+00     2.060119E-03
    7    22    -1.007921E+00     7.695137E-04
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0079447483757351
            Iterations: 7
            Function evaluations: 32
            Gradient evaluations: 7
  NIT    FC           OBJFUN            GNORM
    1     4    -1.000005E+00     8.565508E-04
    2     7    -1.000025E+00     7.819653E-04
    3    10    -1.000035E+00     5.322843E-04
    4    12    -1.000035E+00     4.924128E-04
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0000354608371067
            Iterations: 4
            Function evaluations: 12
            Gradient evaluations: 4
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     7.483173E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.306803E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.359719E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
  NIT    FC           OBJFUN            GNORM
    1     3    -1.000000E+00     8.361989E-03
Optimization terminated successfully    (Exit mode 0)
            Current function value: -1.0
            Iterations: 1
            Function evaluations: 3
            Gradient evaluations: 1
Performing optimizations with Serial Refine...
[Serial Refine] Processing pass=0, turbine_depth=0 (0.0%)
[Serial Refine] Processing pass=0, turbine_depth=1 (16.7%)
[Serial Refine] Processing pass=0, turbine_depth=2 (33.3%)
[Serial Refine] Processing pass=1, turbine_depth=0 (50.0%)
[Serial Refine] Processing pass=1, turbine_depth=1 (66.7%)
[Serial Refine] Processing pass=1, turbine_depth=2 (83.3%)
Performing optimizations with Geometric Yaw...

 Time spent, Geometric Yaw: 0.19 s.
 Time spent, Serial Refine: 1.08 s.
 Time spent, SciPy (SLSQP): 51.95 s.
../../_images/7eefd5698cb5b8bfb142078ce377d36347c866c2e052932eb939c334c39d31ac.png ../../_images/08d490cd45d87c30c2282d2190344838d3c92b73176d53430bfffc1c5e7f26c4.png ../../_images/fd8df850f216cfc500c693709cbccdc425d46db714bbef62cb0dc1484f10c1f7.png ../../_images/29b8296c6cf902bf22447f744f67167135d071fde9f5f25dd1ad566d5ee2432f.png ../../_images/c6c4496373e9aaa1bfc898292d30e50fa2375cf51bf859c4de95788cc96d1e5c.png ../../_images/f94d7a0521c2dd95d591239f12efe510d37684f4031e0ae393158b7455998ab5.png