diff --git a/examples/wind_farm_power_tracking_florisstandin/amr_input.inp b/examples/wind_farm_power_tracking_florisstandin/amr_input.inp index 3de6ac64..8ef0cd1a 100644 --- a/examples/wind_farm_power_tracking_florisstandin/amr_input.inp +++ b/examples/wind_farm_power_tracking_florisstandin/amr_input.inp @@ -158,24 +158,6 @@ Actuator.UniformCtDisk.num_points_r = 20 Actuator.UniformCtDisk.num_points_t = 5 -Actuator.labels = T00 T01 -# T02 T03 T04 T05 T06 T07 -Actuator.JoukowskyDisk.thrust_coeff = 8.1672e-01 7.9044e-01 7.8393e-01 7.8624e-01 7.8824e-01 7.8942e-01 7.8902e-01 7.8740e-01 7.8503e-01 7.8237e-01 7.7955e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.6922e-01 7.4270e-01 5.5949e-01 4.6163e-01 3.8786e-01 3.2901e-01 2.8093e-01 2.4114e-01 2.0795e-01 1.8010e-01 1.5663e-01 1.3679e-01 1.1995e-01 1.0562e-01 9.3384e-02 8.2908e-02 7.3910e-02 6.6159e-02 5.9463e-02 5.3662e-02 4.8622e-02 4.4230e-02 -Actuator.JoukowskyDisk.wind_speed = 3.0000e+00 3.5495e+00 4.0679e+00 4.5539e+00 5.0064e+00 5.4244e+00 5.8069e+00 6.1530e+00 6.4619e+00 6.7330e+00 6.9655e+00 7.1589e+00 7.3128e+00 7.4269e+00 7.5009e+00 7.5345e+00 7.5412e+00 7.5883e+00 7.6757e+00 7.8031e+00 7.9702e+00 8.1767e+00 8.4221e+00 8.7059e+00 9.0273e+00 9.3856e+00 9.7800e+00 1.0210e+01 1.0659e+01 1.0673e+01 1.1170e+01 1.1699e+01 1.2259e+01 1.2848e+01 1.3465e+01 1.4109e+01 1.4778e+01 1.5471e+01 1.6185e+01 1.6921e+01 1.7674e+01 1.8445e+01 1.9231e+01 2.0030e+01 2.0841e+01 2.1661e+01 2.2489e+01 2.3323e+01 2.4160e+01 2.5000e+01 -Actuator.JoukowskyDisk.rpm = 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0861e+00 5.1954e+00 5.2765e+00 5.3290e+00 5.3529e+00 5.3577e+00 5.3912e+00 5.4532e+00 5.5437e+00 5.6625e+00 5.8092e+00 5.9836e+00 6.1851e+00 6.4135e+00 6.6681e+00 6.9483e+00 7.2535e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 -Actuator.JoukowskyDisk.rotor_diameter = 240.0 -Actuator.JoukowskyDisk.hub_height = 150.0 -Actuator.JoukowskyDisk.output_frequency = 100 -Actuator.JoukowskyDisk.diameters_to_sample = 1.0 -Actuator.JoukowskyDisk.num_points_r = 40 -Actuator.JoukowskyDisk.num_points_t = 5 -Actuator.JoukowskyDisk.num_blades = 3 -Actuator.JoukowskyDisk.use_tip_correction = true -Actuator.JoukowskyDisk.use_root_correction = true -Actuator.JoukowskyDisk.epsilon = 5.0 -Actuator.JoukowskyDisk.vortex_core_size = 24.0 - -Actuator.UniformCtDisk.yaw = 240.0 - +Actuator.labels = T00 T01 Actuator.T00.base_position = 0.0 0.0 0.0 Actuator.T01.base_position = 1000.0 0.0 0.0 diff --git a/whoc/controllers/wind_farm_power_tracking_controller.py b/whoc/controllers/wind_farm_power_tracking_controller.py index 8cc9ad8e..bd2f00b8 100644 --- a/whoc/controllers/wind_farm_power_tracking_controller.py +++ b/whoc/controllers/wind_farm_power_tracking_controller.py @@ -16,7 +16,8 @@ from whoc.controllers.controller_base import ControllerBase -POWER_SETPOINT_DEFAULT = 1e9 +# Default power setpoint in kW (meant to ensure power maximization) +POWER_SETPOINT_DEFAULT = 1e9 class WindFarmPowerDistributingController(ControllerBase): """ @@ -65,7 +66,8 @@ def turbine_power_references(self, farm_power_reference=POWER_SETPOINT_DEFAULT): class WindFarmPowerTrackingController(WindFarmPowerDistributingController): """ - Based on controller developed under A2e2g project. + Based on controller developed under A2e2g project. Proportional control only--- + all integral action is disabled. Inherits from WindFarmPowerDistributingController. """ @@ -74,19 +76,19 @@ def __init__(self, interface, input_dict, proportional_gain=1, verbose=False): super().__init__(interface, input_dict, verbose=verbose) # No integral action for now. beta and omega_n not used. - beta=0.7 - omega_n=0.01 - integral_gain=0 + # beta=0.7 + # omega_n=0.01 + # integral_gain=0 self.K_p = proportional_gain * 1/self.n_turbines - self.K_i = integral_gain *(4*beta*omega_n) + # self.K_i = integral_gain *(4*beta*omega_n) # Initialize controller (only used for integral action) - self.e_prev = 0 - self.u_prev = 0 - self.u_i_prev = 0 - self.ai_prev = [0.33]*self.n_turbines # TODO: different method for anti-windup? - self.n_saturated = 0 + # self.e_prev = 0 + # self.u_prev = 0 + # self.u_i_prev = 0 + # self.ai_prev = [0.33]*self.n_turbines # TODO: different method for anti-windup? + # self.n_saturated = 0 def turbine_power_references(self, farm_power_reference=POWER_SETPOINT_DEFAULT): """ @@ -109,19 +111,19 @@ def turbine_power_references(self, farm_power_reference=POWER_SETPOINT_DEFAULT): else: gain_adjustment = self.n_turbines K_p_gs = gain_adjustment*self.K_p - K_i_gs = gain_adjustment*self.K_i + #K_i_gs = gain_adjustment*self.K_i # Discretize and apply difference equation (trapezoid rule) u_p = K_p_gs*farm_current_error - u_i = self.dt/2*K_i_gs * (farm_current_error + self.e_prev) + self.u_i_prev + #u_i = self.dt/2*K_i_gs * (farm_current_error + self.e_prev) + self.u_i_prev # Apply integral anti-windup - eps = 0.0001 # Threshold for anti-windup - if (np.array(self.ai_prev) > 1/3-eps).all() or \ - (np.array(self.ai_prev) < 0+eps).all(): - u_i = 0 + #eps = 0.0001 # Threshold for anti-windup + #if (np.array(self.ai_prev) > 1/3-eps).all() or \ + # (np.array(self.ai_prev) < 0+eps).all(): + # u_i = 0 - u = u_p + u_i + u = u_p #+ u_i delta_P_ref = u turbine_power_setpoints = np.array(turbine_current_powers) + delta_P_ref @@ -133,9 +135,9 @@ def turbine_power_references(self, farm_power_reference=POWER_SETPOINT_DEFAULT): "yaw_angles": [-1000]*self.n_turbines } - # Store error, control - self.e_prev = farm_current_error - self.u_prev = u - self.u_i_prev = u_i + # Store error, control (only needed for integral action, which is disabled) + # self.e_prev = farm_current_error + # self.u_prev = u + # self.u_i_prev = u_i return None