Skip to content

Commit

Permalink
Merge pull request #512 from rafmudaf/api
Browse files Browse the repository at this point in the history
FLORIS Tools API improvements
  • Loading branch information
rafmudaf authored Nov 14, 2022
2 parents e0b3219 + 93cee31 commit 5e71acc
Show file tree
Hide file tree
Showing 17 changed files with 169 additions and 263 deletions.
1 change: 0 additions & 1 deletion examples/01_opening_floris_computing_power.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# See https://floris.readthedocs.io for documentation


import matplotlib.pyplot as plt
import numpy as np

from floris.tools import FlorisInterface
Expand Down
15 changes: 7 additions & 8 deletions examples/02_visualizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
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
import floris.tools.visualization as wakeviz

"""
This example initializes the FLORIS software, and then uses internal
Expand Down Expand Up @@ -52,9 +51,9 @@
# Create the plots
fig, ax_list = plt.subplots(3, 1, figsize=(10, 8))
ax_list = ax_list.flatten()
visualize_cut_plane(horizontal_plane, ax=ax_list[0], title="Horizontal")
visualize_cut_plane(y_plane, ax=ax_list[1], title="Streamwise profile")
visualize_cut_plane(cross_plane, ax=ax_list[2], title="Spanwise profile")
wakeviz.visualize_cut_plane(horizontal_plane, ax=ax_list[0], title="Horizontal")
wakeviz.visualize_cut_plane(y_plane, ax=ax_list[1], title="Streamwise profile")
wakeviz.visualize_cut_plane(cross_plane, ax=ax_list[2], title="Spanwise profile")

# FLORIS further includes visualization methods for visualing the rotor plane of each
# Turbine in the simulation
Expand All @@ -64,7 +63,7 @@
fi.calculate_wake()

# Plot the values at each rotor
fig, axes, _ , _ = plot_rotor_values(fi.floris.flow_field.u, wd_index=0, ws_index=0, n_rows=1, n_cols=3, return_fig_objects=True)
fig, axes, _ , _ = wakeviz.plot_rotor_values(fi.floris.flow_field.u, wd_index=0, ws_index=0, n_rows=1, n_cols=3, return_fig_objects=True)
fig.suptitle("Rotor Plane Visualization, Original Resolution")

# FLORIS supports multiple types of grids for capturing wind speed
Expand All @@ -86,7 +85,7 @@
fi.calculate_wake()

# Plot the values at each rotor
fig, axes, _ , _ = plot_rotor_values(fi.floris.flow_field.u, wd_index=0, ws_index=0, n_rows=1, n_cols=3, return_fig_objects=True)
fig, axes, _ , _ = wakeviz.plot_rotor_values(fi.floris.flow_field.u, wd_index=0, ws_index=0, n_rows=1, n_cols=3, return_fig_objects=True)
fig.suptitle("Rotor Plane Visualization, 10x10 Resolution")

plt.show()
wakeviz.show_plots()
34 changes: 17 additions & 17 deletions examples/03_making_adjustments.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import numpy as np

from floris.tools import FlorisInterface
from floris.tools import visualize_cut_plane #, plot_turbines_with_fi
import floris.tools.visualization as wakeviz

"""
This example makes changes to the given input file through the script.
Expand All @@ -38,53 +38,53 @@

# Plot a horizatonal slice of the initial configuration
horizontal_plane = fi.calculate_horizontal_plane(height=90.0)
visualize_cut_plane(horizontal_plane, ax=axarr[0], title="Initial setup", minSpeed=MIN_WS, maxSpeed=MAX_WS)

wakeviz.visualize_cut_plane(horizontal_plane, ax=axarr[0], title="Initial setup", min_speed=MIN_WS, max_speed=MAX_WS)

# Change the wind speed
horizontal_plane = fi.calculate_horizontal_plane(ws=[7.0], height=90.0)
visualize_cut_plane(horizontal_plane, ax=axarr[1], title="Wind speed at 7 m/s", minSpeed=MIN_WS, maxSpeed=MAX_WS)
wakeviz.visualize_cut_plane(horizontal_plane, ax=axarr[1], title="Wind speed at 7 m/s", min_speed=MIN_WS, max_speed=MAX_WS)


