From 5629669428c00f553ef6533da2b93de525ccb3a1 Mon Sep 17 00:00:00 2001 From: dhcho347 Date: Mon, 14 Nov 2022 17:09:47 +0900 Subject: [PATCH 1/8] enhancement: fix_farm_orientation for horizontal_plane Results plot with original layout (not rotate to west) --- examples/vis_03_horizontal_plane.txt | 71 ++++++++++++++++++++++++++++ floris/simulation/grid.py | 23 +++++++-- floris/tools/floris_interface.py | 11 ++++- floris/utilities.py | 9 +++- 4 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 examples/vis_03_horizontal_plane.txt diff --git a/examples/vis_03_horizontal_plane.txt b/examples/vis_03_horizontal_plane.txt new file mode 100644 index 000000000..589723253 --- /dev/null +++ b/examples/vis_03_horizontal_plane.txt @@ -0,0 +1,71 @@ +# Copyright 2021 NREL + +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +# See https://floris.readthedocs.io for documentation + +import matplotlib.pyplot as plt + +from floris.tools import FlorisInterface +from floris.tools.visualization import visualize_cut_plane +from floris.tools.visualization import plot_rotor_values + +#dh +import numpy as np + +fi = FlorisInterface("floris/examples/inputs/gch.yaml") # 3.2.1.2.1.1 + +# # Define 4 turbines +layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) +layout_y = np.array([800.0, 800.0, 800.0, 0.0]) +turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] +fi.reinitialize(layout_x=layout_x, layout_y=layout_y, turbine_type=turbine_type) + +# sweep_wind_directions +# just with yawangle +if 1 : # just with yaw angle text + # select wind directions and wind speed for horizontal plot + wd = [[i] for i in np.arange(0,360,90)]; #change : wind directions + ws = [8.0] + # yaw angles: Change the yaw angles and configure the plot differently + n_wd=fi.floris.flow_field.n_wind_directions; n_ws=fi.floris.flow_field.n_wind_speeds + n_wtg=fi.floris.farm.n_turbines + yaw_angles = np.zeros((1, 1, n_wtg)); + yaw_angles[:,:,:] = (0, 0, 15, -15) + + # ready for plot + n_col=2 #change : graph's column + fig, ax_list = plt.subplots( round(len(wd)/n_col+0.5), n_col, figsize=(16, 8)) + ax_list = ax_list.flatten() + + horizontal_plane =[]; res=200; + # get DFs (x,y,z, u,v,w) for horizontal plane + for i in range(len(wd)): + horizontal_plane.append(fi.calculate_horizontal_plane(wd=wd[i], ws=ws, height=90.0, yaw_angles=yaw_angles, x_resolution=res, y_resolution=res), ) + + # plot DFs + for i in range(len(wd)): + ax=ax_list[i]; + visualize_cut_plane(horizontal_plane[i], ax=ax, title="Wind direction "+str(wd[i])+"deg", color_bar=True); + + # text on WTGs + turbine_yaw = yaw_angles.flatten() + turbine_type= fi.floris.farm.turbine_type + + mytext = [f"yaw: {i:.1f}" for i in turbine_yaw] + if 1: mytext = [f"T{i:0d}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_wtg)] + for j in range(fi.floris.farm.n_turbines): + ax.text(fi.layout_x[j], fi.layout_y[j], mytext[j], color='springgreen') + + # text on Farm + ax.text(min(horizontal_plane[i].df.x1), min(horizontal_plane[i].df.x2), f' WD: {wd[i]}, WS: {ws[0]} \n',color='white') + + plt.tight_layout(); plt.savefig("fix_orient.png"); plt.show(); \ No newline at end of file diff --git a/floris/simulation/grid.py b/floris/simulation/grid.py index 9f8fdc3ed..91d51e366 100644 --- a/floris/simulation/grid.py +++ b/floris/simulation/grid.py @@ -354,17 +354,30 @@ def set_grid(self) -> None: First, sort the turbines so that we know the bounds in the correct orientation. Then, create the grid based on this wind-from-left orientation """ + + fix_orientation = True #dh. TODO add variable in class + if fix_orientation : wd = np.ones_like(self.wind_directions)*270 #dh. do not rotate + else : wd = self.wind_directions #dh. do rotate + # These are the rotated coordinates of the wind turbines based on the wind direction - x, y, z = rotate_coordinates_rel_west(self.wind_directions, self.turbine_coordinates_array) + x, y, z = rotate_coordinates_rel_west(wd, self.turbine_coordinates_array) max_diameter = np.max(self.reference_turbine_diameter) if self.normal_vector == "z": # Rules of thumb for horizontal plane if self.x1_bounds is None: - self.x1_bounds = (np.min(x) - 2 * max_diameter, np.max(x) + 10 * max_diameter) + # dh. broaden the flowfiled_planar + if fix_orientation : + self.x1_bounds = (np.min(x) - 10 * max_diameter, np.max(x) + 10 * max_diameter) + else : + self.x1_bounds = (np.min(x) - 2 * max_diameter, np.max(x) + 10 * max_diameter) if self.x2_bounds is None: - self.x2_bounds = (np.min(y) - 2 * max_diameter, np.max(y) + 2 * max_diameter) + # dh + if fix_orientation : + self.x2_bounds = (np.min(y) - 10 * max_diameter, np.max(y) + 10 * max_diameter) + else : + self.x2_bounds = (np.min(y) - 2 * max_diameter, np.max(y) + 2 * max_diameter) # TODO figure out proper z spacing for GCH, currently set to +/- 10.0 x_points, y_points, z_points = np.meshgrid( @@ -378,6 +391,10 @@ def set_grid(self) -> None: indexing="ij" ) + #dh. rotating meshgrid to west + if fix_orientation : + x_points, y_points, z_points = rotate_coordinates_rel_west(self.wind_directions, (x_points, y_points, z_points), inv_rot=False ) + self.x_sorted = x_points[None, None, :, :, :] self.y_sorted = y_points[None, None, :, :, :] self.z_sorted = z_points[None, None, :, :, :] diff --git a/floris/tools/floris_interface.py b/floris/tools/floris_interface.py index 6f1e84099..3130bc579 100644 --- a/floris/tools/floris_interface.py +++ b/floris/tools/floris_interface.py @@ -31,6 +31,8 @@ from floris.tools.cut_plane import CutPlane from floris.type_dec import NDArrayFloat +#dh +from floris.utilities import rotate_coordinates_rel_west class FlorisInterface(LoggerBase): """ @@ -297,6 +299,13 @@ def get_plane_of_points( v_flat = self.floris.flow_field.v_sorted[0, 0].flatten() w_flat = self.floris.flow_field.w_sorted[0, 0].flatten() + #dh. inverse rotation of cal. results (x,y,z) + if 1 : + x_flat2, y_flat2, z_flat2 = rotate_coordinates_rel_west(self.floris.flow_field.wind_directions, (x_flat, y_flat, z_flat), inv_rot=True ) + x_flat=x_flat2[0,0].flatten(); + y_flat=y_flat2[0,0].flatten(); + z_flat=z_flat2[0,0].flatten(); + # Create a df of these if normal_vector == "z": df = pd.DataFrame( @@ -342,7 +351,7 @@ def get_plane_of_points( df = df.drop_duplicates() # Sort values of df to make sure plotting is acceptable - df = df.sort_values(["x2", "x1"]).reset_index(drop=True) + #df = df.sort_values(["x2", "x1"]).reset_index(drop=True) #dh. deactivate return df diff --git a/floris/utilities.py b/floris/utilities.py index 276bf26b6..a08300768 100644 --- a/floris/utilities.py +++ b/floris/utilities.py @@ -195,13 +195,18 @@ def wind_delta(wind_directions): return ((wind_directions - 270) % 360 + 360) % 360 -def rotate_coordinates_rel_west(wind_directions, coordinates): +def rotate_coordinates_rel_west(wind_directions, coordinates, inv_rot=False): #dh. add inv_rot # Calculate the difference in given wind direction from 270 / West wind_deviation_from_west = wind_delta(wind_directions) wind_deviation_from_west = np.reshape(wind_deviation_from_west, (len(wind_directions), 1, 1)) + if inv_rot : wind_deviation_from_west = -wind_deviation_from_west #dh. for inverse rotation + # Construct the arrays storing the turbine locations - x_coordinates, y_coordinates, z_coordinates = coordinates.T + if isinstance(coordinates, (np.ndarray, np.generic) ) : + x_coordinates, y_coordinates, z_coordinates = coordinates.T + else : + x_coordinates, y_coordinates, z_coordinates = coordinates #dh. to handle additional input type (mesh grid) # Find center of rotation - this is the center of box bounding all of the turbines x_center_of_rotation = (np.min(x_coordinates) + np.max(x_coordinates)) / 2 From a77f7c5c77e7212e485d6b11162e5ba94d69ae4d Mon Sep 17 00:00:00 2001 From: dhcho347 Date: Mon, 14 Nov 2022 19:34:18 +0900 Subject: [PATCH 2/8] enhencemnet: horizontal plot with fi horizontal cut plane with north up farm layout infor with yaw, avg speed, Ct, power & Farm power --- .../vis_03_1_horizontal_plane_with fi info.py | 90 +++++++++++++++++++ ...l_plane.txt => vis_03_horizontal_plane.py} | 0 floris/tools/visualization.py | 4 + 3 files changed, 94 insertions(+) create mode 100644 examples/vis_03_1_horizontal_plane_with fi info.py rename examples/{vis_03_horizontal_plane.txt => vis_03_horizontal_plane.py} (100%) diff --git a/examples/vis_03_1_horizontal_plane_with fi info.py b/examples/vis_03_1_horizontal_plane_with fi info.py new file mode 100644 index 000000000..10e35f398 --- /dev/null +++ b/examples/vis_03_1_horizontal_plane_with fi info.py @@ -0,0 +1,90 @@ +# Copyright 2021 NREL + +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +# See https://floris.readthedocs.io for documentation + +import matplotlib.pyplot as plt + +from floris.tools import FlorisInterface +from floris.tools.visualization import visualize_cut_plane +from floris.tools.visualization import plot_rotor_values + +#dh +import numpy as np +from floris.tools.visualization import plot_turbines_with_fi + +fi = FlorisInterface("floris/examples/inputs/gch.yaml") + +# # Define 4 turbines +layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) +layout_y = np.array([800.0, 800.0, 800.0, 0.0]) +if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs +if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs +fi.reinitialize(layout_x=layout_x, layout_y=layout_y, turbine_type=turbine_type) + +# plot with yawangle, fi info +if 1 : # dh. 화면에 yaw, fi 정보도 출력 + # wind directions and speeds for plot + wd = [[i] for i in np.arange(45,360,90)]; + ws = [8.0]; + if 0: ws = [[i] for i in np.arange(3,25,1.0)]; + + # yaw angles: Change the yaw angles and configure the plot differently + n_wd=fi.floris.flow_field.n_wind_directions; n_ws=fi.floris.flow_field.n_wind_speeds + n_wtg=fi.floris.farm.n_turbines + yaw_angles = np.zeros((1, 1, n_wtg)); + yaw_angles[:,:,:] = (0, 0, 15, -15) + + # ready for plot + n_col=2 + fig, ax_list = plt.subplots( round(len(wd)/n_col+0.5), n_col, figsize=(16, 8)) + ax_list = ax_list.flatten() + res=200; + for i in range(len(wd)): + # fi update for text on WTGs. + # at the end of fi.calculate_horizontal_plane, restoring fi to previous, + # we can't use those results for texting + fi.reinitialize( wind_speeds=ws, wind_directions=wd[i] ) # class fi + fi.floris.farm.yaw_angles=yaw_angles; # yaw angles + + # getting df (x,y,z, u,v,w) for planar flow field + horizontal_plane=fi.calculate_horizontal_plane(wd=wd[i], ws=ws, height=90.0, yaw_angles=yaw_angles, x_resolution=res, y_resolution=res) + + # plot + ax=ax_list[i]; + visualize_cut_plane(horizontal_plane, ax=ax, title="Wind direction "+str(wd[i])+"deg", color_bar=True); + plot_turbines_with_fi(ax=ax_list[i],fi=fi) # , wd=wd[i] + FarmP = fi.get_farm_power()/1000 # 이거?? + plt.xlabel(f'{FarmP[0,0]:.3f}'+' KW') + + #dh. text on WTGs + # fi update with reinitialize + turbine_yaw = fi.floris.farm.yaw_angles + turbine_type= fi.floris.farm.turbine_type + turbine_avg_vel=fi.get_turbine_average_velocities() + turbine_powers = fi.get_turbine_powers()/1000. + turbine_ais =fi.get_turbine_ais() + turbine_Cts = fi.get_turbine_Cts() + + mytext = [f"yaw: {i:.1f}" for i in turbine_yaw[0,0]] + if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_wtg)] + if 1: mytext = [f"{mytext[i]} \n Vel: {turbine_avg_vel[0,0,i]:.1f}" for i in range(n_wtg)] + if 1: mytext = [f"{mytext[i]} \n Pow: {turbine_powers[0,0,i]:.1f}" for i in range(n_wtg)] + if 0: mytext = [f"{mytext[i]} \n ai: {turbine_ais[0,0,i]:.1f}" for i in range(n_wtg)] + if 1: mytext = [f"{mytext[i]} \n ct: {turbine_Cts[0,0,i]:.1f}" for i in range(n_wtg)] + for j in range(fi.floris.farm.n_turbines): + ax.text(fi.layout_x[j], fi.layout_y[j], mytext[j], color='springgreen') + + #dh. text on Farm + ax.text(min(horizontal_plane.df.x1), min(horizontal_plane.df.x2), f' FarmPower: {FarmP[0,0]:.2f}'+f' KW \n WD: {wd[i]}, WS: {ws[0]} \n',color='white') + + plt.tight_layout(); plt.savefig("abc.png"); plt.show(); \ No newline at end of file diff --git a/examples/vis_03_horizontal_plane.txt b/examples/vis_03_horizontal_plane.py similarity index 100% rename from examples/vis_03_horizontal_plane.txt rename to examples/vis_03_horizontal_plane.py diff --git a/floris/tools/visualization.py b/floris/tools/visualization.py index 178ad17e5..61116a5c3 100644 --- a/floris/tools/visualization.py +++ b/floris/tools/visualization.py @@ -53,6 +53,10 @@ def plot_turbines( color (str): Pyplot color option to plot the turbines. wind_direction (float): Wind direction (rotates farm) """ + + # Correct for the wind direction + yaw_angles = np.array(yaw_angles) - wind_direction - 270 #dh. activate + if color is None: color = "k" From e93dfc52318f4cf91f08bc1188bec53c0d40867f Mon Sep 17 00:00:00 2001 From: dhcho347 Date: Mon, 14 Nov 2022 19:45:11 +0900 Subject: [PATCH 3/8] minor chg --- examples/vis_03_horizontal_plane.py | 3 ++- floris/tools/floris_interface.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/vis_03_horizontal_plane.py b/examples/vis_03_horizontal_plane.py index 589723253..80d19eb16 100644 --- a/examples/vis_03_horizontal_plane.py +++ b/examples/vis_03_horizontal_plane.py @@ -26,7 +26,8 @@ # # Define 4 turbines layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) layout_y = np.array([800.0, 800.0, 800.0, 0.0]) -turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] +if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs +if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs fi.reinitialize(layout_x=layout_x, layout_y=layout_y, turbine_type=turbine_type) # sweep_wind_directions diff --git a/floris/tools/floris_interface.py b/floris/tools/floris_interface.py index 3130bc579..097476b3e 100644 --- a/floris/tools/floris_interface.py +++ b/floris/tools/floris_interface.py @@ -300,7 +300,8 @@ def get_plane_of_points( w_flat = self.floris.flow_field.w_sorted[0, 0].flatten() #dh. inverse rotation of cal. results (x,y,z) - if 1 : + fix_orientation = True #dh. TODO add variable in class + if fix_orientation : x_flat2, y_flat2, z_flat2 = rotate_coordinates_rel_west(self.floris.flow_field.wind_directions, (x_flat, y_flat, z_flat), inv_rot=True ) x_flat=x_flat2[0,0].flatten(); y_flat=y_flat2[0,0].flatten(); From 9160b6ddb258205f1b20786c117743919927f4ef Mon Sep 17 00:00:00 2001 From: dhcho347 Date: Tue, 15 Nov 2022 16:19:55 +0900 Subject: [PATCH 4/8] Add visual check of input example for visual check chg : plot_turbine_with_fi --- examples/vis_01_visChk_Input.py | 130 ++++++++++++++++++ .../vis_03_1_horizontal_plane_with fi info.py | 10 +- examples/vis_03_horizontal_plane.py | 6 +- floris/tools/visualization.py | 10 +- 4 files changed, 147 insertions(+), 9 deletions(-) create mode 100644 examples/vis_01_visChk_Input.py diff --git a/examples/vis_01_visChk_Input.py b/examples/vis_01_visChk_Input.py new file mode 100644 index 000000000..14fcae33d --- /dev/null +++ b/examples/vis_01_visChk_Input.py @@ -0,0 +1,130 @@ +# Copyright 2021 NREL + +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +# See https://floris.readthedocs.io for documentation + +import matplotlib.pyplot as plt + +from floris.tools import FlorisInterface +from floris.tools.visualization import visualize_cut_plane +from floris.tools.visualization import plot_rotor_values + +#dh +import numpy as np +from floris.tools.visualization import plot_turbines_with_fi +from floris.utilities import rotate_coordinates_rel_west +import math #dh. for drawing swept area + +fi = FlorisInterface("floris/examples/inputs/gch.yaml") +flow_field=fi.floris.flow_field +farm=fi.floris.farm +grid=fi.floris.grid +n_WTG=farm.n_turbines; +wd = flow_field.wind_directions +ws = flow_field.wind_speeds + +# check : Farm layout and flowfield info +if 1 : + fig, ax = plt.subplots(1, 1) + plot_turbines_with_fi(ax=ax,fi=fi) + + # text on WTGs + turbine_type= farm.turbine_type_names_sorted + mytext = [f"yaw: {i:.1f}" for i in farm.yaw_angles[0,0]] # after FI, yaw_angles are set 0 + if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_WTG)] + for j in range(n_WTG): + ax.text(fi.layout_x[j], fi.layout_y[j], mytext[j], color='b') + + # text on Farm + mytext = [f" WD: {wd}, WS: {ws}"] # height + if 1: mytext = [f"{mytext} \n TI: {flow_field.turbulence_intensity}, shear: {flow_field.wind_shear}, veer: {flow_field.wind_veer}"] + ax.text(min(fi.layout_x), min(fi.layout_x), mytext, color='black') + + #plt.tight_layout(); plt.show() + +# check : Turbine Grid for 1 wind direction rel to west +if 1 : + fig, ax = plt.subplots(1, 1) + ax = fig.add_subplot(projection='3d') + + xWTG, y_WTG, z_WTG=rotate_coordinates_rel_west(np.array([wd[0]]), (grid.x_sorted[0,0], grid.y_sorted[0,0], grid.z_sorted[0,0]), inv_rot=True) + ax.scatter(xWTG,y_WTG,z_WTG) # 작동 + + # text on WTGs + turbine_type= farm.turbine_type_names_sorted + hh=farm.hub_heights; RD=farm.rotor_diameters + mytext = [f"yaw: {i:.1f}" for i in farm.yaw_angles[0,0]] # after FI, yaw_angles are set 0 + if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_WTG)] + if 1: mytext = [f"{mytext[i]} \n HH: {hh[i]}" for i in range(n_WTG)] + if 1: mytext = [f"{mytext[i]} \n RD: {RD[i]}" for i in range(n_WTG)] + for j in range(n_WTG): + ax.text(fi.layout_x[j], fi.layout_y[j], farm.hub_heights[j], mytext[j], color='b') + + +if 1: # change some information + # Define 4 turbines + layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) + layout_y = np.array([800.0, 800.0, 800.0, 0.0]) + if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs + if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs + fi.reinitialize(layout_x=layout_x, layout_y=layout_y, turbine_type=turbine_type) + + flow_field=fi.floris.flow_field; farm=fi.floris.farm; grid=fi.floris.grid + n_WTG=farm.n_turbines + wd = flow_field.wind_directions + ws = flow_field.wind_speeds + + # set yaw angles + n_WTG = 4 + yaw_angles = np.zeros((1, 1, n_WTG)) + yaw_angles[:,:,:] = (0, 0, 15, -15) + fi.floris.farm.yaw_angles=yaw_angles; # update yaw in fi class + +# check : Farm layout and flowfield info +if 1 : + fig, ax = plt.subplots(1, 1) + plot_turbines_with_fi(ax=ax,fi=fi) + + # text on WTGs + turbine_type= farm.turbine_type_names_sorted + mytext = [f"yaw: {i:.1f}" for i in farm.yaw_angles[0,0]] # after FI, yaw_angles are set 0 + if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_WTG)] + for j in range(n_WTG): + ax.text(fi.layout_x[j], fi.layout_y[j], mytext[j], color='b') + + # text on Farm + mytext = [f" WD: {wd}, WS: {ws}"] # height + if 1: mytext = [f"{mytext} \n TI: {flow_field.turbulence_intensity}, shear: {flow_field.wind_shear}, veer: {flow_field.wind_veer}"] + ax.text(min(fi.layout_x), min(fi.layout_x), mytext, color='black') + + #plt.tight_layout(); plt.show() + +# check : Turbine Grid for 1 wind direction rel to west +if 1 : + fig, ax = plt.subplots(1, 1) + ax = fig.add_subplot(projection='3d') + + xWTG, y_WTG, z_WTG=rotate_coordinates_rel_west(np.array([wd[0]]), (grid.x_sorted[0,0], grid.y_sorted[0,0], grid.z_sorted[0,0]), inv_rot=True) + ax.scatter(xWTG,y_WTG,z_WTG) # 작동 + + # text on WTGs + turbine_type= farm.turbine_type_names_sorted + hh=farm.hub_heights; RD=farm.rotor_diameters + mytext = [f"yaw: {i:.1f}" for i in farm.yaw_angles[0,0]] # after FI, yaw_angles are set 0 + if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_WTG)] + if 1: mytext = [f"{mytext[i]} \n HH: {hh[i]}" for i in range(n_WTG)] + if 1: mytext = [f"{mytext[i]} \n RD: {RD[i]}" for i in range(n_WTG)] + for j in range(n_WTG): + ax.text(fi.layout_x[j], fi.layout_y[j], farm.hub_heights[j], mytext[j], color='b') + + +plt.tight_layout(); plt.show() \ No newline at end of file diff --git a/examples/vis_03_1_horizontal_plane_with fi info.py b/examples/vis_03_1_horizontal_plane_with fi info.py index 10e35f398..6e970d5bb 100644 --- a/examples/vis_03_1_horizontal_plane_with fi info.py +++ b/examples/vis_03_1_horizontal_plane_with fi info.py @@ -27,8 +27,8 @@ # # Define 4 turbines layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) layout_y = np.array([800.0, 800.0, 800.0, 0.0]) -if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs -if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs +if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs +if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs fi.reinitialize(layout_x=layout_x, layout_y=layout_y, turbine_type=turbine_type) # plot with yawangle, fi info @@ -53,8 +53,8 @@ # fi update for text on WTGs. # at the end of fi.calculate_horizontal_plane, restoring fi to previous, # we can't use those results for texting - fi.reinitialize( wind_speeds=ws, wind_directions=wd[i] ) # class fi - fi.floris.farm.yaw_angles=yaw_angles; # yaw angles + fi.reinitialize( wind_speeds=ws, wind_directions=wd[i] ) # update class fi, loosing yaw angles + fi.floris.farm.yaw_angles=yaw_angles; # set again yaw angles into fi # getting df (x,y,z, u,v,w) for planar flow field horizontal_plane=fi.calculate_horizontal_plane(wd=wd[i], ws=ws, height=90.0, yaw_angles=yaw_angles, x_resolution=res, y_resolution=res) @@ -69,7 +69,7 @@ #dh. text on WTGs # fi update with reinitialize turbine_yaw = fi.floris.farm.yaw_angles - turbine_type= fi.floris.farm.turbine_type + turbine_type= fi.floris.farm.turbine_type_names_sorted turbine_avg_vel=fi.get_turbine_average_velocities() turbine_powers = fi.get_turbine_powers()/1000. turbine_ais =fi.get_turbine_ais() diff --git a/examples/vis_03_horizontal_plane.py b/examples/vis_03_horizontal_plane.py index 80d19eb16..115a23c57 100644 --- a/examples/vis_03_horizontal_plane.py +++ b/examples/vis_03_horizontal_plane.py @@ -26,8 +26,8 @@ # # Define 4 turbines layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) layout_y = np.array([800.0, 800.0, 800.0, 0.0]) -if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs -if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs +if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs +if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs fi.reinitialize(layout_x=layout_x, layout_y=layout_y, turbine_type=turbine_type) # sweep_wind_directions @@ -59,7 +59,7 @@ # text on WTGs turbine_yaw = yaw_angles.flatten() - turbine_type= fi.floris.farm.turbine_type + turbine_type= fi.floris.farm.turbine_type_names_sorted mytext = [f"yaw: {i:.1f}" for i in turbine_yaw] if 1: mytext = [f"T{i:0d}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_wtg)] diff --git a/floris/tools/visualization.py b/floris/tools/visualization.py index 61116a5c3..b54a525f9 100644 --- a/floris/tools/visualization.py +++ b/floris/tools/visualization.py @@ -90,12 +90,20 @@ def plot_turbines_with_fi(fi: FlorisInterface, ax=None, color=None, yaw_angles=N fig, ax = plt.subplots() if yaw_angles is None: yaw_angles = fi.floris.farm.yaw_angles + + #dh. after cal_wake. wind_directions shape has changed. + try: + np.shape(fi.floris.farm.rotor_diameters)[1] + rd=fi.floris.farm.rotor_diameters[0,0] # after calculate_wake with wd or ws is over 2 + except: + rd=fi.floris.farm.rotor_diameters # after FI, reinitialize, etc... + plot_turbines( ax, fi.layout_x, fi.layout_y, yaw_angles[0, 0], - fi.floris.farm.rotor_diameters[0, 0], + rd, #dh. change color=color, wind_direction=fi.floris.flow_field.wind_directions[0], ) From a1d63fb16c4d9e632e0a3053c51de5a0dd44a899 Mon Sep 17 00:00:00 2001 From: dhcho347 Date: Tue, 15 Nov 2022 21:24:33 +0900 Subject: [PATCH 5/8] ex: visual check for input data plot farm layout with info plot 3d for turbine grid with rotor swept circle plot flowfieldplanar grid --- examples/vis_01_visChk_Input.py | 94 +++++++++++++++++-- .../vis_03_1_horizontal_plane_with fi info.py | 2 +- floris/tools/visualization.py | 2 +- 3 files changed, 86 insertions(+), 12 deletions(-) diff --git a/examples/vis_01_visChk_Input.py b/examples/vis_01_visChk_Input.py index 14fcae33d..e80d82b84 100644 --- a/examples/vis_01_visChk_Input.py +++ b/examples/vis_01_visChk_Input.py @@ -28,9 +28,11 @@ flow_field=fi.floris.flow_field farm=fi.floris.farm grid=fi.floris.grid + n_WTG=farm.n_turbines; wd = flow_field.wind_directions ws = flow_field.wind_speeds +RD=farm.rotor_diameters # check : Farm layout and flowfield info if 1 : @@ -48,7 +50,7 @@ mytext = [f" WD: {wd}, WS: {ws}"] # height if 1: mytext = [f"{mytext} \n TI: {flow_field.turbulence_intensity}, shear: {flow_field.wind_shear}, veer: {flow_field.wind_veer}"] ax.text(min(fi.layout_x), min(fi.layout_x), mytext, color='black') - + ax.set_title('Farm layout ') #plt.tight_layout(); plt.show() # check : Turbine Grid for 1 wind direction rel to west @@ -59,6 +61,20 @@ xWTG, y_WTG, z_WTG=rotate_coordinates_rel_west(np.array([wd[0]]), (grid.x_sorted[0,0], grid.y_sorted[0,0], grid.z_sorted[0,0]), inv_rot=True) ax.scatter(xWTG,y_WTG,z_WTG) # 작동 + # draw rotor swept Area + xcoord=np.mean(grid.x_sorted[:, :], axis=(3, 4))[0,0] + ycoord=np.mean(grid.y_sorted[:, :], axis=(3, 4))[0,0] + zcoord=np.mean(grid.z_sorted[:, :], axis=(3, 4))[0,0] + for i in range(n_WTG): + x=[]; y=[]; z=[] + for t in range(360): # on x plane with (y,z) at rot_west condition + x.append(xcoord[i]+0*RD[i]) # wind direction + y.append(ycoord[i]+math.sin(math.radians(t))*RD[i]/2) # + z.append(zcoord[i]+math.cos(math.radians(t))*RD[i]/2) # hub heights + x, y, z=rotate_coordinates_rel_west(np.array([wd[0]]), (x, y, z), inv_rot=True) + ax.plot(x[0,0],y[0,0],z[0,0]) + ax.set_title('Turbine Grid with rotor swept area') + # text on WTGs turbine_type= farm.turbine_type_names_sorted hh=farm.hub_heights; RD=farm.rotor_diameters @@ -70,18 +86,29 @@ ax.text(fi.layout_x[j], fi.layout_y[j], farm.hub_heights[j], mytext[j], color='b') -if 1: # change some information +# change some information +if 1: # Define 4 turbines layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) layout_y = np.array([800.0, 800.0, 800.0, 0.0]) if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs - fi.reinitialize(layout_x=layout_x, layout_y=layout_y, turbine_type=turbine_type) + solver_settings = { + "type": "turbine_grid", #turbine_grid | flow_field_planar_grid + "turbine_grid_points": 10 + } + fi.reinitialize(layout_x=layout_x, layout_y=layout_y, + turbine_type=turbine_type, + solver_settings=solver_settings) - flow_field=fi.floris.flow_field; farm=fi.floris.farm; grid=fi.floris.grid - n_WTG=farm.n_turbines + flow_field=fi.floris.flow_field + farm=fi.floris.farm + grid=fi.floris.grid + + n_WTG=farm.n_turbines; wd = flow_field.wind_directions ws = flow_field.wind_speeds + RD=farm.rotor_diameters_sorted[0,0] # set yaw angles n_WTG = 4 @@ -100,12 +127,12 @@ if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_WTG)] for j in range(n_WTG): ax.text(fi.layout_x[j], fi.layout_y[j], mytext[j], color='b') - + # text on Farm mytext = [f" WD: {wd}, WS: {ws}"] # height if 1: mytext = [f"{mytext} \n TI: {flow_field.turbulence_intensity}, shear: {flow_field.wind_shear}, veer: {flow_field.wind_veer}"] ax.text(min(fi.layout_x), min(fi.layout_x), mytext, color='black') - + ax.set_title('Farm layout: 2nd') #plt.tight_layout(); plt.show() # check : Turbine Grid for 1 wind direction rel to west @@ -116,6 +143,20 @@ xWTG, y_WTG, z_WTG=rotate_coordinates_rel_west(np.array([wd[0]]), (grid.x_sorted[0,0], grid.y_sorted[0,0], grid.z_sorted[0,0]), inv_rot=True) ax.scatter(xWTG,y_WTG,z_WTG) # 작동 + # draw rotor swept Area + xcoord=np.mean(grid.x_sorted[:, :], axis=(3, 4))[0,0] + ycoord=np.mean(grid.y_sorted[:, :], axis=(3, 4))[0,0] + zcoord=np.mean(grid.z_sorted[:, :], axis=(3, 4))[0,0] + for i in range(n_WTG): + x=[]; y=[]; z=[] + for t in range(360): # on x plane with (y,z) at rot_west condition + x.append(xcoord[i]+0*RD[i]) # wind direction + y.append(ycoord[i]+math.sin(math.radians(t))*RD[i]/2) # + z.append(zcoord[i]+math.cos(math.radians(t))*RD[i]/2) # hub heights + x, y, z=rotate_coordinates_rel_west(np.array([wd[0]]), (x, y, z), inv_rot=True) + ax.plot(x[0,0],y[0,0],z[0,0]) + ax.set_title('Turbine Grid with rotor swept area: 2nd') + # text on WTGs turbine_type= farm.turbine_type_names_sorted hh=farm.hub_heights; RD=farm.rotor_diameters @@ -125,6 +166,39 @@ if 1: mytext = [f"{mytext[i]} \n RD: {RD[i]}" for i in range(n_WTG)] for j in range(n_WTG): ax.text(fi.layout_x[j], fi.layout_y[j], farm.hub_heights[j], mytext[j], color='b') - - -plt.tight_layout(); plt.show() \ No newline at end of file + + +# check for flow_field_planar_grid +if 1: # Set the solver to a flow field planar grid + solver_settings = { + "type": "flow_field_planar_grid", + "normal_vector": "z", + "planar_coordinate": flow_field.reference_wind_height, + "flow_field_grid_points": [20, 20], + "flow_field_bounds": [None, None], + } + fi.reinitialize(wind_directions=wd, wind_speeds=ws, solver_settings=solver_settings) + + flow_field=fi.floris.flow_field + farm=fi.floris.farm + grid=fi.floris.grid + + n_WTG=farm.n_turbines; + wd = flow_field.wind_directions + ws = flow_field.wind_speeds; + + # set yaw angles + n_WTG = 4 + yaw_angles = np.zeros((1, 1, n_WTG)) + yaw_angles[:,:,:] = (0, 0, 15, -15) + fi.floris.farm.yaw_angles=yaw_angles; # update yaw in fi class + +if 1 : #plot grid + fig, ax = plt.subplots(1, 1) + ax = fig.add_subplot(projection='3d') + xWTG, y_WTG, z_WTG=rotate_coordinates_rel_west(np.array([wd[0]]), (grid.x_sorted[0,0], grid.y_sorted[0,0], grid.z_sorted[0,0]), inv_rot=True) + ax.scatter(xWTG,y_WTG,z_WTG) # 작동 + ax.set_zlim(0, 150) + ax.set_title('flowfieldplanar Grid with rotor swept area') + +plt.tight_layout(); plt.show() diff --git a/examples/vis_03_1_horizontal_plane_with fi info.py b/examples/vis_03_1_horizontal_plane_with fi info.py index 6e970d5bb..1cc01539f 100644 --- a/examples/vis_03_1_horizontal_plane_with fi info.py +++ b/examples/vis_03_1_horizontal_plane_with fi info.py @@ -41,7 +41,7 @@ # yaw angles: Change the yaw angles and configure the plot differently n_wd=fi.floris.flow_field.n_wind_directions; n_ws=fi.floris.flow_field.n_wind_speeds n_wtg=fi.floris.farm.n_turbines - yaw_angles = np.zeros((1, 1, n_wtg)); + yaw_angles = np.zeros((1, 1, n_wtg)) yaw_angles[:,:,:] = (0, 0, 15, -15) # ready for plot diff --git a/floris/tools/visualization.py b/floris/tools/visualization.py index b54a525f9..1e1503b9e 100644 --- a/floris/tools/visualization.py +++ b/floris/tools/visualization.py @@ -91,7 +91,7 @@ def plot_turbines_with_fi(fi: FlorisInterface, ax=None, color=None, yaw_angles=N if yaw_angles is None: yaw_angles = fi.floris.farm.yaw_angles - #dh. after cal_wake. wind_directions shape has changed. + #dh. after cal_wake. rotor_diameters shape has changed. try: np.shape(fi.floris.farm.rotor_diameters)[1] rd=fi.floris.farm.rotor_diameters[0,0] # after calculate_wake with wd or ws is over 2 From 913577cfe2d3f8c27d16ccc5bfc57309395c30aa Mon Sep 17 00:00:00 2001 From: dhcho347 Date: Wed, 16 Nov 2022 04:42:20 +0900 Subject: [PATCH 6/8] Resolve conflicts during pull request update visualization.py from develop branch --- floris/tools/visualization.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/floris/tools/visualization.py b/floris/tools/visualization.py index 1e1503b9e..3dd8adb8c 100644 --- a/floris/tools/visualization.py +++ b/floris/tools/visualization.py @@ -53,13 +53,12 @@ def plot_turbines( color (str): Pyplot color option to plot the turbines. wind_direction (float): Wind direction (rotates farm) """ - - # Correct for the wind direction - yaw_angles = np.array(yaw_angles) - wind_direction - 270 #dh. activate - if color is None: color = "k" + fix_orientation=1 #dh. how to + if fix_orientation : wind_direction = np.ones_like(wind_direction)*270 #dh + coordinates_array = np.array([[x, y, 0.0] for x, y in list(zip(layout_x, layout_y))]) layout_x, layout_y, _ = rotate_coordinates_rel_west( np.array([wind_direction]), @@ -95,7 +94,7 @@ def plot_turbines_with_fi(fi: FlorisInterface, ax=None, color=None, yaw_angles=N try: np.shape(fi.floris.farm.rotor_diameters)[1] rd=fi.floris.farm.rotor_diameters[0,0] # after calculate_wake with wd or ws is over 2 - except: + except: rd=fi.floris.farm.rotor_diameters # after FI, reinitialize, etc... plot_turbines( @@ -103,7 +102,7 @@ def plot_turbines_with_fi(fi: FlorisInterface, ax=None, color=None, yaw_angles=N fi.layout_x, fi.layout_y, yaw_angles[0, 0], - rd, #dh. change + rotor_diameters=rd, #dh color=color, wind_direction=fi.floris.flow_field.wind_directions[0], ) From 7eadaf885986a1443cf7bdb8da66207b82d32472 Mon Sep 17 00:00:00 2001 From: Rafael M Mudafort Date: Tue, 7 Feb 2023 15:25:55 -0700 Subject: [PATCH 7/8] Fix example input paths and floris.tools API --- examples/vis_01_visChk_Input.py | 2 +- examples/vis_03_1_horizontal_plane_with fi info.py | 7 +++---- examples/vis_03_horizontal_plane.py | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/examples/vis_01_visChk_Input.py b/examples/vis_01_visChk_Input.py index e80d82b84..37c11476a 100644 --- a/examples/vis_01_visChk_Input.py +++ b/examples/vis_01_visChk_Input.py @@ -24,7 +24,7 @@ from floris.utilities import rotate_coordinates_rel_west import math #dh. for drawing swept area -fi = FlorisInterface("floris/examples/inputs/gch.yaml") +fi = FlorisInterface("inputs/gch.yaml") flow_field=fi.floris.flow_field farm=fi.floris.farm grid=fi.floris.grid diff --git a/examples/vis_03_1_horizontal_plane_with fi info.py b/examples/vis_03_1_horizontal_plane_with fi info.py index 1cc01539f..887fc35e8 100644 --- a/examples/vis_03_1_horizontal_plane_with fi info.py +++ b/examples/vis_03_1_horizontal_plane_with fi info.py @@ -22,7 +22,7 @@ import numpy as np from floris.tools.visualization import plot_turbines_with_fi -fi = FlorisInterface("floris/examples/inputs/gch.yaml") +fi = FlorisInterface("inputs/gch.yaml") # # Define 4 turbines layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) @@ -70,15 +70,14 @@ # fi update with reinitialize turbine_yaw = fi.floris.farm.yaw_angles turbine_type= fi.floris.farm.turbine_type_names_sorted - turbine_avg_vel=fi.get_turbine_average_velocities() + turbine_avg_vel=fi.turbine_average_velocities turbine_powers = fi.get_turbine_powers()/1000. turbine_ais =fi.get_turbine_ais() turbine_Cts = fi.get_turbine_Cts() mytext = [f"yaw: {i:.1f}" for i in turbine_yaw[0,0]] if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_wtg)] - if 1: mytext = [f"{mytext[i]} \n Vel: {turbine_avg_vel[0,0,i]:.1f}" for i in range(n_wtg)] - if 1: mytext = [f"{mytext[i]} \n Pow: {turbine_powers[0,0,i]:.1f}" for i in range(n_wtg)] + if 1: mytext = [f"{mytext[i]} \n Vel: {turbine_avg_vel[0,0,i]:.1f}" for i in range(n_wtg)] if 1: mytext = [f"{mytext[i]} \n Pow: {turbine_powers[0,0,i]:.1f}" for i in range(n_wtg)] if 0: mytext = [f"{mytext[i]} \n ai: {turbine_ais[0,0,i]:.1f}" for i in range(n_wtg)] if 1: mytext = [f"{mytext[i]} \n ct: {turbine_Cts[0,0,i]:.1f}" for i in range(n_wtg)] for j in range(fi.floris.farm.n_turbines): diff --git a/examples/vis_03_horizontal_plane.py b/examples/vis_03_horizontal_plane.py index 115a23c57..738e873c5 100644 --- a/examples/vis_03_horizontal_plane.py +++ b/examples/vis_03_horizontal_plane.py @@ -21,7 +21,7 @@ #dh import numpy as np -fi = FlorisInterface("floris/examples/inputs/gch.yaml") # 3.2.1.2.1.1 +fi = FlorisInterface("inputs/gch.yaml") # # Define 4 turbines layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) From 4f3552cc79066adf1d8d5be9c99ed85312612b56 Mon Sep 17 00:00:00 2001 From: Rafael M Mudafort Date: Fri, 31 Mar 2023 14:26:12 -0500 Subject: [PATCH 8/8] Remove temporary examples --- examples/vis_01_visChk_Input.py | 204 ------------------ .../vis_03_1_horizontal_plane_with fi info.py | 89 -------- 2 files changed, 293 deletions(-) delete mode 100644 examples/vis_01_visChk_Input.py delete mode 100644 examples/vis_03_1_horizontal_plane_with fi info.py diff --git a/examples/vis_01_visChk_Input.py b/examples/vis_01_visChk_Input.py deleted file mode 100644 index 37c11476a..000000000 --- a/examples/vis_01_visChk_Input.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright 2021 NREL - -# Licensed under the Apache License, Version 2.0 (the "License"); you may not -# use this file except in compliance with the License. You may obtain a copy of -# the License at http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations under -# the License. - -# See https://floris.readthedocs.io for documentation - -import matplotlib.pyplot as plt - -from floris.tools import FlorisInterface -from floris.tools.visualization import visualize_cut_plane -from floris.tools.visualization import plot_rotor_values - -#dh -import numpy as np -from floris.tools.visualization import plot_turbines_with_fi -from floris.utilities import rotate_coordinates_rel_west -import math #dh. for drawing swept area - -fi = FlorisInterface("inputs/gch.yaml") -flow_field=fi.floris.flow_field -farm=fi.floris.farm -grid=fi.floris.grid - -n_WTG=farm.n_turbines; -wd = flow_field.wind_directions -ws = flow_field.wind_speeds -RD=farm.rotor_diameters - -# check : Farm layout and flowfield info -if 1 : - fig, ax = plt.subplots(1, 1) - plot_turbines_with_fi(ax=ax,fi=fi) - - # text on WTGs - turbine_type= farm.turbine_type_names_sorted - mytext = [f"yaw: {i:.1f}" for i in farm.yaw_angles[0,0]] # after FI, yaw_angles are set 0 - if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_WTG)] - for j in range(n_WTG): - ax.text(fi.layout_x[j], fi.layout_y[j], mytext[j], color='b') - - # text on Farm - mytext = [f" WD: {wd}, WS: {ws}"] # height - if 1: mytext = [f"{mytext} \n TI: {flow_field.turbulence_intensity}, shear: {flow_field.wind_shear}, veer: {flow_field.wind_veer}"] - ax.text(min(fi.layout_x), min(fi.layout_x), mytext, color='black') - ax.set_title('Farm layout ') - #plt.tight_layout(); plt.show() - -# check : Turbine Grid for 1 wind direction rel to west -if 1 : - fig, ax = plt.subplots(1, 1) - ax = fig.add_subplot(projection='3d') - - xWTG, y_WTG, z_WTG=rotate_coordinates_rel_west(np.array([wd[0]]), (grid.x_sorted[0,0], grid.y_sorted[0,0], grid.z_sorted[0,0]), inv_rot=True) - ax.scatter(xWTG,y_WTG,z_WTG) # 작동 - - # draw rotor swept Area - xcoord=np.mean(grid.x_sorted[:, :], axis=(3, 4))[0,0] - ycoord=np.mean(grid.y_sorted[:, :], axis=(3, 4))[0,0] - zcoord=np.mean(grid.z_sorted[:, :], axis=(3, 4))[0,0] - for i in range(n_WTG): - x=[]; y=[]; z=[] - for t in range(360): # on x plane with (y,z) at rot_west condition - x.append(xcoord[i]+0*RD[i]) # wind direction - y.append(ycoord[i]+math.sin(math.radians(t))*RD[i]/2) # - z.append(zcoord[i]+math.cos(math.radians(t))*RD[i]/2) # hub heights - x, y, z=rotate_coordinates_rel_west(np.array([wd[0]]), (x, y, z), inv_rot=True) - ax.plot(x[0,0],y[0,0],z[0,0]) - ax.set_title('Turbine Grid with rotor swept area') - - # text on WTGs - turbine_type= farm.turbine_type_names_sorted - hh=farm.hub_heights; RD=farm.rotor_diameters - mytext = [f"yaw: {i:.1f}" for i in farm.yaw_angles[0,0]] # after FI, yaw_angles are set 0 - if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_WTG)] - if 1: mytext = [f"{mytext[i]} \n HH: {hh[i]}" for i in range(n_WTG)] - if 1: mytext = [f"{mytext[i]} \n RD: {RD[i]}" for i in range(n_WTG)] - for j in range(n_WTG): - ax.text(fi.layout_x[j], fi.layout_y[j], farm.hub_heights[j], mytext[j], color='b') - - -# change some information -if 1: - # Define 4 turbines - layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) - layout_y = np.array([800.0, 800.0, 800.0, 0.0]) - if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs - if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs - solver_settings = { - "type": "turbine_grid", #turbine_grid | flow_field_planar_grid - "turbine_grid_points": 10 - } - fi.reinitialize(layout_x=layout_x, layout_y=layout_y, - turbine_type=turbine_type, - solver_settings=solver_settings) - - flow_field=fi.floris.flow_field - farm=fi.floris.farm - grid=fi.floris.grid - - n_WTG=farm.n_turbines; - wd = flow_field.wind_directions - ws = flow_field.wind_speeds - RD=farm.rotor_diameters_sorted[0,0] - - # set yaw angles - n_WTG = 4 - yaw_angles = np.zeros((1, 1, n_WTG)) - yaw_angles[:,:,:] = (0, 0, 15, -15) - fi.floris.farm.yaw_angles=yaw_angles; # update yaw in fi class - -# check : Farm layout and flowfield info -if 1 : - fig, ax = plt.subplots(1, 1) - plot_turbines_with_fi(ax=ax,fi=fi) - - # text on WTGs - turbine_type= farm.turbine_type_names_sorted - mytext = [f"yaw: {i:.1f}" for i in farm.yaw_angles[0,0]] # after FI, yaw_angles are set 0 - if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_WTG)] - for j in range(n_WTG): - ax.text(fi.layout_x[j], fi.layout_y[j], mytext[j], color='b') - - # text on Farm - mytext = [f" WD: {wd}, WS: {ws}"] # height - if 1: mytext = [f"{mytext} \n TI: {flow_field.turbulence_intensity}, shear: {flow_field.wind_shear}, veer: {flow_field.wind_veer}"] - ax.text(min(fi.layout_x), min(fi.layout_x), mytext, color='black') - ax.set_title('Farm layout: 2nd') - #plt.tight_layout(); plt.show() - -# check : Turbine Grid for 1 wind direction rel to west -if 1 : - fig, ax = plt.subplots(1, 1) - ax = fig.add_subplot(projection='3d') - - xWTG, y_WTG, z_WTG=rotate_coordinates_rel_west(np.array([wd[0]]), (grid.x_sorted[0,0], grid.y_sorted[0,0], grid.z_sorted[0,0]), inv_rot=True) - ax.scatter(xWTG,y_WTG,z_WTG) # 작동 - - # draw rotor swept Area - xcoord=np.mean(grid.x_sorted[:, :], axis=(3, 4))[0,0] - ycoord=np.mean(grid.y_sorted[:, :], axis=(3, 4))[0,0] - zcoord=np.mean(grid.z_sorted[:, :], axis=(3, 4))[0,0] - for i in range(n_WTG): - x=[]; y=[]; z=[] - for t in range(360): # on x plane with (y,z) at rot_west condition - x.append(xcoord[i]+0*RD[i]) # wind direction - y.append(ycoord[i]+math.sin(math.radians(t))*RD[i]/2) # - z.append(zcoord[i]+math.cos(math.radians(t))*RD[i]/2) # hub heights - x, y, z=rotate_coordinates_rel_west(np.array([wd[0]]), (x, y, z), inv_rot=True) - ax.plot(x[0,0],y[0,0],z[0,0]) - ax.set_title('Turbine Grid with rotor swept area: 2nd') - - # text on WTGs - turbine_type= farm.turbine_type_names_sorted - hh=farm.hub_heights; RD=farm.rotor_diameters - mytext = [f"yaw: {i:.1f}" for i in farm.yaw_angles[0,0]] # after FI, yaw_angles are set 0 - if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_WTG)] - if 1: mytext = [f"{mytext[i]} \n HH: {hh[i]}" for i in range(n_WTG)] - if 1: mytext = [f"{mytext[i]} \n RD: {RD[i]}" for i in range(n_WTG)] - for j in range(n_WTG): - ax.text(fi.layout_x[j], fi.layout_y[j], farm.hub_heights[j], mytext[j], color='b') - - -# check for flow_field_planar_grid -if 1: # Set the solver to a flow field planar grid - solver_settings = { - "type": "flow_field_planar_grid", - "normal_vector": "z", - "planar_coordinate": flow_field.reference_wind_height, - "flow_field_grid_points": [20, 20], - "flow_field_bounds": [None, None], - } - fi.reinitialize(wind_directions=wd, wind_speeds=ws, solver_settings=solver_settings) - - flow_field=fi.floris.flow_field - farm=fi.floris.farm - grid=fi.floris.grid - - n_WTG=farm.n_turbines; - wd = flow_field.wind_directions - ws = flow_field.wind_speeds; - - # set yaw angles - n_WTG = 4 - yaw_angles = np.zeros((1, 1, n_WTG)) - yaw_angles[:,:,:] = (0, 0, 15, -15) - fi.floris.farm.yaw_angles=yaw_angles; # update yaw in fi class - -if 1 : #plot grid - fig, ax = plt.subplots(1, 1) - ax = fig.add_subplot(projection='3d') - xWTG, y_WTG, z_WTG=rotate_coordinates_rel_west(np.array([wd[0]]), (grid.x_sorted[0,0], grid.y_sorted[0,0], grid.z_sorted[0,0]), inv_rot=True) - ax.scatter(xWTG,y_WTG,z_WTG) # 작동 - ax.set_zlim(0, 150) - ax.set_title('flowfieldplanar Grid with rotor swept area') - -plt.tight_layout(); plt.show() diff --git a/examples/vis_03_1_horizontal_plane_with fi info.py b/examples/vis_03_1_horizontal_plane_with fi info.py deleted file mode 100644 index 887fc35e8..000000000 --- a/examples/vis_03_1_horizontal_plane_with fi info.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright 2021 NREL - -# Licensed under the Apache License, Version 2.0 (the "License"); you may not -# use this file except in compliance with the License. You may obtain a copy of -# the License at http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations under -# the License. - -# See https://floris.readthedocs.io for documentation - -import matplotlib.pyplot as plt - -from floris.tools import FlorisInterface -from floris.tools.visualization import visualize_cut_plane -from floris.tools.visualization import plot_rotor_values - -#dh -import numpy as np -from floris.tools.visualization import plot_turbines_with_fi - -fi = FlorisInterface("inputs/gch.yaml") - -# # Define 4 turbines -layout_x = np.array([3000.0, 0.0, 1500.0, 3000.0]) -layout_y = np.array([800.0, 800.0, 800.0, 0.0]) -if 1 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'nrel_5MW', 'nrel_5MW'] # same WTGs -if 0 : turbine_type = ['nrel_5MW', 'nrel_5MW', 'iea_10MW', 'iea_15MW'] # mix WTGs -fi.reinitialize(layout_x=layout_x, layout_y=layout_y, turbine_type=turbine_type) - -# plot with yawangle, fi info -if 1 : # dh. 화면에 yaw, fi 정보도 출력 - # wind directions and speeds for plot - wd = [[i] for i in np.arange(45,360,90)]; - ws = [8.0]; - if 0: ws = [[i] for i in np.arange(3,25,1.0)]; - - # yaw angles: Change the yaw angles and configure the plot differently - n_wd=fi.floris.flow_field.n_wind_directions; n_ws=fi.floris.flow_field.n_wind_speeds - n_wtg=fi.floris.farm.n_turbines - yaw_angles = np.zeros((1, 1, n_wtg)) - yaw_angles[:,:,:] = (0, 0, 15, -15) - - # ready for plot - n_col=2 - fig, ax_list = plt.subplots( round(len(wd)/n_col+0.5), n_col, figsize=(16, 8)) - ax_list = ax_list.flatten() - res=200; - for i in range(len(wd)): - # fi update for text on WTGs. - # at the end of fi.calculate_horizontal_plane, restoring fi to previous, - # we can't use those results for texting - fi.reinitialize( wind_speeds=ws, wind_directions=wd[i] ) # update class fi, loosing yaw angles - fi.floris.farm.yaw_angles=yaw_angles; # set again yaw angles into fi - - # getting df (x,y,z, u,v,w) for planar flow field - horizontal_plane=fi.calculate_horizontal_plane(wd=wd[i], ws=ws, height=90.0, yaw_angles=yaw_angles, x_resolution=res, y_resolution=res) - - # plot - ax=ax_list[i]; - visualize_cut_plane(horizontal_plane, ax=ax, title="Wind direction "+str(wd[i])+"deg", color_bar=True); - plot_turbines_with_fi(ax=ax_list[i],fi=fi) # , wd=wd[i] - FarmP = fi.get_farm_power()/1000 # 이거?? - plt.xlabel(f'{FarmP[0,0]:.3f}'+' KW') - - #dh. text on WTGs - # fi update with reinitialize - turbine_yaw = fi.floris.farm.yaw_angles - turbine_type= fi.floris.farm.turbine_type_names_sorted - turbine_avg_vel=fi.turbine_average_velocities - turbine_powers = fi.get_turbine_powers()/1000. - turbine_ais =fi.get_turbine_ais() - turbine_Cts = fi.get_turbine_Cts() - - mytext = [f"yaw: {i:.1f}" for i in turbine_yaw[0,0]] - if 1: mytext = [f"T{i}: {turbine_type[i]} \n {mytext[i]}" for i in range(n_wtg)] - if 1: mytext = [f"{mytext[i]} \n Vel: {turbine_avg_vel[0,0,i]:.1f}" for i in range(n_wtg)] if 1: mytext = [f"{mytext[i]} \n Pow: {turbine_powers[0,0,i]:.1f}" for i in range(n_wtg)] - if 0: mytext = [f"{mytext[i]} \n ai: {turbine_ais[0,0,i]:.1f}" for i in range(n_wtg)] - if 1: mytext = [f"{mytext[i]} \n ct: {turbine_Cts[0,0,i]:.1f}" for i in range(n_wtg)] - for j in range(fi.floris.farm.n_turbines): - ax.text(fi.layout_x[j], fi.layout_y[j], mytext[j], color='springgreen') - - #dh. text on Farm - ax.text(min(horizontal_plane.df.x1), min(horizontal_plane.df.x2), f' FarmPower: {FarmP[0,0]:.2f}'+f' KW \n WD: {wd[i]}, WS: {ws[0]} \n',color='white') - - plt.tight_layout(); plt.savefig("abc.png"); plt.show(); \ No newline at end of file