Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ This form is written in GitHub's Markdown format. For a reference on this type
of syntax, see GitHub's documentation:
https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax

This template contains guidance for your submission within the < ! - -, - - > blocks.
These are comments in HTML syntax and will not appear in the submission.
Be sure to use the "Preview" feature on GitHub to ensure your submission is formatted as intended.

When including code snippets, please paste the text itself and wrap the code block with
ticks (see the other character on the tilde ~ key in a US keyboard) to format it as code.
For example, Python code should be wrapped in ticks like this:
Expand Down
4 changes: 4 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ This form is written in GitHub's Markdown format. For a reference on this type
of syntax, see GitHub's documentation:
https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax

This template contains guidance for your submission within the < ! - -, - - > blocks.
These are comments in HTML syntax and will not appear in the submission.
Be sure to use the "Preview" feature on GitHub to ensure your submission is formatted as intended.

When including code snippets, please paste the text itself and wrap the code block with
ticks (see the other character on the tilde ~ key in a US keyboard) to format it as code.
For example, Python code should be wrapped in ticks like this:
Expand Down
4 changes: 4 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ This form is written in GitHub's Markdown format. For a reference on this type
of syntax, see GitHub's documentation:
https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax

This template contains guidance for your submission within the < ! - -, - - > blocks.
These are comments in HTML syntax and will not appear in the submission.
Be sure to use the "Preview" feature on GitHub to ensure your submission is formatted as intended.

When including code snippets, please paste the text itself and wrap the code block with
ticks (see the other character on the tilde ~ key in a US keyboard) to format it as code.
For example, Python code should be wrapped in ticks like this:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ __pycache__/
dist
build
.pytest_cache
.ruff_cache

# pip meta data
pip-wheel-metadata
Expand Down
64 changes: 40 additions & 24 deletions docs/code_quality.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/floating_wind_turbine.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ performance curve, and corrections must be included to accurately predict the po
production.