# Change the wind shear, reset the wind speed, and plot a vertical slice
fi.reinitialize( wind_shear=0.2, wind_speeds=[8.0] )
y_plane = fi.calculate_y_plane(crossstream_dist=0.0)
visualize_cut_plane(y_plane, ax=axarr[2], title="Wind shear at 0.2", minSpeed=MIN_WS, maxSpeed=MAX_WS)
wakeviz.visualize_cut_plane(y_plane, ax=axarr[2], title="Wind shear at 0.2", min_speed=MIN_WS, max_speed=MAX_WS)


# Change the farm layout
# # Change the farm layout
N = 3 # Number of turbines per row and per column
X, Y = np.meshgrid(
5.0 * fi.floris.farm.rotor_diameters[0][0][0] * np.arange(0, N, 1),
5.0 * fi.floris.farm.rotor_diameters[0][0][0] * np.arange(0, N, 1),
)
fi.reinitialize(layout_x=X.flatten(), layout_y=Y.flatten())
fi.reinitialize(layout_x=X.flatten(), layout_y=Y.flatten(), wind_directions=[360.0])
horizontal_plane = fi.calculate_horizontal_plane(height=90.0)
visualize_cut_plane(horizontal_plane, ax=axarr[3], title="3x3 Farm", minSpeed=MIN_WS, maxSpeed=MAX_WS)

wakeviz.visualize_cut_plane(horizontal_plane, ax=axarr[3], title="3x3 Farm", min_speed=MIN_WS, max_speed=MAX_WS)
wakeviz.add_turbine_id_labels(fi, axarr[3], color="w", backgroundcolor="k")
wakeviz.plot_turbines_with_fi(fi, axarr[3])

# Change the yaw angles and configure the plot differently
yaw_angles = np.zeros((1, 1, N * N))

## First row
yaw_angles[:,:,0] = 30.0
yaw_angles[:,:,1] = -30.0
yaw_angles[:,:,2] = 30.0
yaw_angles[:,:,3] = -30.0
yaw_angles[:,:,6] = 30.0

## Second row
yaw_angles[:,:,3] = -30.0
yaw_angles[:,:,1] = -30.0
yaw_angles[:,:,4] = 30.0
yaw_angles[:,:,5] = -30.0
yaw_angles[:,:,7] = -30.0

horizontal_plane = fi.calculate_horizontal_plane(yaw_angles=yaw_angles, height=90.0)
visualize_cut_plane(horizontal_plane, ax=axarr[4], title="Yawesome art", cmap="PuOr", minSpeed=MIN_WS, maxSpeed=MAX_WS)
# plot_turbines_with_fi(axarr[8], fi)
wakeviz.visualize_cut_plane(horizontal_plane, ax=axarr[4], title="Yawesome art", cmap="PuOr", min_speed=MIN_WS, max_speed=MAX_WS)
wakeviz.plot_turbines_with_fi(fi, axarr[4], yaw_angles=yaw_angles, color="c")


# Plot the cross-plane of the 3x3 configuration
cross_plane = fi.calculate_cross_plane(yaw_angles=yaw_angles, downstream_dist=610.0)
visualize_cut_plane(cross_plane, ax=axarr[5], title="Cross section at 610 m", minSpeed=MIN_WS, maxSpeed=MAX_WS)
wakeviz.visualize_cut_plane(cross_plane, ax=axarr[5], title="Cross section at 610 m", min_speed=MIN_WS, max_speed=MAX_WS)
axarr[5].invert_xaxis()


plt.show()
wakeviz.show_plots()
3 changes: 1 addition & 2 deletions examples/04_sweep_wind_directions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
import numpy as np

from floris.tools import FlorisInterface
from floris.tools.visualization import visualize_cut_plane


"""
04_sweep_wind_directions
Expand Down Expand Up @@ -72,4 +70,5 @@
ax.legend()
ax.set_xlabel('Wind Direction (deg)')
ax.set_ylabel('Power (kW)')

plt.show()
1 change: 0 additions & 1 deletion examples/05_sweep_wind_speeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import numpy as np

from floris.tools import FlorisInterface
from floris.tools.visualization import visualize_cut_plane

"""
05_sweep_wind_speeds
Expand Down
1 change: 0 additions & 1 deletion examples/06_sweep_wind_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# See https://floris.readthedocs.io for documentation


