-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement TurbOPark as a Gaussian model #907
Merged
misi9170
merged 47 commits into
NREL:develop
from
JasperShell:feature/turbopark_as_gauss
Jul 18, 2024
Merged
Changes from all commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
a2d679c
added turboparkgauss & double gauss wake models
JasperShell 6aac296
Correct implementation of mirror turbines
JasperShell 5f6c104
Merge remote-tracking branch 'origin/develop' into feature/turbopark_…
JasperShell e9531b6
Test case files added
JasperShell 6683358
isort, ruff.
misi9170 b5e5249
Switch to relative inputs to run from PR_TurbOParkGauss directory.
misi9170 f607770
Clean up rowpark example some, add comments.
misi9170 04c1d32
Move inputs into single file for simplicity.
misi9170 283dfeb
Second input file for RowPark.
misi9170 6e4a7fc
Simplify inputs to TwinPark example.
misi9170 aec0fa6
Clean up TwinPark runscript.
misi9170 4e726df
Consolidate example scripts.
misi9170 93d310f
Consolidate input files.
misi9170 8b60ebd
Move data to subdirectory.
misi9170 faf7bd4
Add _sorted_interial_frame coordinates for viz purposes.
misi9170 fb4f656
Consolidate single turbine example into main runscript.
misi9170 b63f584
Build constant CT turbine in script.
misi9170 28789af
Remove inputs directory; all information now in input yamls and script.
misi9170 9115607
move to examples directory.
misi9170 aef862e
Merge branch 'develop' into feature/tag_ms
misi9170 056aedd
empty lines.
misi9170 d851e04
Add description to example.
misi9170 cd85398
Fix trailing whitespace issue.
misi9170 e2dc395
isort.
misi9170 6a1f7af
Add reg test consistent with other wake models.
misi9170 c3bfdb9
Add full flow reg test.
misi9170 d7faa32
Add unit test to compare to Nygaard results.
misi9170 adfb06c
Add unit test.
misi9170 23f7447
End lines.
misi9170 edd337b
Move D factor outside of characteristic_wake_width calculation.
misi9170 304fae6
Make mirror wakes optional (but hardcoded to included) similar to EmG.
misi9170 1ac34e1
Add TODO note.
misi9170 9732e20
Import gaussian_function to avoid redundant code and remove unneeded …
misi9170 f131ba8
Fix bug that was using np.min in place of np.minimum, which is a carr…
misi9170 94897eb
Update reg tests after np.min bugfix.
misi9170 bb48495
Update refs.
misi9170 8d03890
removed sigma_max_rel & wtg_overlapping, introduced include_mirror_wa…
JasperShell 370c151
Removed doublegauss wake model
JasperShell 3496658
Remove sigma_max_rel from testing.
misi9170 0c18d1a
Minor changes to full flow solver results after removal of sigma_max_…
misi9170 9ae6bb6
Add description and citation for new turbopark implementation.
misi9170 a94f6ad
Merge develop branch.
misi9170 68a791a
Remove commented out code for Doublegass model.
misi9170 53ea929
Add comments on comparison data from Matlab
misi9170 f18de3b
add warning recommending using turboparkgauss; leave constants hardco…
misi9170 1272356
remove unclear comment about original turbopark implementation mismat…
misi9170 221c41b
Fix typo.
misi9170 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
190 changes: 190 additions & 0 deletions
190
examples/examples_turbopark/001_compare_turbopark_implementations.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
"""Example: Compare TurbOPark model implementations | ||
This example demonstrates a new implementation of the TurbOPark model that is | ||
more faithful to the original description provided by Pedersen et al and uses | ||
the sequential_solver, and compares it to the existing implementation in | ||
Floris. | ||
""" | ||
|
||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
import pandas as pd | ||
|
||
import floris.flow_visualization as flowviz | ||
from floris import FlorisModel, TimeSeries | ||
from floris.turbine_library import build_cosine_loss_turbine_dict | ||
|
||
|
||
# Note: "new" is used to refer to the new implementation of TurbOPark, which is | ||
# more faithful to the description provided by Pedersen et al. (2022). "orig" | ||
# is used to refer to the existing TurbOPark implementation in Floris (which | ||
# was based on Ørsted's Matlab code, originally from Nygaard et al. (2020). | ||
|
||
### Build a constant CT turbine model for use in comparisons (not realistic) | ||
const_CT_turb = build_cosine_loss_turbine_dict( | ||
turbine_data_dict={ | ||
"wind_speed":[0.0, 30.0], | ||
"power":[0.0, 1.0], # Not realistic but won't be used here | ||
"thrust_coefficient":[0.75, 0.75] | ||
}, | ||
turbine_name="ConstantCT", | ||
rotor_diameter=120.0, | ||
hub_height=100.0, | ||
ref_tilt=0.0, | ||
) | ||
|
||
### Start by visualizing a single turbine in and its wake with the new model | ||
# Load the new TurboPark implementation and switch to constant CT turbine | ||
fmodel_new = FlorisModel("../inputs/turboparkgauss_cubature.yaml") | ||
fmodel_new.set(turbine_type=[const_CT_turb]) | ||
fmodel_new.run() | ||
u0 = fmodel_new.wind_speeds[0] | ||
|
||
col_orig = "C0" | ||
col_new = "C1" | ||
|
||
# Get plane of points for visualization | ||
rotor_diameter = 120.0 | ||
x_resolution=1501 | ||
y_resolution=201 | ||
z_resolution=100 | ||
x_bounds = [-5*rotor_diameter, 25*rotor_diameter] | ||
|
||
horizontal_plane = fmodel_new.calculate_horizontal_plane( | ||
x_resolution=x_resolution, | ||
y_resolution=y_resolution, | ||
height=100.0, | ||
x_bounds=x_bounds | ||
) | ||
|
||
# Visualize the flows with a horizontal slice | ||
fig, ax = plt.subplots(3,1) | ||
fig.set_size_inches(7, 10) | ||
flowviz.visualize_cut_plane( | ||
horizontal_plane, | ||
ax=ax[0], | ||
label_contours=True, | ||
title="Horizontal plane" | ||
) | ||
ax[0].set_xlabel("x [m]") | ||
ax[0].set_ylabel("y [m]") | ||
|
||
# Get points and velocities, normalized by rotor diameter and freestream velocity | ||
x_locs_norm = horizontal_plane.df.x1[:x_resolution]/rotor_diameter | ||
y_locs_norm = horizontal_plane.df.x2[::x_resolution]/rotor_diameter | ||
u_norm = horizontal_plane.df.u[150100:151601]/u0 | ||
|
||
# Plot downstream velocities | ||
ax[1].plot(x_locs_norm, u_norm, color=col_new) | ||
ax[1].set_xlabel("Downstream distance [D]") | ||
ax[1].set_ylabel("Normalized velocity [-]") | ||
ax[1].grid() | ||
ax[1].set_xlim([x/rotor_diameter for x in x_bounds]) | ||
|
||
# Plot axial velocities at various downstream distances | ||
for loc in np.append(251, np.linspace(350,750,5)): #range(200,1200,200): | ||
u_norm = horizontal_plane.df.u[int(loc)::x_resolution]/u0 | ||
alpha = 1.0 - (loc-250)/1000 | ||
ax[2].plot(y_locs_norm, u_norm, label=str((loc-250)/50)+"D downstream", alpha=alpha, c=col_new) | ||
ax[2].legend() | ||
ax[2].set_xlabel("Radial distance [D]") | ||
ax[2].set_ylabel("Normalized velocity [-]") | ||
ax[2].grid() | ||
ax[2].set_xlim([-2, 2]) | ||
|
||
### Look at the wake profile at a single downstream distance for a range of wind directions | ||
# Load the original TurboPark implementation and switch to constant CT turbine | ||
fmodel_orig = FlorisModel("../inputs/turbopark_cubature.yaml") | ||
fmodel_orig.set(turbine_type=[const_CT_turb]) | ||
|
||
# Set up and solve flows | ||
wd_array = np.arange(225,315,0.1) | ||
wind_data_wd_sweep = TimeSeries( | ||
wind_speeds=8.0, | ||
wind_directions=wd_array, | ||
turbulence_intensities=0.06 | ||
) | ||
fmodel_orig.set( | ||
layout_x = [0.0, 600.0], | ||
layout_y = [0.0, 0.0], | ||
wind_data=wind_data_wd_sweep | ||
) | ||
fmodel_orig.run() | ||
|
||
# Extract output velocities at downstream turbine | ||
orig_vels_ds = fmodel_orig.turbine_average_velocities[:,1] | ||
u0 = fmodel_orig.wind_speeds[0] # Get freestream wind speed for normalization | ||
|
||
# Set up and solve flows; extract velocities at downstream turbine | ||
fmodel_new.set( | ||
layout_x = [0.0, 600.0], | ||
layout_y = [0.0, 0.0], | ||
wind_data=wind_data_wd_sweep | ||
) | ||
fmodel_new.run() | ||
new_vels_ds = fmodel_new.turbine_average_velocities[:,1] | ||
|
||
# Load comparison data (generated by running Ørsted's Matlab code | ||
# https://github.com/OrstedRD/TurbOPark) | ||
df_twinpark = pd.read_csv("comparison_data/WindDirection_Sweep_Orsted.csv") | ||
|
||
# Plot the data and compare | ||
fig, ax = plt.subplots(2, 1) | ||
fig.set_size_inches(7, 10) | ||
ax[0].plot(wd_array, orig_vels_ds/u0, label="Floris - TurbOPark", c=col_orig) | ||
ax[0].plot(wd_array, new_vels_ds/u0, label="Floris - TurbOPark-Gauss", c=col_new) | ||
df_twinpark.plot("wd", "wws", ax=ax[0], linestyle="--", color="k", label="Orsted - TurbOPark") | ||
|
||
ax[0].set_xlabel("Wind direction [deg]") | ||
ax[0].set_ylabel("Normalized rotor averaged waked wind speed [-]") | ||
ax[0].set_xlim(240,300) | ||
ax[0].set_ylim(0.65,1.05) | ||
ax[0].legend() | ||
ax[0].grid() | ||
|
||
### Now, look at velocities along a row of ten turbines aligned with the flow | ||
layout_x = np.linspace(0.0, 5400.0, 10) | ||
layout_y = np.zeros_like(layout_x) | ||
turbines = range(len(layout_x)) | ||
wind_data_row = TimeSeries( | ||
wind_speeds=np.array([8.0]), | ||
wind_directions=270.0, | ||
turbulence_intensities=0.06 | ||
) | ||
fmodel_orig.set( | ||
layout_x=layout_x, | ||
layout_y=layout_y, | ||
wind_data=wind_data_row | ||
) | ||
fmodel_new.set( | ||
layout_x=layout_x, | ||
layout_y=layout_y, | ||
wind_data=wind_data_row | ||
) | ||
|
||
# Run and extract flow velocities at the turbines | ||
fmodel_orig.run() | ||
orig_vels_row = fmodel_orig.turbine_average_velocities | ||
fmodel_new.run() | ||
new_vels_row = fmodel_new.turbine_average_velocities | ||
u0 = fmodel_orig.wind_speeds[0] # Get freestream wind speed for normalization | ||
|
||
# Load comparison data | ||
df_rowpark = pd.read_csv("comparison_data/Rowpark_Orsted.csv") | ||
|
||
# Plot the data and compare | ||
ax[1].scatter( | ||
turbines, df_rowpark["wws"], s=80, marker="o", c="k", label="Orsted - TurbOPark" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe if not too bulky could add (Source: ...) |
||
) | ||
ax[1].scatter( | ||
turbines, orig_vels_row/u0, s=20, marker="o", c=col_orig, label="Floris - TurbOPark" | ||
) | ||
ax[1].scatter( | ||
turbines, new_vels_row/u0, s=20, marker="o", c=col_new, label="Floris - TurbOPark_Gauss" | ||
) | ||
ax[1].set_xlabel("Turbine number") | ||
ax[1].set_ylabel("Normalized rotor averaged wind speed [-]") | ||
ax[1].set_ylim(0.25, 1.05) | ||
ax[1].legend() | ||
ax[1].grid() | ||
|
||
plt.show() |
11 changes: 11 additions & 0 deletions
11
examples/examples_turbopark/comparison_data/Rowpark_Orsted.csv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
wtg_nr,wws | ||
1,1 | ||
2,0.709920677983239 | ||
3,0.615355749367675 | ||
4,0.551410465937128 | ||
5,0.502600655337247 | ||
6,0.46316755609319 | ||
7,0.430238792036599 | ||
8,0.402137593655074 | ||
9,0.377783142608699 | ||
10,0.356429516711137 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add here a note on where the data comparison_data comes from, is it from one of the referenced papers? Or the website?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The testcases were my own, so not based on literature. The comparison data comes from running Orsted's Matlab code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've now added a text comment saying that the comparison data comes from running Ørsted's Matlab code.