Skip to content

Commit

Permalink
[Bugfix] Cast yaw angles to np.ndarray on set (#828)
Browse files Browse the repository at this point in the history
* Add tests of setting yaw

* Move to the correct file

* fix dimensions

* numpy conversion on passed yaw_angles.

* Tests for power setpoints, disabling turbines, combinations.

* Switch to setter methods for yaw angles and power setpoints.

---------

Co-authored-by: misi9170 <michael.sinner@nrel.gov>
  • Loading branch information
paulf81 and misi9170 authored Mar 6, 2024
1 parent 8ac93bf commit a60060c
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 16 deletions.
16 changes: 12 additions & 4 deletions floris/simulation/farm.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,12 @@ def expand_farm_properties(self, n_findex: int, sorted_coord_indices):
axis=1
)

def set_yaw_angles(self, n_findex: int):
self.yaw_angles = np.zeros((n_findex, self.n_turbines))
def set_yaw_angles(self, yaw_angles: NDArrayFloat | list[float]):
self.yaw_angles = np.array(yaw_angles)

def set_yaw_angles_to_ref_yaw(self, n_findex: int):
yaw_angles = np.zeros((n_findex, self.n_turbines))
self.set_yaw_angles(yaw_angles)
self.yaw_angles_sorted = np.zeros((n_findex, self.n_turbines))

def set_tilt_to_ref_tilt(self, n_findex: int):
Expand All @@ -343,8 +347,12 @@ def set_tilt_to_ref_tilt(self, n_findex: int):
* self.ref_tilts
)

def set_power_setpoints(self, n_findex: int):
self.power_setpoints = POWER_SETPOINT_DEFAULT * np.ones((n_findex, self.n_turbines))
def set_power_setpoints(self, power_setpoints: NDArrayFloat):
self.power_setpoints = np.array(power_setpoints)

def set_power_setpoints_to_ref_power(self, n_findex: int):
power_setpoints = POWER_SETPOINT_DEFAULT * np.ones((n_findex, self.n_turbines))
self.set_power_setpoints(power_setpoints)
self.power_setpoints_sorted = POWER_SETPOINT_DEFAULT * np.ones((n_findex, self.n_turbines))

def calculate_tilt_for_eff_velocities(self, rotor_effective_velocities):
Expand Down
4 changes: 2 additions & 2 deletions floris/simulation/floris.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ def __attrs_post_init__(self) -> None:
self.farm.construct_turbine_ref_tilts()
self.farm.construct_turbine_tilt_interps()
self.farm.construct_turbine_correct_cp_ct_for_tilt()
self.farm.set_yaw_angles(self.flow_field.n_findex)
self.farm.set_yaw_angles_to_ref_yaw(self.flow_field.n_findex)
self.farm.set_tilt_to_ref_tilt(self.flow_field.n_findex)
self.farm.set_power_setpoints(self.flow_field.n_findex)
self.farm.set_power_setpoints_to_ref_power(self.flow_field.n_findex)