import enum
import matplotlib.pyplot as plt
import numpy as np

Expand Down
8 changes: 2 additions & 6 deletions examples/08_calc_aep_from_rose_use_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@
# See https://floris.readthedocs.io for documentation


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.interpolate import NearestNDInterpolator
from floris.tools import FlorisInterface, WindRose, wind_rose
import floris.tools.visualization as wakeviz

"""
This example demonstrates how to calculate the Annual Energy Production (AEP)
Expand Down Expand Up @@ -70,5 +67,4 @@
aep_no_wake = fi.get_farm_AEP_wind_rose_class(wind_rose=wind_rose, no_wake=True)
print("Farm AEP (no_wake=True): {:.3f} GWh".format(aep_no_wake / 1.0e9))


plt.show()
wakeviz.show_plots()
1 change: 0 additions & 1 deletion examples/09_compare_farm_power_with_neighbor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@


import numpy as np
import pandas as pd
from floris.tools import FlorisInterface
import matplotlib.pyplot as plt

Expand Down
11 changes: 5 additions & 6 deletions examples/17_multiple_turbine_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@


import matplotlib.pyplot as plt
import numpy as np

from floris.tools import FlorisInterface
from floris.tools.visualization import visualize_cut_plane
import floris.tools.visualization as wakeviz

"""
This example uses an input file where multiple turbine types are defined.
Expand All @@ -38,8 +37,8 @@
# Create the plots
fig, ax_list = plt.subplots(3, 1, figsize=(10, 8))
ax_list = ax_list.flatten()
visualize_cut_plane(horizontal_plane, ax=ax_list[0], title="Horizontal")
visualize_cut_plane(y_plane, ax=ax_list[1], title="Streamwise profile")
visualize_cut_plane(cross_plane, ax=ax_list[2], title="Spanwise profile")
wakeviz.visualize_cut_plane(horizontal_plane, ax=ax_list[0], title="Horizontal")
wakeviz.visualize_cut_plane(y_plane, ax=ax_list[1], title="Streamwise profile")
wakeviz.visualize_cut_plane(cross_plane, ax=ax_list[2], title="Spanwise profile")

plt.show()
wakeviz.show_plots()
5 changes: 0 additions & 5 deletions examples/18_check_turbine.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import os

from floris.tools import FlorisInterface
from floris.tools import visualize_cut_plane #, plot_turbines_with_fi

"""
For each turbine in the turbine library, make a small figure showing that its power curve and power loss to yaw are reasonable and
Expand Down Expand Up @@ -109,8 +108,4 @@
# Give a suptitle
fig.suptitle(t)



plt.show()


1 change: 0 additions & 1 deletion examples/19_streamlit_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import matplotlib.pyplot as plt
import streamlit as st
import numpy as np
import pandas as pd
# import seaborn as sns

from floris.tools import FlorisInterface
Expand Down
12 changes: 4 additions & 8 deletions examples/22_get_wind_speed_at_turbines.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# See https://floris.readthedocs.io for documentation


import matplotlib.pyplot as plt
import numpy as np

from floris.tools import FlorisInterface
Expand All @@ -35,13 +34,10 @@
print('U points is 1 wd x 1 ws x 4 turbines x 3 x 3 points (turbine_grid_points=3)')
print(u_points.shape)

# Collect the average wind speeds from each turbine
avg_vel = fi.get_turbine_average_velocities()

print('Avg vel is 1 wd x 1 ws x 4 turbines')
print(avg_vel.shape)
print('turbine_average_velocities is 1 wd x 1 ws x 4 turbines')
print(fi.turbine_average_velocities)

# Show that one is equivalent to the other following averaging
print('Avg Vel is determined by taking the cube root of mean of the cubed value across the points')
print('Average velocity: ', avg_vel)
print('turbine_average_velocities is determined by taking the cube root of mean of the cubed value across the points')
print('turbine_average_velocities: ', fi.turbine_average_velocities)
print('Recomputed: ', np.cbrt(np.mean(u_points**3, axis=(3,4))))
59 changes: 26 additions & 33 deletions floris/tools/cut_plane.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,33 @@ def __init__(self, df, x1_resolution, x2_resolution, normal_vector):
df (pandas.DataFrame): Pandas DataFrame of data with
columns x1, x2, u, v, w.
"""
self.df = df
self.normal_vector = normal_vector
self.df: pd.DataFrame = df
self.normal_vector: str = normal_vector
self.resolution = (x1_resolution, x2_resolution)
self.df.set_index(["x1", "x2"])

