Skip to content

Commit

Permalink
Add reset function to FlorisInterface
Browse files Browse the repository at this point in the history
  • Loading branch information
rafmudaf committed Jan 19, 2024
1 parent 58b2cb9 commit 96c6e10
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 6 deletions.
34 changes: 34 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,39 @@ 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.flow_field.wind_speeds = wind_speeds
self.floris.flow_field.wind_directions = wind_directions

self.floris.grid = TurbineGrid(
turbine_coordinates=self.floris.farm.coordinates,
turbine_diameters=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
72 changes: 66 additions & 6 deletions tests/floris_interface_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_calculate_wake():
)
)
fi.calculate_wake(yaw_angles=yaw_angles)
assert fi.floris.farm.yaw_angles == yaw_angles
assert np.array_equal(fi.floris.farm.yaw_angles, yaw_angles)

yaw_angles = np.zeros(
(
Expand All @@ -41,7 +41,7 @@ def test_calculate_wake():
)
)
fi.calculate_wake(yaw_angles=yaw_angles)
assert fi.floris.farm.yaw_angles == yaw_angles
assert np.array_equal(fi.floris.farm.yaw_angles, yaw_angles)


def test_calculate_no_wake():
Expand All @@ -59,7 +59,7 @@ def test_calculate_no_wake():
)
)
fi.calculate_no_wake(yaw_angles=yaw_angles)
assert fi.floris.farm.yaw_angles == yaw_angles
assert np.array_equal(fi.floris.farm.yaw_angles, yaw_angles)

yaw_angles = np.zeros(
(
Expand All @@ -69,8 +69,68 @@ def test_calculate_no_wake():
)
)
fi.calculate_no_wake(yaw_angles=yaw_angles)
assert fi.floris.farm.yaw_angles == yaw_angles
assert np.array_equal(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)

# 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 + 180,
wind_speeds=fi.floris.flow_field.wind_speeds,
)
fi.calculate_wake()
rotated_turbine_powers = fi.get_turbine_powers()
assert np.array_equal(
baseline_turbine_powers,
rotated_turbine_powers[:,:,::-1] # turbine dimension is flipped below
)

# At 90 degree rotation, all turbines are unwaked so all turbine powers should be equal
# to the upstream turbine in the baseline array
fi.reset(
layout_x=fi.floris.farm.layout_x,
layout_y=fi.floris.farm.layout_y,
wind_directions=fi.floris.flow_field.wind_directions + 90,
wind_speeds=fi.floris.flow_field.wind_speeds,
)
fi.calculate_wake()
unwaked_turbine_powers = fi.get_turbine_powers()
n_turbines = fi.floris.farm.n_turbines
assert np.array_equal(
np.repeat(baseline_turbine_powers[:,:,0:1], n_turbines, axis=2),
unwaked_turbine_powers
)

0 comments on commit 96c6e10

Please sign in to comment.