-
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
Implement TurbOPark as a Gaussian model #907
Conversation
Hi @JasperShell , thank you again for taking the time to dig into FLORIS and for submitting this pull request. I've now had more of a chance to start working with it, and I've started with reorganizing the PR_TurbOParkGauss folder and turning it into an example in the examples/ directory (under a new subdirectory, examples_turbopark). The key changes I've made are:
Now, running 001_compare_turbopark_implementations.py produces the following figures (which match those from the case scripts/notebooks): |
The process I'm planning for working on this PR is
|
Hi @JasperShell , I've now looked carefully through your implementation of the TurboPark model and compared with Pedersen et al (2022). I think it's in really great shape, and I'm just about ready to move onto finalizing things (adding a bit of documentation etc). Before I do that though, I have a couple of requests:
I'll wait for your response on both of these and then move forward with finalizing the pull request and asking for reviews from @rafmudaf and @paulf81 . |
…ke as argument Removed sigma_max_rel, because that restriction is not needed in this implementation. Therefore also removed wtg_overlapping mask Introduced include_mirror_wake as input argument
This wake model was only included to demonstrate that other wake models could be implemented. The current implementation was not complete, it had some shortcomings compared to the latest literature. Hence, removing it from this pull request. It can be introduced later in another pull request.
Hi @misi9170,
I pushed these proposed changes in a new commit.
I removed the doublegauss wake model in another commit. |
@paulf81 @bayc @rafmudaf this is now ready for review. As I've already been through it thoroughly, I'm happy to merge once one of you is happy. @Bartdoekemeijer , I've also added you as a reviewer in case you'd like to take a look and provide any comments. |
I'll document here for future reference that this implementation has optional mirror wakes to model the effect of the ground or sea surface. The Boolean field Mirror wake functionality is also available in the empirical Gaussian (EmG) model; but there, it is currently hardcoded to |
more faithful to the original description provided by Nygaard et al and uses | ||
the sequential_solver, and compares it to the existing implementation in | ||
Floris. | ||
""" |
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.
|
||
# 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 comment
The reason will be displayed to describe this comment to others. Learn more.
maybe if not too bulky could add (Source: ...)
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.
Thank you very much @JasperShell for this contribution! Only very minor comments from me so I'm going to approve. But I did have two optional thoughts I wanted to check with you and also @misi9170:
- Should we add a warning to the former turbopark model if we have a preference toward the new?
- More for @misi9170 , the tests are failing on my computer locally but that is due to randomoptregtest so I'll open a separate issue
@paulf81, thanks for approving this pull request. On your first point, first of all it is primarily up to you and @misi9170 as owners of the tool. |
Thank you for the comments @JasperShell , I'll meet up with @misi9170 and I think we can get this merged very soon! |
TurbOPark implemented like Gauss wake model using sequential_solver
The current implementation of TurbOPark follows Orsted's original implementation (https://github.com/OrstedRD/TurbOPark), and has a dedicated solver,
turbopark_solver
insolver.py
.However, the current implementation does not match the results of Orsted's model.
This pull request proposes a new implementation of the TurbOPark wake model,
turboparkgauss.py
. Instead of introducing a dedicated solver, it makes use of thesequential_solver
, the same as used for Gauss (GCH) wake model.This new implementation gives exact match with the original Orsted model.
It also improves the modularity of Floris, because this implementation doesn't need a dedicated solver.
Related issue
The new implementation benefits from the cubature_grid integration scheme that was introduced in #649. It uses:
Test cases
All test cases are stored in the
PR_TurbOParkGauss
folder.In these examples, all turbines have a constant CT of 0.75. Wind speed is fixed to 8.0m/s and TI is set to 6%.
Example 1: Single wake
This example is based on
Case_SingleTurbineWake.ipynb
andCase_SingleTurbineWake.yaml
NOTE: This test case is built in Floris v3.6.
Because the new implementation uses the
sequential_solver
, also thefull_flow_sequential_solver
can be used to visualize a single wake. This is not possible with the current TurbOPark implementation.The new implementation is compared with Orsted's model and with my own ShellWakes tool.
Example 2: Wind direction sweep
This example is based on
Case_TwinPark_TurbOPark_implementation.py
,Case_TwinPark_TurbOPark.yaml
andCase_TwinPark_TurbOParkGauss.yaml
.NOTE: This test case is built in Floris v4.0.
A wind direction sweep is done with 2 wind turbines.
Example 3: Row of turbines
This example is based on
Case_Rowpark_TurbOPark.py
,Case_RowPark_TurbOPark.yaml
andCase_RowPark_TurbOParkGauss.yaml
NOTE: This test case is built in Floris v4.0.
A fully aligned wind farm of 10 wind turbines with 5D spacing.
Examples 2 and 3 show the mismatch of the original implementation of
turbopark.py
and the matching implementation ofturboparkgauss.py
.Note that in the same way, other wake models can be implemented that use the
sequential_solver
, as long as the wake profiles are smooth. Models like, gaussian, super-gaussian, double-gaussian, polynomial (Larson), and even EV.Only hat-shaped models, like Jensen, or models with integrated super-positioning, like CC, require a dedicated solver.