def __sub__(self, other):

if self.normal_vector != other.normal_vector:
raise ValueError("Operands must have consistent normal vectors.")

# if self.normal_vector.df.
# DF must be of the same size
# resolution must be of the same size

df: pd.DataFrame = self.df.copy()
other_df: pd.DataFrame = other.df.copy()

df['u'] = self.df['u'] - other_df['u']
df['v'] = self.df['v'] - other_df['v']
df['w'] = self.df['w'] - other_df['w']

return CutPlane(
df,
self.resolution[0],
self.resolution[1],
self.normal_vector
)


# Modification functions
Expand Down Expand Up @@ -323,37 +347,6 @@ def project_onto(cut_plane_a, cut_plane_b):
)


def subtract(cut_plane_a_in, cut_plane_b_in):
"""
Subtract u,v,w terms of cut_plane_b from cut_plane_a
Args:
cut_plane_a_in (:py:class:`~.tools.cut_plane.CutPlane`):
Plane of data to subtract from.
cut_plane_b_in (:py:class:`~.tools.cut_plane.CutPlane`):
Plane of data to subtract b.
Returns:
cut_plane (:py:class:`~.tools.cut_plane.CutPlane`):
Difference of cut_plane_a_in minus cut_plane_b_in.
"""

# First make copies of original
cut_plane_a = copy.deepcopy(cut_plane_a_in)
cut_plane_b = copy.deepcopy(cut_plane_b_in)

# Sort x1 and x2 and make the index
cut_plane_a.df = cut_plane_a.df.set_index(["x1", "x2"])
cut_plane_b.df = cut_plane_b.df.set_index(["x1", "x2"])

# Do subtraction
cut_plane_a.df = cut_plane_a.df.subtract(
cut_plane_b.df
).reset_index() # .sort_values(['x2','x1'])# .dropna()
# cut_plane_a.df = cut_plane_a.df.sort_values(['x1','x2'])
return cut_plane_a


def calculate_wind_speed(cross_plane, x1_loc, x2_loc, R):
"""
Calculate effective wind speed within specified range of a point.
Expand Down
25 changes: 12 additions & 13 deletions floris/tools/floris_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,16 @@ def calculate_wake(
track_n_upstream_wakes (bool, optional): When *True*, will keep track of the
number of upstream wakes a turbine is experiencing. Defaults to *False*.
"""
# self.floris.flow_field.calculate_wake(
# no_wake=no_wake,
# points=points,
# track_n_upstream_wakes=track_n_upstream_wakes,
# )

# TODO decide where to handle this sign issue
if (yaw_angles is not None) and not (np.all(yaw_angles==0.)):
self.floris.farm.yaw_angles = yaw_angles
if yaw_angles is None:
yaw_angles = np.zeros(
(
self.floris.flow_field.n_wind_directions,
self.floris.flow_field.n_wind_speeds,
self.floris.farm.n_turbines
)
)
self.floris.farm.yaw_angles = yaw_angles

# Initialize solution space
self.floris.initialize_domain()
Expand Down Expand Up @@ -601,11 +602,9 @@ def get_turbine_ais(self) -> NDArrayFloat:
)
return turbine_ais

def get_turbine_average_velocities(self) -> NDArrayFloat:
turbine_avg_vels = average_velocity(
velocities=self.floris.flow_field.u,
)
return turbine_avg_vels
@property
def turbine_average_velocities(self) -> NDArrayFloat:
return average_velocity(velocities=self.floris.flow_field.u)

def get_turbine_TIs(self) -> NDArrayFloat:
return self.floris.flow_field.turbulence_intensity_field
Expand Down
Loading

0 comments on commit 5e71acc

Please sign in to comment.