if self.solver["type"] == "turbine_grid":
self.grid = TurbineGrid(
Expand Down
8 changes: 4 additions & 4 deletions floris/tools/floris_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,12 @@ def set(
# If the yaw angles or power setpoints are not the default, set them back to the
# previous setting
if not (_yaw_angles == 0).all():
self.floris.farm.yaw_angles = _yaw_angles
self.floris.farm.set_yaw_angles(_yaw_angles)
if not (
(_power_setpoints == POWER_SETPOINT_DEFAULT)
| (_power_setpoints == POWER_SETPOINT_DISABLED)
).all():
self.floris.farm.power_setpoints = _power_setpoints
self.floris.farm.set_power_setpoints(_power_setpoints)

# Set the operation
self._set_operation(
Expand Down Expand Up @@ -355,7 +355,7 @@ def _set_operation(
"""
# Add operating conditions to the floris object
if yaw_angles is not None:
self.floris.farm.yaw_angles = yaw_angles
self.floris.farm.set_yaw_angles(yaw_angles)

if power_setpoints is not None:
power_setpoints = np.array(power_setpoints)
Expand All @@ -366,7 +366,7 @@ def _set_operation(
] = POWER_SETPOINT_DEFAULT
power_setpoints = floris_array_converter(power_setpoints)

self.floris.farm.power_setpoints = power_setpoints
self.floris.farm.set_power_setpoints(power_setpoints)

# Check for turbines to disable
if disable_turbines is not None:
Expand Down
2 changes: 1 addition & 1 deletion floris/tools/uncertainty_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def _expand_wind_directions_and_yaw_angles(self):
def _reassign_yaw_angles(self, yaw_angles=None):
# Overwrite the yaw angles in the FlorisInterface object
if yaw_angles is not None:
self.fi.floris.farm.yaw_angles = yaw_angles
self.fi.floris.farm.set_yaw_angles(yaw_angles)

# Public methods

Expand Down
10 changes: 5 additions & 5 deletions tests/farm_unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def test_farm_init_homogenous_turbines():
# turbine_type=[turbine_data["turbine_type"]]

farm.construct_hub_heights()
farm.set_yaw_angles(N_FINDEX)
farm.set_yaw_angles_to_ref_yaw(N_FINDEX)

# Check initial values
np.testing.assert_array_equal(farm.coordinates, coordinates)
Expand All @@ -47,17 +47,17 @@ def test_asdict(sample_inputs_fixture: SampleInputs):
farm = Farm.from_dict(sample_inputs_fixture.farm)
farm.construct_hub_heights()
farm.construct_turbine_ref_tilts()
farm.set_yaw_angles(N_FINDEX)
farm.set_yaw_angles_to_ref_yaw(N_FINDEX)
farm.set_tilt_to_ref_tilt(N_FINDEX)
farm.set_power_setpoints(N_FINDEX)
farm.set_power_setpoints_to_ref_power(N_FINDEX)
dict1 = farm.as_dict()

new_farm = farm.from_dict(dict1)
new_farm.construct_hub_heights()
new_farm.construct_turbine_ref_tilts()
new_farm.set_yaw_angles(N_FINDEX)
new_farm.set_yaw_angles_to_ref_yaw(N_FINDEX)
new_farm.set_tilt_to_ref_tilt(N_FINDEX)
new_farm.set_power_setpoints(N_FINDEX)
new_farm.set_power_setpoints_to_ref_power(N_FINDEX)
dict2 = new_farm.as_dict()

assert dict1 == dict2
Expand Down
25 changes: 25 additions & 0 deletions tests/floris_interface_integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@ def test_read_yaml():
fi = FlorisInterface(configuration=YAML_INPUT)
assert isinstance(fi, FlorisInterface)

def test_assign_setpoints():

fi = FlorisInterface(configuration=YAML_INPUT)
fi.set(layout_x=[0, 0], layout_y=[0, 1000])

# Test setting yaw angles via a list, integers, numpy array
fi.set(yaw_angles=[[20.0, 30.0]])
fi.set(yaw_angles=[[20, 30]])
fi.set(yaw_angles=np.array([[20.0, 30.0]]))

# Test setting power setpoints in various ways
fi.set(power_setpoints=[[1e6, 2e6]])
fi.set(power_setpoints=np.array([[1e6, 2e6]]))

# Disable turbines
fi.set(disable_turbines=[[True, False]])
fi.set(disable_turbines=np.array([[True, False]]))

# Combination
fi.set(yaw_angles=[[0, 30]], power_setpoints=np.array([[1e6, None]]))

# power_setpoints and disable_turbines (disable_turbines overrides power_setpoints)
fi.set(power_setpoints=[[1e6, 2e6]], disable_turbines=[[True, False]])
assert np.allclose(fi.floris.farm.power_setpoints, np.array([[0.001, 2e6]]))

def test_set_run():
"""
These tests are designed to test the set / run sequence to ensure that inputs are
Expand Down

0 comments on commit a60060c

Please sign in to comment.