Skip to content
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

Add cubature integration method for rotor velocities #649

Merged
merged 45 commits into from May 12, 2023

Conversation

rafmudaf
Copy link
Collaborator

@rafmudaf rafmudaf commented May 7, 2023

Add a cubature integration grid to average rotor points

This pull request adds a new grid type for placing and weighting grid points at the rotor so that a more accurate average can be calculated with fewer grid points. As @Bartdoekemeijer noted in #499, the square grid of points on the rotor swept area is inadequate since the calculated performance is highly dependent on grid resolution. Furthermore, the outer region of the blades are not captured at all and this is the area most sensitive to power production or power loss due to wakes.

The plot below shows a comparison of the convergence between the new and old method for averaging the velocity on the rotor for a turbine under no wake and with a shear profile exponent of 0.12. The x-axis for both series are the grid points input, and this translates to the square root of the number of points actually created on the grid. Here, you can see the square grid has a slow convergence rate, while the cubature grid is nearly converged by N=3.

convergence velcoity

This slow convergence in the current method is due to coarse sampling of both the shear profile and the wind turbine wake profiles. As shown in the image below, the typical 3 x 3 rectangular grid on the rotor swept area only covers a portion of the discs, and the new cubature grid covers a larger portion of the swept area.

grids

The following plot again shows the convergence of the cubature method for three turbines in line so two downstream turbines are waked.

all turbines

Usage

The cubature integration method works seamlessly with the existing solvers. To enable it, simply use these solver settings:

    solver_dict = {
        "type": "turbine_cubature_grid",
        "turbine_grid_points": 4
    }

API Changes

Initially, this pull request changed the API's for the turbine-module functions for calculating performance (Turbine.rotor_effective_velocity, Turbine.Ct, Turbine.axial_induction). However, after reviewing the current implementation and results, we've decided to approach this change as an intermediate step for including this type of grid and integration method. The current API's are retained so that no breaking changes are introduced when using the existing square grid (TurbineGrid). To use the new grid (TurbineCubatureGrid), additional input arguments are passed to the following functions:

def rotor_effective_velocity(
    ...
    average_method: str = "cubic-mean",
    cubature_weights: np.array | None = None
) -> NDArrayFloat:

def Ct(
    ...
    average_method: str = "cubic-mean",
    cubature_weights: np.array | None = None
) -> NDArrayFloat:

def axial_induction(
    ...
    average_method: str = "cubic-mean",
    cubature_weights: np.array | None = None
) -> NDArrayFloat:

def average_velocity(
    ...
    method: str = "cubic-mean",
    cubature_weights: np.array | None = None
) -> NDArrayFloat:

After further validation, it is intended that this grid-type will be the default, and the API's will be changed accordingly.

Future Work

The changes here have raised some important questions about the current velocity averaging in FLORIS. Specifically, we currently average velocities with a cube root of the mean of the velocities cubed. This accurately captures the average velocity for the power calculation since that is a function of the velocity cubed, but other turbine properties have a different relationship to the velocity yet we use the same method.

Additionally, it may be worthwhile to consider how the velocities are weighted across the blade span since the root does less work than the tip, but the velocities at both stations are weighted equally.

Finally, more work is required to show that the cubature method arrives at the correct answer in addition to arriving at the answer faster. The existing model defaults may need to be retuned based on the performance calculated from a different velocity integration, as well.

Related issue

#499

Impacted areas of the software

A new grid-type is added to the grid module, the turbine module performance functions have new optional arguments, and the solvers are updated to reflect these API changes.

@rafmudaf rafmudaf self-assigned this May 7, 2023
Rather than the full cubature coefficient data
@rafmudaf rafmudaf marked this pull request as ready for review May 11, 2023 22:41
@rafmudaf rafmudaf requested review from misi9170 and paulf81 May 11, 2023 22:43
@rafmudaf rafmudaf added the enhancement An improvement of an existing feature label May 11, 2023
@rafmudaf rafmudaf added this to the v3.4 milestone May 11, 2023
This is more consistent with the naming of the other grids where the points on the turbine explicitly state that they’re on the turbine and the others don’t
Copy link
Collaborator

@misi9170 misi9170 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me @rafmudaf. I'll look now into why the empirical_gauss examples aren't running and push changes up.

@@ -79,6 +79,7 @@ class Grid(ABC):
x_sorted: NDArrayFloat = field(init=False)
y_sorted: NDArrayFloat = field(init=False)
z_sorted: NDArrayFloat = field(init=False)
cubature_weights: NDArrayFloat = field(init=False, default=None)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see why this is needed here; I wonder whether in future, we should have an abstract TurbineGrid class (inherits from abstract Grid, or possibly general PointsGrid as we have discussed elsewhere) from which TurbineCubatureGrid and TurbineSquareGrid would inherit. Could get a little complicated with multiple levels on inheritance though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. The grid module overall needs some work. It would be helpful to identify where there's overlap between these grid-types. Possibly one path forward is to get rid of one grid super class in favor of categories of grids. At the least, the grid abstract base class could only define the required API's for all grids like x, x_sorted and sorted_indeces etc.

floris/simulation/turbine.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@paulf81 paulf81 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the code, and I know a few more changes are coming but wanted to log approval that this is looking really great

@rafmudaf rafmudaf changed the title Rotor cubature Add cubature integration method for rotor velocities May 12, 2023
@rafmudaf rafmudaf merged commit d5d4b13 into NREL:develop May 12, 2023
5 checks passed
@rafmudaf rafmudaf deleted the rotor_cubature branch May 12, 2023 18:15
@Bartdoekemeijer
Copy link
Collaborator

Specifically, we currently average velocities with a cube root of the mean of the velocities cubed. This accurately captures the average velocity for the power calculation since that is a function of the velocity cubed,

I'm not sure if this statement holds up, but agree that it's good to push this back to the next FLORIS release!

Thanks for doing all this work. This is going to be very helpful moving forward!

@rafmudaf
Copy link
Collaborator Author

Thanks for catching that @Bartdoekemeijer. I've made a note to clarify this in a couple of weeks, so I'll reach out then.

@rafmudaf rafmudaf mentioned this pull request May 16, 2023
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement An improvement of an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants