From 0cc12839b283d070b2191fec5fcd5e2feee0f59e Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 12 Jun 2019 15:17:01 -0600 Subject: [PATCH 1/5] Add a new option to compute yaw loss by w-exp --- floris/simulation/turbine.py | 44 ++++++++++++++++++++++++++++++++ floris/tools/floris_utilities.py | 13 ++++++++++ 2 files changed, 57 insertions(+) diff --git a/floris/simulation/turbine.py b/floris/simulation/turbine.py index 4b9603e65..8bd9c0a13 100644 --- a/floris/simulation/turbine.py +++ b/floris/simulation/turbine.py @@ -424,6 +424,29 @@ def Cp(self): """ return self._fCp(self.average_velocity) + # @property + def Cp_new(self, scaled_velocity): + """ + This property returns the power coeffcient of a turbine. + + This property returns the coefficient of power of the turbine + using the rotor swept area average velocity, interpolated from + the coefficient of power table. The average velocity is + calculated as the cube root of the mean cubed velocity in the + rotor area. + + Returns: + float: The power coefficient of a turbine at the current + operating conditions. + + Examples: + To get the power coefficient value for a turbine: + + >>> Cp = floris.farm.turbines[0].Cp() + """ + + return self._fCp(scaled_velocity) + @property def Ct(self): """ @@ -467,6 +490,27 @@ def power(self): * cptmp * self.generator_efficiency \ * self.average_velocity**3 + @property + def power_new(self): + """ + This property returns the power produced by turbine (W), + adjusted for yaw and tilt. + + Returns: + float: Power of a turbine in watts. + + Examples: + To get the power for a turbine: + + >>> power = floris.farm.turbines[0].power() + """ + p_w = 0.6 # Based on Optimising yaw control at wind farm level + scaled_velocity = self.average_velocity * cosd(self.yaw_angle) ** p_w + cptmp = self.Cp_new(scaled_velocity) + return 0.5 * self.air_density * (np.pi * self.rotor_radius**2) \ + * cptmp * self.generator_efficiency \ + * scaled_velocity**3 + @property def aI(self): """ diff --git a/floris/tools/floris_utilities.py b/floris/tools/floris_utilities.py index 376c70ea6..6b36729dc 100644 --- a/floris/tools/floris_utilities.py +++ b/floris/tools/floris_utilities.py @@ -287,6 +287,19 @@ def get_turbine_power(self): ] return turb_powers + def get_turbine_power_new(self): + """ + Report power from each wind turbine from instance of floris. + + Returns: + turb_powers (np.array): power produced by each wind turbine. + """ + turb_powers = [ + turbine.power_new + for turbine in self.floris.farm.flow_field.turbine_map.turbines + ] + return turb_powers + def get_turbine_ct(self): """ Report thrust coefficient from each wind turbine from instance of floris. From 5b2ab0293ff26f1a015f6b48d6669c4b8ad5d4ec Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 12 Jun 2019 16:00:40 -0600 Subject: [PATCH 2/5] compute w as function of pP to minimze api impact --- floris/simulation/turbine.py | 84 +++++++++++++++----------------- floris/tools/floris_utilities.py | 13 ----- 2 files changed, 39 insertions(+), 58 deletions(-) diff --git a/floris/simulation/turbine.py b/floris/simulation/turbine.py index 8bd9c0a13..1732b5080 100644 --- a/floris/simulation/turbine.py +++ b/floris/simulation/turbine.py @@ -402,30 +402,30 @@ def average_velocity(self): """ return np.cbrt(np.mean(self.velocities**3)) - @property - def Cp(self): - """ - This property returns the power coeffcient of a turbine. + # @property + # def Cp(self): + # """ + # This property returns the power coeffcient of a turbine. - This property returns the coefficient of power of the turbine - using the rotor swept area average velocity, interpolated from - the coefficient of power table. The average velocity is - calculated as the cube root of the mean cubed velocity in the - rotor area. + # This property returns the coefficient of power of the turbine + # using the rotor swept area average velocity, interpolated from + # the coefficient of power table. The average velocity is + # calculated as the cube root of the mean cubed velocity in the + # rotor area. - Returns: - float: The power coefficient of a turbine at the current - operating conditions. + # Returns: + # float: The power coefficient of a turbine at the current + # operating conditions. - Examples: - To get the power coefficient value for a turbine: + # Examples: + # To get the power coefficient value for a turbine: - >>> Cp = floris.farm.turbines[0].Cp() - """ - return self._fCp(self.average_velocity) + # >>> Cp = floris.farm.turbines[0].Cp() + # """ + # return self._fCp(self.average_velocity) - # @property - def Cp_new(self, scaled_velocity): + @property + def Cp(self): """ This property returns the power coeffcient of a turbine. @@ -444,8 +444,11 @@ def Cp_new(self, scaled_velocity): >>> Cp = floris.farm.turbines[0].Cp() """ - - return self._fCp(scaled_velocity) + # Compute the yaw effective velocity + p_w = self.pP / 2.88 # Convert from pP to w + yaw_effective_velocity = self.average_velocity * cosd(self.yaw_angle) ** p_w + + return self._fCp(yaw_effective_velocity) @property def Ct(self): @@ -483,33 +486,24 @@ def power(self): >>> power = floris.farm.turbines[0].power() """ - cptmp = self.Cp \ - * cosd(self.yaw_angle)**self.pP \ - * cosd(self.tilt_angle)**self.pT - return 0.5 * self.air_density * (np.pi * self.rotor_radius**2) \ - * cptmp * self.generator_efficiency \ - * self.average_velocity**3 - - @property - def power_new(self): - """ - This property returns the power produced by turbine (W), - adjusted for yaw and tilt. - Returns: - float: Power of a turbine in watts. - - Examples: - To get the power for a turbine: - - >>> power = floris.farm.turbines[0].power() - """ - p_w = 0.6 # Based on Optimising yaw control at wind farm level - scaled_velocity = self.average_velocity * cosd(self.yaw_angle) ** p_w - cptmp = self.Cp_new(scaled_velocity) + # Update to power calculation which replaces the fixed pP exponent with + # an exponent w, that changes the effective wind speed input to the power + # calculation, rather than scaling the power. This better handles power + # loss to yaw in above rated conditions + # + # based on the paper Optimising yaw control at wind farm level by + # Ervin Bossanyi + + # Compute the yaw effective velocity + p_w = self.pP / 2.88 # Convert from pP to w + yaw_effective_velocity = self.average_velocity * cosd(self.yaw_angle) ** p_w + + # Now compute the power + cptmp = self.Cp #Note Cp is also now based on yaw effective velocity return 0.5 * self.air_density * (np.pi * self.rotor_radius**2) \ * cptmp * self.generator_efficiency \ - * scaled_velocity**3 + * yaw_effective_velocity**3 @property def aI(self): diff --git a/floris/tools/floris_utilities.py b/floris/tools/floris_utilities.py index 6b36729dc..376c70ea6 100644 --- a/floris/tools/floris_utilities.py +++ b/floris/tools/floris_utilities.py @@ -287,19 +287,6 @@ def get_turbine_power(self): ] return turb_powers - def get_turbine_power_new(self): - """ - Report power from each wind turbine from instance of floris. - - Returns: - turb_powers (np.array): power produced by each wind turbine. - """ - turb_powers = [ - turbine.power_new - for turbine in self.floris.farm.flow_field.turbine_map.turbines - ] - return turb_powers - def get_turbine_ct(self): """ Report thrust coefficient from each wind turbine from instance of floris. From ce1c2192e6f97f116a2427c96147c2be8d34398e Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 12 Jun 2019 16:02:04 -0600 Subject: [PATCH 3/5] clean up comments --- floris/simulation/turbine.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/floris/simulation/turbine.py b/floris/simulation/turbine.py index 1732b5080..0b56226d5 100644 --- a/floris/simulation/turbine.py +++ b/floris/simulation/turbine.py @@ -402,27 +402,6 @@ def average_velocity(self): """ return np.cbrt(np.mean(self.velocities**3)) - # @property - # def Cp(self): - # """ - # This property returns the power coeffcient of a turbine. - - # This property returns the coefficient of power of the turbine - # using the rotor swept area average velocity, interpolated from - # the coefficient of power table. The average velocity is - # calculated as the cube root of the mean cubed velocity in the - # rotor area. - - # Returns: - # float: The power coefficient of a turbine at the current - # operating conditions. - - # Examples: - # To get the power coefficient value for a turbine: - - # >>> Cp = floris.farm.turbines[0].Cp() - # """ - # return self._fCp(self.average_velocity) @property def Cp(self): From f8abc208db74f70a5f7539dcee8331209741cae0 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 13 Jun 2019 10:55:49 -0600 Subject: [PATCH 4/5] Update comments, and pW=pP/3 --- floris/simulation/turbine.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/floris/simulation/turbine.py b/floris/simulation/turbine.py index 0b56226d5..7c3805deb 100644 --- a/floris/simulation/turbine.py +++ b/floris/simulation/turbine.py @@ -414,6 +414,8 @@ def Cp(self): calculated as the cube root of the mean cubed velocity in the rotor area. + Note, the velocity is scalled to an effective velocity by the yaw + Returns: float: The power coefficient of a turbine at the current operating conditions. @@ -424,8 +426,8 @@ def Cp(self): >>> Cp = floris.farm.turbines[0].Cp() """ # Compute the yaw effective velocity - p_w = self.pP / 2.88 # Convert from pP to w - yaw_effective_velocity = self.average_velocity * cosd(self.yaw_angle) ** p_w + pW = self.pP / 3.0 # Convert from pP to pW + yaw_effective_velocity = self.average_velocity * cosd(self.yaw_angle) ** pW return self._fCp(yaw_effective_velocity) @@ -467,16 +469,16 @@ def power(self): """ # Update to power calculation which replaces the fixed pP exponent with - # an exponent w, that changes the effective wind speed input to the power + # an exponent pW, that changes the effective wind speed input to the power # calculation, rather than scaling the power. This better handles power # loss to yaw in above rated conditions # - # based on the paper Optimising yaw control at wind farm level by + # based on the paper "Optimising yaw control at wind farm level" by # Ervin Bossanyi # Compute the yaw effective velocity - p_w = self.pP / 2.88 # Convert from pP to w - yaw_effective_velocity = self.average_velocity * cosd(self.yaw_angle) ** p_w + pW = self.pP / 3.0 # Convert from pP to w + yaw_effective_velocity = self.average_velocity * cosd(self.yaw_angle) ** pW # Now compute the power cptmp = self.Cp #Note Cp is also now based on yaw effective velocity From df0b3a8626ee0d9f7492a49266b322fae9bb29ee Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 13 Jun 2019 11:06:09 -0600 Subject: [PATCH 5/5] small unit test update --- tests/curl_regression_test.py | 2 +- tests/gauss_regression_test.py | 2 +- tests/jensen_jimenez_regression_test.py | 2 +- tests/multizone_jimenez_regression_test.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/curl_regression_test.py b/tests/curl_regression_test.py index a6c1c9081..321c57c68 100644 --- a/tests/curl_regression_test.py +++ b/tests/curl_regression_test.py @@ -39,7 +39,7 @@ def baseline(self, turbine_index): def yawed_baseline(self, turbine_index): baseline = [ - (0.4632707, 0.7626735 , 1780240.6778116, 0.2559082, 7.9727208), + (0.4632734, 0.7626735, 1780250.9240069, 0.2559082, 7.9727208), (0.4539774, 0.8325224, 761784.3584749, 0.2953798, 6.0342075) ] return baseline[turbine_index] diff --git a/tests/gauss_regression_test.py b/tests/gauss_regression_test.py index 2256c682e..3a1dc521a 100644 --- a/tests/gauss_regression_test.py +++ b/tests/gauss_regression_test.py @@ -39,7 +39,7 @@ def baseline(self, turbine_index): def yawed_baseline(self, turbine_index): baseline = [ - (0.4632706, 0.7626695, 1780851.3400887, 0.2559061, 7.9736330), + (0.4632733, 0.7626695, 1780861.5909742, 0.2559061, 7.9736330), (0.4519389, 0.8403914, 696267.1270400, 0.3002448, 5.8647976) ] return baseline[turbine_index] diff --git a/tests/jensen_jimenez_regression_test.py b/tests/jensen_jimenez_regression_test.py index ddc8d5200..7285360fb 100644 --- a/tests/jensen_jimenez_regression_test.py +++ b/tests/jensen_jimenez_regression_test.py @@ -39,7 +39,7 @@ def baseline(self, turbine_index): def yawed_baseline(self, turbine_index): baseline = [ - (0.4632706, 0.7626695, 1780851.3400887, 0.2559061, 7.9736330), + (0.4632733, 0.7626695, 1780861.5909742, 0.2559061, 7.9736330), (0.4554894, 0.8266861, 813067.4207660, 0.2918451, 6.1598540) ] return baseline[turbine_index] diff --git a/tests/multizone_jimenez_regression_test.py b/tests/multizone_jimenez_regression_test.py index 90b7f64c4..8ed3b11ca 100644 --- a/tests/multizone_jimenez_regression_test.py +++ b/tests/multizone_jimenez_regression_test.py @@ -39,7 +39,7 @@ def baseline(self, turbine_index): def yawed_baseline(self, turbine_index): baseline = [ - (0.4632706, 0.7626695, 1780851.3400887, 0.2559061, 7.9736330), + (0.4632733, 0.7626695, 1780861.5909742, 0.2559061, 7.9736330), (0.4420041, 0.8650277, 535742.2576472, 0.3163071, 5.4141570) ] return baseline[turbine_index]