Skip to content

Commit

Permalink
Save WindData onto FlorisModel and simplify post-run() calls (NREL#849
Browse files Browse the repository at this point in the history
)

* Add functions to reshape turbine and farm power to wd x ws

* Add tests of new wind rose functions

* wind_data saved onto FlorisModel; functions partially built.

* Update tests; rename _wind_data to wind_data since optimizers may need access.

* 07 example updated (waked and no_wake match previous output).

* Remove wind_data need from layout optimizers.

* Bugfix; copy did not bring over wind_data."

* Update examples 13, 15

* Removing unneeded methods.

* Group hidden and outer get_turbine_powers methods.

* Ruff and isort.

* Add getter for wind_data.

* Rename converters to be more explicit about output.

* Updating tests.

* Copy up docstring from hidden version.

* Fix a couple more examples.

* Fix scaling on uniform frequency.

* ruff and isort.

* Log warnings when freq not provided and test.

* Update uncertain model for new paradigm

* Add test of wind rose setting

* bufgix

* change _expanded suffix to _rose to avoid confusion in UncertainFlorisModel.

* to_ methods specify class rather than suggested instantiation.

---------

Co-authored-by: Paul <[email protected]>
  • Loading branch information
misi9170 and paulf81 authored Mar 22, 2024
1 parent ddadefa commit 724f452
Show file tree
Hide file tree
Showing 18 changed files with 625 additions and 448 deletions.
23 changes: 6 additions & 17 deletions examples/07_calc_aep_from_rose.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,26 +55,15 @@
wind_speeds=wind_speeds,
turbulence_intensities=turbulence_intensities,
)
fmodel.run()

# Compute the AEP using the default settings
aep = fmodel.get_farm_AEP(freq=freq)
print("Farm AEP (default options): {:.3f} GWh".format(aep / 1.0e9))

# Compute the AEP again while specifying a cut-in and cut-out wind speed.
# The wake calculations are skipped for any wind speed below respectively
# above the cut-in and cut-out wind speed. This can speed up computation and
# prevent unexpected behavior for zero/negative and very high wind speeds.
# In this example, the results should not change between this and the default
# call to 'get_farm_AEP()'.
aep = fmodel.get_farm_AEP(
freq=freq,
cut_in_wind_speed=3.0, # Wakes are not evaluated below this wind speed
cut_out_wind_speed=25.0, # Wakes are not evaluated above this wind speed
)
print("Farm AEP (with cut_in/out specified): {:.3f} GWh".format(aep / 1.0e9))
print("Farm AEP: {:.3f} GWh".format(aep / 1.0e9))

