You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug description
The heterogeneous map functionality uses the wrong (wind-aligned) coordinate system, rather than the north-aligned/inertial frame coordinate system.
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.
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.
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.
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_mapheterogeneous inflow functionality. The user can specify an input according to:https://github.com/NREL/floris/blob/8436fd78b002e5792f5d0dd1409332d171036d49/examples/16_heterogeneous_inflow.py#L42
Which suggests that
x_locsandy_locsand are in the same coordinate system asfi.layout_xandfi_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
xandycoordinates and the speed-ups infloris_interface.py, something likehttps://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 usinggrid.x_sortedandgrid.y_sorted, as follows:https://github.com/NREL/floris/blob/8436fd78b002e5792f5d0dd1409332d171036d49/floris/simulation/flow_field.py#L94
This is fundamentally incorrect.
grid.x_sortedandgrid.y_sortedare 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
results in
Showing that the correct usage here should be inserting
grid.x_sorted_inertial_frameandgrid.y_sorted_inertial_frameinto 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 59f3a6System Information (please complete the following information):
Additional information
While looking at the
het_mapfunctionality, 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.