From 3a09d596eb5f97b5cac57ffa0af514cddf31daaa Mon Sep 17 00:00:00 2001 From: Bart Doekemeijer Date: Fri, 4 Aug 2023 10:50:33 +0200 Subject: [PATCH 1/3] Add wind direction degree of freedom in heterogeneous inflow --- ...py => 16b_heterogeneity_multiple_ws_wd.py} | 27 ++++++------- examples/inputs/gch_heterogeneous_inflow.yaml | 8 ++-- floris/simulation/flow_field.py | 38 +++++++++++-------- 3 files changed, 41 insertions(+), 32 deletions(-) rename examples/{16b_heterogenaity_multiple_ws_wd.py => 16b_heterogeneity_multiple_ws_wd.py} (80%) diff --git a/examples/16b_heterogenaity_multiple_ws_wd.py b/examples/16b_heterogeneity_multiple_ws_wd.py similarity index 80% rename from examples/16b_heterogenaity_multiple_ws_wd.py rename to examples/16b_heterogeneity_multiple_ws_wd.py index 43ac6f7eb..f8f1422f3 100644 --- a/examples/16b_heterogenaity_multiple_ws_wd.py +++ b/examples/16b_heterogeneity_multiple_ws_wd.py @@ -29,7 +29,7 @@ # Define the speed ups of the heterogeneous inflow, and their locations. # For the 2-dimensional case, this requires x and y locations. # The speed ups are multipliers of the ambient wind speed. -speed_ups = [[2.0, 1.0, 2.0, 1.0]] +speed_ups = [[[2.0, 1.0, 2.0, 1.0]]] # Has the shape (n_wind_directions, n_wind_speeds, n_points) x_locs = [-300.0, -300.0, 2600.0, 2600.0] y_locs = [ -300.0, 300.0, -300.0, 300.0] @@ -58,19 +58,20 @@ print(f'T1: {turbine_powers[1]:.1f} kW') print() -# Since het maps are assigned for each wind direciton, it's allowable to change -# the number of wind speeds -fi.reinitialize(wind_speeds=[4, 8]) -fi.calculate_wake() -turbine_powers = np.round(fi.get_turbine_powers() / 1000.) -print('With wind speeds now set to 4 and 8 m/s') -print(f'T0: {turbine_powers[:, :, 0].flatten()} kW') -print(f'T1: {turbine_powers[:, :, 1].flatten()} kW') -print() - # To change the number of wind directions however it is necessary to make a matching # change to the dimensions of the het map -speed_multipliers = [[2.0, 1.0, 2.0, 1.0], [2.0, 1.0, 2.0, 1.0]] # Expand to two wind directions +speed_multipliers = [ + [ + [2.0, 1.0, 2.0, 1.0], # Wind direction 270, Wind speed 7.0, four locations (x,y) + [2.0, 1.0, 2.0, 1.0], # Wind direction 270, Wind speed 8.0, four locations (x,y) + [2.0, 1.0, 2.0, 1.0], # Wind direction 270, Wind speed 9.0, four locations (x,y) + ], + [ + [2.0, 1.0, 2.0, 1.0], # Wind direction 275, Wind speed 7.0, four locations (x,y) + [2.0, 1.0, 2.0, 1.0], # Wind direction 275, Wind speed 8.0, four locations (x,y) + [2.0, 1.0, 2.0, 1.0], # Wind direction 275, Wind speed 9.0, four locations (x,y) + ], +] heterogenous_inflow_config = { 'speed_multipliers': speed_multipliers, 'x': x_locs, @@ -78,7 +79,7 @@ } fi.reinitialize( wind_directions=[270.0, 275.0], - wind_speeds=[8.0], + wind_speeds=[7.0, 8.0, 9.0], heterogenous_inflow_config=heterogenous_inflow_config ) fi.calculate_wake() diff --git a/examples/inputs/gch_heterogeneous_inflow.yaml b/examples/inputs/gch_heterogeneous_inflow.yaml index d7cffa0d5..9e84f969d 100644 --- a/examples/inputs/gch_heterogeneous_inflow.yaml +++ b/examples/inputs/gch_heterogeneous_inflow.yaml @@ -29,10 +29,10 @@ flow_field: air_density: 1.225 heterogenous_inflow_config: speed_multipliers: - - - 2.0 - - 1.0 - - 2.0 - - 1.0 + - - - 2.0 + - 1.0 + - 2.0 + - 1.0 x: - -300. - -300. diff --git a/floris/simulation/flow_field.py b/floris/simulation/flow_field.py index a8dbf7393..cc9f78ad3 100644 --- a/floris/simulation/flow_field.py +++ b/floris/simulation/flow_field.py @@ -163,13 +163,13 @@ def initialize_velocity_field(self, grid: Grid) -> None: "fully cover the calculated flow field area." ) - if len(self.het_map[0].points[0]) == 2: + if len(self.het_map[0][0].points[0]) == 2: speed_ups = self.calculate_speed_ups( self.het_map, grid.x_sorted_inertial_frame, grid.y_sorted_inertial_frame ) - elif len(self.het_map[0].points[0]) == 3: + elif len(self.het_map[0][0].points[0]) == 3: speed_ups = self.calculate_speed_ups( self.het_map, grid.x_sorted_inertial_frame, @@ -240,21 +240,23 @@ def finalize(self, unsorted_indices): ) def calculate_speed_ups(self, het_map, x, y, z=None): + speed_ups = np.ones_like(x) + n_wind_directions = np.shape(x)[0] + n_wind_speeds = np.shape(x)[1] + if z is not None: # Calculate the 3-dimensional speed ups; squeeze is needed as the generator # adds an extra dimension - speed_ups = np.squeeze( - [het_map[i](x[i:i+1], y[i:i+1], z[i:i+1]) for i in range( len(het_map))], - axis=1, - ) + for wdii in range(n_wind_directions): + for wsii in range(n_wind_speeds): + speed_ups[wdii, wsii] = het_map[wdii][wsii](x[wdii, wsii], y[wdii, wsii], z[wdii, wsii]) else: # Calculate the 2-dimensional speed ups; squeeze is needed as the generator # adds an extra dimension - speed_ups = np.squeeze( - [het_map[i](x[i:i+1], y[i:i+1]) for i in range(len(het_map))], - axis=1, - ) + for wdii in range(n_wind_directions): + for wsii in range(n_wind_speeds): + speed_ups[wdii, wsii] = het_map[wdii][wsii](x[wdii, wsii], y[wdii, wsii]) return speed_ups @@ -275,7 +277,7 @@ def generate_heterogeneous_wind_map(self): - **y**: A list of y locations at which the speed up factors are defined. - **z** (optional): A list of z locations at which the speed up factors are defined. """ - speed_multipliers = self.heterogenous_inflow_config['speed_multipliers'] + all_multipliers = self.heterogenous_inflow_config['speed_multipliers'] x = self.heterogenous_inflow_config['x'] y = self.heterogenous_inflow_config['y'] z = self.heterogenous_inflow_config['z'] @@ -285,16 +287,22 @@ def generate_heterogeneous_wind_map(self): # Linear interpolation is used for points within the user-defined area of values, # while the freestream wind speed is used for points outside that region in_region = [ - LinearNDInterpolator(list(zip(x, y, z)), multiplier, fill_value=1.0) - for multiplier in speed_multipliers + [ + LinearNDInterpolator(list(zip(x, y, z)), multiplier, fill_value=1.0) + for multiplier in single_winddirection_multipliers + ] + for single_winddirection_multipliers in all_multipliers ] else: # Compute the 2-dimensional interpolants for each wind direction # Linear interpolation is used for points within the user-defined area of values, # while the freestream wind speed is used for points outside that region in_region = [ - LinearNDInterpolator(list(zip(x, y)), multiplier, fill_value=1.0) - for multiplier in speed_multipliers + [ + LinearNDInterpolator(list(zip(x, y)), multiplier, fill_value=1.0) + for multiplier in single_winddirection_multipliers + ] + for single_winddirection_multipliers in all_multipliers ] self.het_map = in_region From 664e0176c42eee319f06833c1ba440d2afc3be4b Mon Sep 17 00:00:00 2001 From: Bart Doekemeijer Date: Fri, 4 Aug 2023 11:15:00 +0200 Subject: [PATCH 2/3] Add a second check in het_map validator to check number of wind speeds --- floris/simulation/flow_field.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/floris/simulation/flow_field.py b/floris/simulation/flow_field.py index cc9f78ad3..2a8ffff96 100644 --- a/floris/simulation/flow_field.py +++ b/floris/simulation/flow_field.py @@ -108,6 +108,11 @@ def het_map_validator(self, instance: attrs.Attribute, value: list | None) -> No "The het_map's wind direction dimension not equal to number of wind directions." ) + if self.n_wind_speeds!= np.array(value).shape[1]: + raise ValueError( + "The het_map's wind speed dimension not equal to number of wind speeds." + ) + def __attrs_post_init__(self) -> None: if self.heterogenous_inflow_config is not None: From 22d1281f081e9560c268c8b77bd8f053cb161732 Mon Sep 17 00:00:00 2001 From: Bart Doekemeijer Date: Fri, 4 Aug 2023 12:16:17 +0200 Subject: [PATCH 3/3] Add linebreak to break up long line --- floris/simulation/flow_field.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/floris/simulation/flow_field.py b/floris/simulation/flow_field.py index 2a8ffff96..8aad7e7f9 100644 --- a/floris/simulation/flow_field.py +++ b/floris/simulation/flow_field.py @@ -254,7 +254,8 @@ def calculate_speed_ups(self, het_map, x, y, z=None): # adds an extra dimension for wdii in range(n_wind_directions): for wsii in range(n_wind_speeds): - speed_ups[wdii, wsii] = het_map[wdii][wsii](x[wdii, wsii], y[wdii, wsii], z[wdii, wsii]) + speed_ups[wdii, wsii] = \ + het_map[wdii][wsii](x[wdii, wsii], y[wdii, wsii], z[wdii, wsii]) else: # Calculate the 2-dimensional speed ups; squeeze is needed as the generator