# Finally, we can also compute the AEP while ignoring all wake calculations.
# This can be useful to quantity the annual wake losses in the farm. Such
# calculations can be facilitated by enabling the 'no_wake' handle.
aep_no_wake = fmodel.get_farm_AEP(freq, no_wake=True)
print("Farm AEP (no_wake=True): {:.3f} GWh".format(aep_no_wake / 1.0e9))
# calculations can be facilitated by first running with run_no_wake().
fmodel.run_no_wake()
aep_no_wake = fmodel.get_farm_AEP(freq=freq)
print("Farm AEP (no wakes): {:.3f} GWh".format(aep_no_wake / 1.0e9))
3 changes: 3 additions & 0 deletions examples/13_optimize_yaw_with_neighboring_farm.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ def yaw_opt_interpolant(wd, ws):
print(" ")
print("===========================================================")
print("Calculating baseline annual energy production (AEP)...")
fmodel_aep.run()
aep_bl_subset = 1.0e-9 * fmodel_aep.get_farm_AEP(
freq=freq_windrose,
turbine_weights=turbine_weights
Expand Down Expand Up @@ -247,11 +248,13 @@ def yaw_opt_interpolant(wd, ws):
print("===========================================================")
print("Calculating annual energy production with wake steering (AEP)...")
fmodel_aep.set(yaw_angles=yaw_angles_opt_nonb_AEP)
fmodel_aep.run()
aep_opt_subset_nonb = 1.0e-9 * fmodel_aep.get_farm_AEP(
freq=freq_windrose,
turbine_weights=turbine_weights,
)
fmodel_aep.set(yaw_angles=yaw_angles_opt_AEP)
fmodel_aep.run()
aep_opt_subset = 1.0e-9 * fmodel_aep.get_farm_AEP(
freq=freq_windrose,
turbine_weights=turbine_weights,
Expand Down
6 changes: 3 additions & 3 deletions examples/15_optimize_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@
fmodel.set(layout_x=layout_x, layout_y=layout_y)

# Setup the optimization problem
layout_opt = LayoutOptimizationScipy(fmodel, boundaries, wind_data=wind_rose)
layout_opt = LayoutOptimizationScipy(fmodel, boundaries)

# Run the optimization
sol = layout_opt.optimize()

# Get the resulting improvement in AEP
print('... calcuating improvement in AEP')
fmodel.run()
base_aep = fmodel.get_farm_AEP_with_wind_data(wind_data=wind_rose) / 1e6
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_with_wind_data(wind_data=wind_rose) / 1e6
opt_aep = fmodel.get_farm_AEP() / 1e6

percent_gain = 100 * (opt_aep - base_aep) / base_aep

Expand Down
13 changes: 5 additions & 8 deletions examples/16c_optimize_layout_with_heterogeneity.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@
layout_opt = LayoutOptimizationScipy(
fmodel,
boundaries,
wind_data=wind_rose,
min_dist=2*D,
optOptions={"maxiter":maxiter}
)
Expand All @@ -100,10 +99,10 @@
print('... calcuating improvement in AEP')

fmodel.run()
base_aep = fmodel.get_farm_AEP_with_wind_data(wind_data=wind_rose) / 1e6
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_with_wind_data(wind_data=wind_rose) / 1e6
opt_aep = fmodel.get_farm_AEP() / 1e6

percent_gain = 100 * (opt_aep - base_aep) / base_aep

Expand All @@ -128,7 +127,6 @@
layout_opt = LayoutOptimizationScipy(
fmodel,
boundaries,
wind_data=wind_rose,
min_dist=2*D,
enable_geometric_yaw=True,
optOptions={"maxiter":maxiter}
Expand All @@ -142,12 +140,11 @@
print('... calcuating improvement in AEP')

fmodel.set(yaw_angles=np.zeros_like(layout_opt.yaw_angles))
base_aep = fmodel.get_farm_AEP_with_wind_data(wind_data=wind_rose) / 1e6
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_with_wind_data(
wind_data=wind_rose
) / 1e6
opt_aep = fmodel.get_farm_AEP() / 1e6

percent_gain = 100 * (opt_aep - base_aep) / base_aep

Expand Down
1 change: 1 addition & 0 deletions examples/29_floating_vs_fixedbottom_farm.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
wind_speeds= ws_grid.flatten(),
turbulence_intensities=0.06 * np.ones_like(wd_grid.flatten())
)
fmodel.run()

# Compute the AEP
aep_fixed = fmodel_fixed.get_farm_AEP(freq=freq)
Expand Down
10 changes: 5 additions & 5 deletions examples/34_wind_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@
time_series = TimeSeries(wd_array, ws_array, turbulence_intensities=ti_array)

# Now build the wind rose
wind_rose = time_series.to_wind_rose()
wind_rose = time_series.to_WindRose()

# Plot the wind rose
fig, ax = plt.subplots(subplot_kw={"polar": True})
wind_rose.plot_wind_rose(ax=ax,legend_kwargs={"title": "WS"})
fig.suptitle("WindRose Plot")

# Now build a wind rose with turbulence intensity
wind_ti_rose = time_series.to_wind_ti_rose()
wind_ti_rose = time_series.to_WindTIRose()

# Plot the wind rose with TI
fig, axs = plt.subplots(2, 1, figsize=(6,8), subplot_kw={"polar": True})
Expand Down Expand Up @@ -78,9 +78,9 @@
wind_rose_power = fmodel_wind_rose.get_farm_power()
wind_ti_rose_power = fmodel_wind_ti_rose.get_farm_power()

time_series_aep = fmodel_time_series.get_farm_AEP_with_wind_data(time_series)
wind_rose_aep = fmodel_wind_rose.get_farm_AEP_with_wind_data(wind_rose)
wind_ti_rose_aep = fmodel_wind_ti_rose.get_farm_AEP_with_wind_data(wind_ti_rose)
time_series_aep = fmodel_time_series.get_farm_AEP()
wind_rose_aep = fmodel_wind_rose.get_farm_AEP()
wind_ti_rose_aep = fmodel_wind_ti_rose.get_farm_AEP()

print(f"AEP from TimeSeries {time_series_aep / 1e9:.2f} GWh")
print(f"AEP from WindRose {wind_rose_aep / 1e9:.2f} GWh")
Expand Down
Loading

0 comments on commit 724f452

Please sign in to comment.