Skip to content

Commit

Permalink
Add reset function to FlorisInterface
Browse files Browse the repository at this point in the history
partially complete
  • Loading branch information
rafmudaf committed Jan 19, 2024
1 parent 8d7e012 commit 8c4b625
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 2 deletions.
35 changes: 35 additions & 0 deletions floris/tools/floris_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from floris.simulation.turbine_multi_dim import multidim_power_down_select, power_multidim
from floris.tools.cut_plane import CutPlane
from floris.type_dec import NDArrayFloat
from floris.simulation.grid import TurbineGrid


class FlorisInterface(LoggingManager):
Expand Down Expand Up @@ -188,6 +189,40 @@ def calculate_no_wake(
# Finalize values to user-supplied order
self.floris.finalize()

def reset(
self,
layout_x: NDArrayFloat,
layout_y: NDArrayFloat,
wind_speeds: NDArrayFloat,
wind_directions: NDArrayFloat
):
# NOTE: if the layout changes, then the grid will need to be reinitialized. The grid
# points are placed in space based on the farm.layout.
# The size of the grid arrays can remain the same, but the grid points will need to be
# reset.

self.floris.farm.layout_x = layout_x
self.floris.farm.layout_y = layout_y
# TODO: the hub heights are expanded to 3d in the farm, so this takes the first wind
# condition as the reference hub height array. It should instead either not change
# the shape of the hub heights array or get the raw data differently.
self.floris.farm.hub_heights = self.floris.farm.hub_heights[0,0]
self.floris.farm.construct_coordinates()

self.floris.flow_field.wind_speeds = wind_speeds
self.floris.flow_field.wind_directions = wind_directions

self.grid = TurbineGrid(
turbine_coordinates=self.floris.farm.coordinates,
reference_turbine_diameter=self.floris.farm.rotor_diameters[0,0],
wind_directions=self.floris.flow_field.wind_directions,
wind_speeds=self.floris.flow_field.wind_speeds,
grid_resolution=self.floris.solver["turbine_grid_points"],
time_series=self.floris.flow_field.time_series,
)
self.floris.initialize_domain()

# @profile
def reinitialize(
self,
wind_speeds: list[float] | NDArrayFloat | None = None,
Expand Down
65 changes: 63 additions & 2 deletions tests/floris_interface_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,66 @@ def test_calculate_no_wake():
assert fi.floris.farm.yaw_angles == yaw_angles


def test_reinitialize():
pass
def test_reset():
"""
Test that the reset function correctly resets the given arguments, and that
it correctly resets the low level FLORIS objects.
When we change the value of the wind speed, FlowField should reinitialize the velocity
arrays with the updated shear profile.
When we change the value of the wind direction, Grid should sort the points, as needed,
and reset the sorted_indeces that are used in Farm. Farm should also reset all of it's
sorted and unsorted data arrays accordingly.
When we change the size of either of these, all data arrays should be resized based on
the number of wind speeds and wind directions.
"""

# First, test that after resetting the wind speed and direction and layout, the calculation
# results haven't changed.
fi = FlorisInterface(configuration=YAML_INPUT)
fi.calculate_wake()
baseline_turbine_powers = fi.get_turbine_powers()

fi.reset(
layout_x=fi.floris.farm.layout_x,
layout_y=fi.floris.farm.layout_y,
wind_directions=fi.floris.flow_field.wind_directions,
wind_speeds=fi.floris.flow_field.wind_speeds,
)
fi.calculate_wake()
test_turbine_powers = fi.get_turbine_powers()

assert np.array_equal(baseline_turbine_powers, test_turbine_powers)


# NOTE: fi.floris.flow_field.wind_directions returns a numpy array of shape (n wind directions)
# If you wrap that in a list below, then it's a list of numpy arrays that is cast to a numpy
# array by the FlowField attrs. The FlowField.wind_directions is used to create the grid,
# so now the Grid data structures have strange shapes.
# The solution is to ensure that these are not unnecessarily wrapped in lists, but this
# will be time consuming to enforce.
# This isn't a problem here because the Grid is not being reinitialized so the shape of the
# data structures is not yet changed.
# fi.reset(
# wind_directions=[fi.floris.flow_field.wind_directions],
# wind_speeds=[fi.floris.flow_field.wind_speeds],
# )
# print(fi.floris.flow_field.wind_directions)


# Since the test layout is three turbines in a line, rotating 180 degrees should produce
# the same farm power and flipped turbine powers
fi.reset(
layout_x=fi.floris.farm.layout_x,
layout_y=fi.floris.farm.layout_y,
wind_directions=fi.floris.flow_field.wind_directions + 10,
wind_speeds=fi.floris.flow_field.wind_speeds + 10,
)
fi.calculate_wake()
rotated_turbine_powers = fi.get_turbine_powers()
assert np.array_equal(baseline_turbine_powers, rotated_turbine_powers)

print(baseline_turbine_powers)
print(rotated_turbine_powers)

0 comments on commit 8c4b625

Please sign in to comment.