diff --git a/floris/tools/floris_interface.py b/floris/tools/floris_interface.py index ea6e2d036..e8a5fda04 100644 --- a/floris/tools/floris_interface.py +++ b/floris/tools/floris_interface.py @@ -164,9 +164,9 @@ def set( n_findex x n_turbines. True values indicate the turbine is disabled at that findex and the power setpoint at that position is set to 0. Defaults to None. """ - # Reinitialize the floris object after saving the setpoints - save_yaw_angles = self.floris.farm.yaw_angles - save_power_setpoints = self.floris.farm.power_setpoints + # Initialize a new Floris object after saving the setpoints + _yaw_angles = self.floris.farm.yaw_angles + _power_setpoints = self.floris.farm.power_setpoints self._reinitialize( wind_speeds=wind_speeds, wind_directions=wind_directions, @@ -183,13 +183,16 @@ def set( heterogenous_inflow_config=heterogenous_inflow_config, wind_data=wind_data, ) - if not (save_yaw_angles == 0).all(): - self.floris.farm.yaw_angles = save_yaw_angles + + # 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 if not ( - (save_power_setpoints == POWER_SETPOINT_DEFAULT) - | (save_power_setpoints == POWER_SETPOINT_DISABLED) + (_power_setpoints == POWER_SETPOINT_DEFAULT) + | (_power_setpoints == POWER_SETPOINT_DISABLED) ).all(): - self.floris.farm.power_setpoints = save_power_setpoints + self.floris.farm.power_setpoints = _power_setpoints # Set the operation self._set_operation( @@ -200,42 +203,10 @@ def set( def reset_operation(self): """ - Reinstantiate the floris interface and set all operation setpoints to their default values. - - Args: (None) + Instantiate a new Floris object to set all operation setpoints to their default values. """ self._reinitialize() - def run(self) -> None: - """ - Run the FLORIS solve to compute the velocity field and wake effects. - - Args: (None) - """ - - # Initialize solution space - self.floris.initialize_domain() - - # Perform the wake calculations - self.floris.steady_state_atmospheric_condition() - - def run_no_wake( - self, - ) -> None: - """ - This function is similar to `run()` except that it does not apply a wake model. That is, - the wind farm is modeled as if there is no wake in the flow. Yaw angles are used to reduce - the power and thrust of the turbine that is yawed. - - Args: (None) - """ - - # Initialize solution space - self.floris.initialize_domain() - - # Finalize values to user-supplied order - self.floris.finalize() - def _reinitialize( self, wind_speeds: list[float] | NDArrayFloat | None = None, @@ -254,7 +225,8 @@ def _reinitialize( wind_data: type[WindDataBase] | None = None, ): """ - Reinstantiate the floris object with updated conditions set by arguments. + Instantiate a new Floris object with updated conditions set by arguments. Any parameters + in Floris that aren't changed by arguments to this function retain their values. Args: wind_speeds (NDArrayFloat | list[float] | None, optional): Wind speeds at each findex. @@ -423,6 +395,30 @@ def _set_operation( self.floris.farm.yaw_angles[disable_turbines] = 0.0 self.floris.farm.power_setpoints[disable_turbines] = POWER_SETPOINT_DISABLED + def run(self) -> None: + """ + Run the FLORIS solve to compute the velocity field and wake effects. + """ + + # Initialize solution space + self.floris.initialize_domain() + + # Perform the wake calculations + self.floris.steady_state_atmospheric_condition() + + def run_no_wake(self) -> None: + """ + This function is similar to `run()` except that it does not apply a wake model. That is, + the wind farm is modeled as if there is no wake in the flow. Operation settings may + reduce the power and thrust of the turbine to where they're applied. + """ + + # Initialize solution space + self.floris.initialize_domain() + + # Finalize values to user-supplied order + self.floris.finalize() + def get_plane_of_points( self, normal_vector="z", diff --git a/tests/floris_interface_integration_test.py b/tests/floris_interface_integration_test.py index 9f63f2834..2bdedfd4d 100644 --- a/tests/floris_interface_integration_test.py +++ b/tests/floris_interface_integration_test.py @@ -238,12 +238,12 @@ def test_disable_turbines(): layout_y=[0,0,0] ) - # Confirm that passing in a disable value with wrong n_findex raises error + # Confirm that using a disable value with wrong n_findex raises error with pytest.raises(ValueError): fi.set(disable_turbines=np.zeros((10, 3), dtype=bool)) fi.run() - # Confirm that passing in a disable value with wrong n_turbines raises error + # Confirm that using a disable value with wrong n_turbines raises error with pytest.raises(ValueError): fi.set(disable_turbines=np.zeros((2, 10), dtype=bool)) fi.run() @@ -252,12 +252,12 @@ def test_disable_turbines(): fi.set(disable_turbines=np.ones((2, 3), dtype=bool)) fi.run() turbines_powers = fi.get_turbine_powers() - np.testing.assert_allclose(turbines_powers,0,atol=0.1) + np.testing.assert_allclose(turbines_powers, 0, atol=0.1) # Confirm the same for run_no_wake fi.run_no_wake() turbines_powers = fi.get_turbine_powers() - np.testing.assert_allclose(turbines_powers,0,atol=0.1) + np.testing.assert_allclose(turbines_powers, 0, atol=0.1) # Confirm that if all disabled values set to false, equivalent to running normally fi.reset_operation() @@ -284,7 +284,8 @@ def test_disable_turbines(): fi.run() power_with_middle_disabled = fi.get_turbine_powers() - fi.set(layout_x = [0,2000],layout_y = [0, 0], disable_turbines=np.zeros((2, 2), dtype=bool)) + disable_turbines = np.zeros((2, 3), dtype=bool) + fi.set(layout_x=[0,2000], layout_y=[0, 0], disable_turbines=disable_turbines) fi.run() power_with_middle_removed = fi.get_turbine_powers() @@ -293,8 +294,8 @@ def test_disable_turbines(): # Check that yaw angles are correctly set when turbines are disabled fi.set( - layout_x=[0,1000,2000], - layout_y=[0,0,0], + layout_x=[0, 1000, 2000], + layout_y=[0, 0, 0], disable_turbines=disable_turbines, yaw_angles=np.ones((2, 3)) )