Skip to content

Bug report: heterogeneous inflow is interpolated on wind-aligned coordinate system #579

@Bartdoekemeijer

Description

@Bartdoekemeijer

Bug description
The heterogeneous map functionality uses the wrong (wind-aligned) coordinate system, rather than the north-aligned/inertial frame coordinate system.

Example 16 demonstrates the het_map heterogeneous inflow functionality. The user can specify an input according to:
https://github.com/NREL/floris/blob/8436fd78b002e5792f5d0dd1409332d171036d49/examples/16_heterogeneous_inflow.py#L42

speed_ups = [[2.0, 2.0, 1.0, 1.0]]
x_locs = [-300.0, -300.0, 2600.0, 2600.0]
y_locs = [ -300.0, 300.0, -300.0, 300.0]

Which suggests that x_locs and y_locs and are in the same coordinate system as fi.layout_x and fi_layout_y, what I call the inertial coordinate system. This coordinate system is independent of the ambient wind direction.

Then, a linear interpolant is created between these x and y coordinates and the speed-ups in floris_interface.py, something like
https://github.com/NREL/floris/blob/8436fd78b002e5792f5d0dd1409332d171036d49/floris/tools/floris_interface.py#L905

Now, when calculating the initial flow field in flow_field.py, the speed-ups are calculated using grid.x_sorted and grid.y_sorted, as follows:
https://github.com/NREL/floris/blob/8436fd78b002e5792f5d0dd1409332d171036d49/floris/simulation/flow_field.py#L94

This is fundamentally incorrect. grid.x_sorted and grid.y_sorted are in the wind-aligned frame and thus have a different value depending on the wind direction. The grid coordinates inserted into the interpolant should correspond to the inertial frame, not the wind-aligned frame.

To Reproduce

  1. Checkout on the branch in PR Add coordinates from inertial frame to grid class #578
  2. Run the following example:
from floris.tools import FlorisInterface
from floris.tools.floris_interface import generate_heterogeneous_wind_map

speed_ups = [[2.0, 2.0, 1.0, 1.0], [2.0, 2.0, 1.0, 1.0]]
x_locs = [-300.0, -300.0, 2600.0, 2600.0]
y_locs = [ -300.0, 300.0, -300.0, 300.0]

# Generate the linear interpolation to be used for the heterogeneous inflow.
het_map_2d = generate_heterogeneous_wind_map(speed_ups, x_locs, y_locs)

# Initialize FLORIS with a heterogeneous inflow
fi_2d = FlorisInterface("inputs/gch.yaml", het_map=het_map_2d)
fi_2d.reinitialize(
    wind_shear=0.0,
    wind_directions=[255.0, 270.0],
    wind_speeds=[8.0],
)
fi_2d.calculate_wake()

print("grid.x_sorted for first turbine, wind direction of 255.0 deg")
print(fi_2d.floris.grid.x_sorted[0, 0, 0, :, :])
print("grid.x_sorted for first turbine, wind direction of 270.0 deg")
print(fi_2d.floris.grid.x_sorted[1, 0, 0, :, :])

print("grid.x_sorted_inertial_frame for first turbine, wind direction of 255.0 deg")
print(fi_2d.floris.grid.x_sorted_inertial_frame[0, 0, 0, :, :])
print("grid.x_sorted_inertial_frame for first turbine, wind direction of 270.0 deg")
print(fi_2d.floris.grid.x_sorted_inertial_frame[1, 0, 0, :, :])

results in

grid.x_sorted for first turbine, wind direction of 255.0 deg
[[21.46672944 21.46672944 21.46672944]
 [21.46672944 21.46672944 21.46672944]
 [21.46672944 21.46672944 21.46672944]]
grid.x_sorted for first turbine, wind direction of 270.0 deg
[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]
grid.x_sorted_inertial_frame for first turbine, wind direction of 255.0 deg
[[ 8.15279992e+00  8.15279992e+00  8.15279992e+00]
 [-2.27373675e-13 -2.27373675e-13 -2.27373675e-13]
 [-8.15279992e+00 -8.15279992e+00 -8.15279992e+00]]
grid.x_sorted_inertial_frame for first turbine, wind direction of 270.0 deg
[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]

Showing that the correct usage here should be inserting grid.x_sorted_inertial_frame and grid.y_sorted_inertial_frame into the heterogeneous map linear interpolant.

Expected behavior
The heterogeneous map functionality linearly interpolates the speed-ups based on an inertial/north-aligned coordinate system.

Screenshots, if applicable

Floris Version
commit 59f3a6

System Information (please complete the following information):

  • OS: Ubuntu 22.04 LTS
  • Library versions
    • matplotlib==3.6.3
    • numpy==1.24.2
    • pytest==7.1.3
    • scipy==1.10.0

Additional information
While looking at the het_map functionality, I struggled with its interface. It requires a list of interpolants, one per wind direction, and assumes the speed-ups are independent of wind speed. Have you thought about a single interpolant for the entire floris object that takes in (wind_direction_grid, wind_speed_grid, grid_x, grid_y, grid_z)? If the user then doesn't want speed-up dependency on the ambient wind speed, we can just duplicate values behind the curtains to match these dimensions. It also means users do not need to fully reinitialize the interpolants when changing the wind directions in the floris object.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions