diff --git a/docs/graphics/wf-power-tracking-plot.png b/docs/graphics/wf-power-tracking-plot.png index fb75bc81..0dd39a59 100644 Binary files a/docs/graphics/wf-power-tracking-plot.png and b/docs/graphics/wf-power-tracking-plot.png differ diff --git a/examples/lookup-based_wake_steering_florisstandin/plot_output_data.py b/examples/lookup-based_wake_steering_florisstandin/plot_output_data.py index e8307734..afd7db45 100644 --- a/examples/lookup-based_wake_steering_florisstandin/plot_output_data.py +++ b/examples/lookup-based_wake_steering_florisstandin/plot_output_data.py @@ -2,7 +2,7 @@ import numpy as np import pandas as pd -df = pd.read_csv("hercules_output.csv") +df = pd.read_csv("outputs/hercules_output.csv") print(df.columns) diff --git a/setup.py b/setup.py index 47914fd9..f0e3c481 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ # What packages are required for this module to be executed? REQUIRED = [ "numpy~=1.20", - # "flasc", + "flasc~=2.0", # "matplotlib~=3.0", # "pandas~=2.0", # "dash>=2.0.0", diff --git a/tests/controller_library_test.py b/tests/controller_library_test.py index 1d28e11e..89163437 100644 --- a/tests/controller_library_test.py +++ b/tests/controller_library_test.py @@ -12,6 +12,7 @@ # See https://nrel.github.io/wind-hybrid-open-controller for documentation import numpy as np +import pandas as pd # import pandas as pd from whoc.controllers import ( @@ -73,50 +74,50 @@ def test_controller_instantiation(): _ = WindFarmPowerTrackingController(interface=test_interface, input_dict=test_hercules_dict) -# def test_LookupBasedWakeSteeringController(): -# test_interface = HerculesADInterface(test_hercules_dict) - -# # No lookup table passed; simply passes through wind direction to yaw angles -# test_controller = LookupBasedWakeSteeringController( -# interface=test_interface, -# input_dict=test_hercules_dict -# ) - -# # Check that the controller can be stepped -# test_hercules_dict["time"] = 20 -# test_hercules_dict_out = test_controller.step(hercules_dict=test_hercules_dict) -# test_angles = np.array( -# test_hercules_dict_out["hercules_comms"]["amr_wind"]["test_farm"]["turbine_yaw_angles"] -# ) -# wind_directions = np.array( -# test_hercules_dict["hercules_comms"]["amr_wind"]["test_farm"]["turbine_wind_directions"] -# ) -# assert np.allclose(test_angles, wind_directions) - -# # Lookup table that specified 20 degree offset for T000, 10 degree offset for T001 for all -# # wind directions -# test_offsets = np.array([20.0, 10.0]) -# df_opt_test = pd.DataFrame(data={ -# "wind_direction":[220.0, 320.0, 220.0, 320.0], -# "wind_speed":[0.0, 0.0, 20.0, 20.0], -# "yaw_angles_opt":[test_offsets]*4, -# "turbulence_intensity":[0.06]*4 -# }) -# test_controller = LookupBasedWakeSteeringController( -# interface=test_interface, -# input_dict=test_hercules_dict, -# df_yaw=df_opt_test -# ) - -# test_hercules_dict["time"] = 20 -# test_hercules_dict_out = test_controller.step(hercules_dict=test_hercules_dict) -# test_angles = np.array( -# test_hercules_dict_out["hercules_comms"]["amr_wind"]["test_farm"]["turbine_yaw_angles"] -# ) -# wind_directions = np.array( -# test_hercules_dict["hercules_comms"]["amr_wind"]["test_farm"]["turbine_wind_directions"] -# ) -# assert np.allclose(test_angles, wind_directions - test_offsets) +def test_LookupBasedWakeSteeringController(): + test_interface = HerculesADInterface(test_hercules_dict) + + # No lookup table passed; simply passes through wind direction to yaw angles + test_controller = LookupBasedWakeSteeringController( + interface=test_interface, + input_dict=test_hercules_dict + ) + + # Check that the controller can be stepped + test_hercules_dict["time"] = 20 + test_hercules_dict_out = test_controller.step(hercules_dict=test_hercules_dict) + test_angles = np.array( + test_hercules_dict_out["hercules_comms"]["amr_wind"]["test_farm"]["turbine_yaw_angles"] + ) + wind_directions = np.array( + test_hercules_dict["hercules_comms"]["amr_wind"]["test_farm"]["turbine_wind_directions"] + ) + assert np.allclose(test_angles, wind_directions) + + # Lookup table that specified 20 degree offset for T000, 10 degree offset for T001 for all + # wind directions + test_offsets = np.array([20.0, 10.0]) + df_opt_test = pd.DataFrame(data={ + "wind_direction":[220.0, 320.0, 220.0, 320.0], + "wind_speed":[0.0, 0.0, 20.0, 20.0], + "yaw_angles_opt":[test_offsets]*4, + "turbulence_intensity":[0.06]*4 + }) + test_controller = LookupBasedWakeSteeringController( + interface=test_interface, + input_dict=test_hercules_dict, + df_yaw=df_opt_test + ) + + test_hercules_dict["time"] = 20 + test_hercules_dict_out = test_controller.step(hercules_dict=test_hercules_dict) + test_angles = np.array( + test_hercules_dict_out["hercules_comms"]["amr_wind"]["test_farm"]["turbine_yaw_angles"] + ) + wind_directions = np.array( + test_hercules_dict["hercules_comms"]["amr_wind"]["test_farm"]["turbine_wind_directions"] + ) + assert np.allclose(test_angles, wind_directions - test_offsets) def test_WindBatteryController(): diff --git a/whoc/controllers/lookup_based_wake_steering_controller.py b/whoc/controllers/lookup_based_wake_steering_controller.py index 07e05144..3bfc3528 100644 --- a/whoc/controllers/lookup_based_wake_steering_controller.py +++ b/whoc/controllers/lookup_based_wake_steering_controller.py @@ -14,7 +14,7 @@ import numpy as np -#from flasc.wake_steering.lookup_table_tools import get_yaw_angles_interpolant +from flasc.utilities.lookup_table_tools import get_yaw_angles_interpolant from whoc.controllers.controller_base import ControllerBase @@ -32,12 +32,7 @@ def __init__(self, interface, input_dict, df_yaw=None, verbose=False): print("No offsets received; assuming nominal aligned control.") self.wake_steering_interpolant = None else: - # Temporarily raise an error, until we have FLASC updated and compatible - raise NotImplementedError( - "The wake steering controller is not currently implemented due to a dependency ", - " conflict from FLASC." - ) - # self.wake_steering_interpolant = get_yaw_angles_interpolant(df_yaw) + self.wake_steering_interpolant = get_yaw_angles_interpolant(df_yaw) # Set initial conditions yaw_IC = input_dict["controller"]["initial_conditions"]["yaw"] diff --git a/whoc/interfaces/hercules_actuator_disk_interface.py b/whoc/interfaces/hercules_actuator_disk_interface.py index 342ff0aa..3a6f8a7a 100644 --- a/whoc/interfaces/hercules_actuator_disk_interface.py +++ b/whoc/interfaces/hercules_actuator_disk_interface.py @@ -42,7 +42,8 @@ def get_measurements(self, hercules_dict): turbine_powers = hercules_dict["hercules_comms"]["amr_wind"][self.wf_name]["turbine_powers"] time = hercules_dict["time"] - if "wind_power_reference" in hercules_dict["external_signals"]: + if ("external_signals" in hercules_dict + and "wind_power_reference" in hercules_dict["external_signals"]): wind_power_reference = hercules_dict["external_signals"]["wind_power_reference"] else: wind_power_reference = POWER_SETPOINT_DEFAULT