Support for modeling this impact on a floating wind turbine were added in
[PR#518](https://github.com/NREL/floris/pull/518/files) and allow for correcting the
[PR#518](https://github.com/NREL/floris/pull/518/files) and allow for correcting the
user-supplied performance curve for the average tilt. This is accomplished by including
an additional input, `floating_tilt_table`, in the turbine definition which sets the
steady tilt angle of the turbine based on wind speed. An interpolation is created and
Expand Down
6 changes: 3 additions & 3 deletions examples/inputs/jensen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ wake:
turbulence_model: crespo_hernandez
velocity_model: jensen

enable_secondary_steering: true
enable_yaw_added_recovery: true
enable_transverse_velocities: true
enable_secondary_steering: false
enable_yaw_added_recovery: false
enable_transverse_velocities: false

wake_deflection_parameters:
gauss:
Expand Down
13 changes: 6 additions & 7 deletions floris/simulation/farm.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,18 +216,17 @@ def construct_turbine_map(self):
self.turbine_map = [Turbine.from_dict(turb) for turb in self.turbine_definitions]

def construct_turbine_fCts(self):
self.turbine_fCts = [(turb.turbine_type, turb.fCt_interp) for turb in self.turbine_map]

def construct_turbine_fCps(self):
self.turbine_fCps = [(turb.turbine_type, turb.fCp_interp) for turb in self.turbine_map]
self.turbine_fCts = {
turb.turbine_type: turb.fCt_interp for turb in self.turbine_map
}

def construct_turbine_fTilts(self):
self.turbine_fTilts = [(turb.turbine_type, turb.fTilt_interp) for turb in self.turbine_map]

def construct_turbine_power_interps(self):
self.turbine_power_interps = [
(turb.turbine_type, turb.power_interp) for turb in self.turbine_map
]
self.turbine_power_interps = {
turb.turbine_type: turb.power_interp for turb in self.turbine_map
}

def construct_coordinates(self):
self.coordinates = np.array([
Expand Down
1 change: 0 additions & 1 deletion floris/simulation/floris.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ def __attrs_post_init__(self) -> None:
# Initialize farm quanitities that depend on other objects
self.farm.construct_turbine_map()
self.farm.construct_turbine_fCts()
self.farm.construct_turbine_fCps()
self.farm.construct_turbine_power_interps()
self.farm.construct_hub_heights()
self.farm.construct_rotor_diameters()
Expand Down
20 changes: 4 additions & 16 deletions floris/simulation/flow_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,7 @@ def calculate_speed_ups(self, het_map, x, y, z=None):
# Calculate the 3-dimensional speed ups; reshape is needed as the generator
# adds an extra dimension
speed_ups = np.reshape(
[
het_map[0][i](x[i:i+1,:,:,:,:], y[i:i+1,:,:,:,:], z[i:i+1,:,:,:,:])
for i in range(len(het_map[0]))
],
[het_map[0][i](x[i:i+1], y[i:i+1], z[i:i+1]) for i in range( len(het_map[0]))],
np.shape(x)
)

Expand All @@ -195,10 +192,7 @@ def calculate_speed_ups(self, het_map, x, y, z=None):
if np.isnan(speed_ups).any():
idx_nan = np.where(np.isnan(speed_ups))
speed_ups_out_of_region = np.reshape(
[
het_map[1][i](x[i:i+1,:,:,:,:], y[i:i+1,:,:,:,:], z[i:i+1,:,:,:,:])
for i in range(len(het_map[1]))
],
[het_map[1][i](x[i:i+1], y[i:i+1], z[i:i+1]) for i in range(len(het_map[1]))],
np.shape(x)
)

Expand All @@ -208,10 +202,7 @@ def calculate_speed_ups(self, het_map, x, y, z=None):
# Calculate the 2-dimensional speed ups; reshape is needed as the generator
# adds an extra dimension
speed_ups = np.reshape(
[
het_map[0][i](x[i:i+1,:,:,:,:], y[i:i+1,:,:,:,:])
for i in range(len(het_map[0]))
],
[het_map[0][i](x[i:i+1], y[i:i+1]) for i in range(len(het_map[0]))],
np.shape(x)
)

Expand All @@ -220,10 +211,7 @@ def calculate_speed_ups(self, het_map, x, y, z=None):
if np.isnan(speed_ups).any():
idx_nan = np.where(np.isnan(speed_ups))
speed_ups_out_of_region = np.reshape(
[
het_map[1][i](x[i:i+1,:,:,:,:], y[i:i+1,:,:,:,:])
for i in range(len(het_map[1]))
],
[het_map[1][i](x[i:i+1], y[i:i+1]) for i in range(len(het_map[1]))],
np.shape(x)
)

Expand Down
30 changes: 18 additions & 12 deletions floris/simulation/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ class Grid(ABC):
all of these arrays are the same size

Args:
turbine_coordinates (`list[Vec3]`): The collection of turbine coordinate (`Vec3`) objects.
reference_turbine_diameter (:py:obj:`float`): The reference turbine's rotor diameter.
grid_resolution (:py:obj:`int` | :py:obj:`Iterable(int,)`): Grid resolution specific
to each grid type.
turbine_coordinates (`list[Vec3]`): The series of turbine coordinate (`Vec3`) objects.
reference_turbine_diameter (:py:obj:`float`): A reference turbine's rotor diameter.
grid_resolution (:py:obj:`int` | :py:obj:`Iterable(int,)`): Grid resolution with values
specific to each grid type.
wind_directions (:py:obj:`NDArrayFloat`): Wind directions supplied by the user.
wind_speeds (:py:obj:`NDArrayFloat`): Wind speeds supplied by the user.
time_series (:py:obj:`bool`): True/false flag to indicate whether the supplied wind
data is a time series.
time_series (:py:obj:`bool`): Flag to indicate whether the supplied wind data is a time
series.
"""
turbine_coordinates: list[Vec3] = field()
reference_turbine_diameter: float
Expand Down Expand Up @@ -133,11 +133,15 @@ class TurbineGrid(Grid):
"""See `Grid` for more details.

Args:
turbine_coordinates (`list[Vec3]`): The collection of turbine coordinate (`Vec3`) objects.
reference_turbine_diameter (:py:obj:`float`): The reference turbine's rotor diameter.
wind_directions (`list[float]`): The input wind directions
wind_speeds (`list[float]`): The input wind speeds
grid_resolution (:py:obj:`int`): The number of points on each turbine
turbine_coordinates (`list[Vec3]`): The series of turbine coordinate (`Vec3`) objects.
reference_turbine_diameter (:py:obj:`float`): A reference turbine's rotor diameter.
grid_resolution (:py:obj:`int` | :py:obj:`Iterable(int,)`): The number of points in each
direction of the square grid on the rotor plane. For example, grid_resolution=3
creates a 3x3 grid within the rotor swept area.
wind_directions (:py:obj:`NDArrayFloat`): Wind directions supplied by the user.
wind_speeds (:py:obj:`NDArrayFloat`): Wind speeds supplied by the user.
time_series (:py:obj:`bool`): Flag to indicate whether the supplied wind data is a time
series.
"""
# TODO: describe these and the differences between `sorted_indices` and `sorted_coord_indices`
sorted_indices: NDArrayInt = field(init=False)
Expand Down Expand Up @@ -256,7 +260,9 @@ def set_grid(self) -> None:
self.sorted_coord_indices = x.argsort(axis=2)
self.unsorted_indices = self.sorted_indices.argsort(axis=2)

# Put the turbines into the final arrays in their sorted order
# Put the turbine coordinates into the final arrays in their sorted order
# These are the coordinates that should be used within the internal calculations
# such as the wake models and the solvers.
self.x_sorted = np.take_along_axis(_x, self.sorted_indices, axis=2)
self.y_sorted = np.take_along_axis(_y, self.sorted_indices, axis=2)
self.z_sorted = np.take_along_axis(_z, self.sorted_indices, axis=2)
Expand Down
22 changes: 4 additions & 18 deletions floris/simulation/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ def full_flow_sequential_solver(

turbine_grid_farm.construct_turbine_map()
turbine_grid_farm.construct_turbine_fCts()
turbine_grid_farm.construct_turbine_fCps()
turbine_grid_farm.construct_turbine_power_interps()
turbine_grid_farm.construct_hub_heights()
turbine_grid_farm.construct_rotor_diameters()
Expand Down Expand Up @@ -466,24 +465,14 @@ def cc_solver(
z_i = np.mean(grid.z_sorted[:, :, i:i+1], axis=(3, 4))
z_i = z_i[:, :, :, None, None]

rotor_diameter_i = farm.rotor_diameters_sorted[: ,:, i:i+1, None, None]

mask2 = (
np.array(grid.x_sorted < x_i + 0.01)
* np.array(grid.x_sorted > x_i - 0.01)
* np.array(grid.y_sorted < y_i + 0.51*126.0)
* np.array(grid.y_sorted > y_i - 0.51*126.0)
* np.array(grid.y_sorted < y_i + 0.51 * rotor_diameter_i)
* np.array(grid.y_sorted > y_i - 0.51 * rotor_diameter_i)
)
# mask2 = (
# np.logical_and(
# np.logical_and(
# np.logical_and(
# grid.x_sorted < x_i + 0.01,
# grid.x_sorted > x_i - 0.01
# ),
# grid.y_sorted < y_i + 0.51*126.0
# ),
# grid.y_sorted > y_i - 0.51*126.0
# )
# )
turb_inflow_field = (
turb_inflow_field * ~mask2
+ (flow_field.u_initial_sorted - turb_u_wake) * mask2
Expand Down Expand Up @@ -534,7 +523,6 @@ def cc_solver(
turbulence_intensity_i = turbine_turbulence_intensity[:, :, i:i+1]
yaw_angle_i = farm.yaw_angles_sorted[:, :, i:i+1, None, None]
hub_height_i = farm.hub_heights_sorted[: ,:, i:i+1, None, None]
rotor_diameter_i = farm.rotor_diameters_sorted[: ,:, i:i+1, None, None]
TSR_i = farm.TSRs_sorted[: ,:, i:i+1, None, None]

effective_yaw_i = np.zeros_like(yaw_angle_i)
Expand Down Expand Up @@ -666,7 +654,6 @@ def full_flow_cc_solver(

turbine_grid_farm.construct_turbine_map()
turbine_grid_farm.construct_turbine_fCts()
turbine_grid_farm.construct_turbine_fCps()
turbine_grid_farm.construct_turbine_power_interps()
turbine_grid_farm.construct_hub_heights()
turbine_grid_farm.construct_rotor_diameters()
Expand Down Expand Up @@ -1090,7 +1077,6 @@ def full_flow_turbopark_solver(

# turbine_grid_farm.construct_turbine_map()
# turbine_grid_farm.construct_turbine_fCts()
# turbine_grid_farm.construct_turbine_fCps()
# turbine_grid_farm.construct_turbine_power_interps()
# turbine_grid_farm.construct_hub_heights()
# turbine_grid_farm.construct_rotor_diameters()
Expand Down
22 changes: 10 additions & 12 deletions floris/simulation/turbine.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,8 @@ def power(
rotor_effective_velocities = rotor_effective_velocities[:, :, ix_filter]
turbine_type_map = turbine_type_map[:, :, ix_filter]

# Loop over each turbine type given to get thrust coefficient for all turbines
# Loop over each turbine type given to get power for all turbines
p = np.zeros(np.shape(rotor_effective_velocities))
power_interp = dict(power_interp)
turb_types = np.unique(turbine_type_map)
for turb_type in turb_types:
# Using a masked array, apply the thrust coefficient for all turbines of the current
Expand All @@ -276,7 +275,7 @@ def Ct(
yaw_angle: NDArrayFloat,
tilt_angle: NDArrayFloat,
ref_tilt_cp_ct: NDArrayFloat,
fCt: NDArrayObject,
fCt: dict,
tilt_interp: NDArrayObject,
correct_cp_ct_for_tilt: NDArrayBool,
turbine_type_map: NDArrayObject,
Expand All @@ -294,8 +293,8 @@ def Ct(
tilt_angle (NDArrayFloat[wd, ws, turbines]): The tilt angle for each turbine.
ref_tilt_cp_ct (NDArrayFloat[wd, ws, turbines]): The reference tilt angle for each turbine
that the Cp/Ct tables are defined at.
fCt (Iterable[tuple]): The thrust coefficient interpolation functions
for each turbine.
fCt (dict): The thrust coefficient interpolation functions for each turbine. Keys are
the turbine type string and values are the interpolation functions.
tilt_interp (Iterable[tuple]): The tilt interpolation functions for each
turbine.
correct_cp_ct_for_tilt (NDArrayBool[wd, ws, turbines]): Boolean for determining if the
Expand Down Expand Up @@ -341,7 +340,6 @@ def Ct(

# Loop over each turbine type given to get thrust coefficient for all turbines
thrust_coefficient = np.zeros(np.shape(average_velocities))
fCt = dict(fCt)
turb_types = np.unique(turbine_type_map)
for turb_type in turb_types:
# Using a masked array, apply the thrust coefficient for all turbines of the current
Expand All @@ -360,7 +358,7 @@ def axial_induction(
yaw_angle: NDArrayFloat, # (wind directions, wind speeds, turbines)
tilt_angle: NDArrayFloat, # (wind directions, wind speeds, turbines)
ref_tilt_cp_ct: NDArrayFloat,
fCt: NDArrayObject, # (turbines)
fCt: dict, # (turbines)
tilt_interp: NDArrayObject, # (turbines)
correct_cp_ct_for_tilt: NDArrayBool, # (wind directions, wind speeds, turbines)
turbine_type_map: NDArrayObject, # (wind directions, 1, turbines)
Expand All @@ -376,8 +374,8 @@ def axial_induction(
tilt_angle (NDArrayFloat[wd, ws, turbines]): The tilt angle for each turbine.
ref_tilt_cp_ct (NDArrayFloat[wd, ws, turbines]): The reference tilt angle for each turbine
that the Cp/Ct tables are defined at.
fCt (Iterable[tuple]): The thrust coefficient interpolation functions
for each turbine.
fCt (dict): The thrust coefficient interpolation functions for each turbine. Keys are
the turbine type string and values are the interpolation functions.
tilt_interp (Iterable[tuple]): The tilt interpolation functions for each
turbine.
correct_cp_ct_for_tilt (NDArrayBool[wd, ws, turbines]): Boolean for determining if the
Expand Down Expand Up @@ -468,9 +466,9 @@ class PowerThrustTable(FromDictMixin):
"""Helper class to convert the dictionary and list-based inputs to a object of arrays.

Args:
power (NDArrayFloat): The power produced at a given windspeed.
thrust (NDArrayFloat): The thrust at a given windspeed.
wind_speed (NDArrayFloat): Windspeed values, m/s.
power (NDArrayFloat): The power produced at a given wind speed.
thrust (NDArrayFloat): The thrust at a given wind speed.
wind_speed (NDArrayFloat): Wind speed values, m/s.

Raises:
ValueError: Raised if the power, thrust, and wind_speed are not all 1-d array-like shapes.
Expand Down
12 changes: 4 additions & 8 deletions floris/tools/floris_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def reinitialize(
# wtg_id: list[str] | None = None,
# with_resolution: float | None = None,
solver_settings: dict | None = None,
time_series: bool | None = False,
time_series: bool = False,
layout: tuple[list[float], list[float]] | tuple[NDArrayFloat, NDArrayFloat] | None = None,
het_map=None,
):
Expand Down Expand Up @@ -259,10 +259,7 @@ def reinitialize(
if turbine_library_path is not None:
farm_dict["turbine_library_path"] = turbine_library_path

if time_series:
flow_field_dict["time_series"] = True
else:
flow_field_dict["time_series"] = False
flow_field_dict["time_series"] = time_series

## Wake
# if wake is not None:
Expand All @@ -289,7 +286,7 @@ def get_plane_of_points(
):
"""
Calculates velocity values through the
:py:meth:`~.FlowField.calculate_wake` method at points in plane
:py:meth:`FlorisInterface.calculate_wake` method at points in plane
specified by inputs.

Args:
Expand All @@ -298,9 +295,8 @@ def get_plane_of_points(
planar_coordinate (float, optional): Value of normal vector
to slice through. Defaults to None.


Returns:
:py:class:`pandas.DataFrame`: containing values of x1, x2, u, v, w
:py:class:`pandas.DataFrame`: containing values of x1, x2, x3, u, v, w
"""
# Get results vectors
x_flat = self.floris.grid.x_sorted[0, 0].flatten()
Expand Down
Loading