Skip to content

Commit

Permalink
add grid shape as an attribute defined in set_grid
Browse files Browse the repository at this point in the history
  • Loading branch information
RHammond2 committed Dec 18, 2023
1 parent 324b1a5 commit f2a0dd4
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
18 changes: 15 additions & 3 deletions floris/simulation/flow_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ class FlowField(BaseClass):
heterogenous_inflow_config: dict = field(default=None)
multidim_conditions: dict = field(default=None)

n_wind_directions: int = field(init=False)
n_wind_speeds: int = field(init=False)
n_wind_directions: int = field(init=False)
n_turbines: int = field(init=False, default=0)
grid_resolution: int = field(init=False, default=0)
grid_shape: tuple[int, int, int, int, int] = field(init=False, default=(0, 0, 0, 0, 0))

u_initial_sorted: NDArrayFloat = array_5D_field
v_initial_sorted: NDArrayFloat = array_5D_field
Expand Down Expand Up @@ -113,6 +113,18 @@ 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."
)

@grid_shape.validator
def grid_shape_validator(self, attribute: attrs.Attribute, value: tuple) -> None:
"""Validates that ``grid_shape`` is length-5 tuple of integers.
Args:
attribute (attrs.Attribute): The attrs Attribute data.
value (tuple): A length-5 tuple of integers.
"""
if len(value) != 5:
raise ValueError("`grid_shape` must be a tuple of 5 integer values.")
if not all(isinstance(v, int) for v in value):
raise TypeError("`grid_shape` must be a tuple of 5 integer values.")

def __attrs_post_init__(self) -> None:
if self.heterogenous_inflow_config is not None:
Expand All @@ -132,7 +144,7 @@ def initialize_velocity_field(self, grid: Grid) -> None:
# for height, using it here to apply the shear law makes that dimension store the vertical
# wind profile.
self.n_turbines = grid.n_turbines
self.grid_resolution = grid.grid_resolution
self.grid_shape = grid.grid_shape

wind_profile_plane = (grid.z_sorted / self.reference_wind_height) ** self.wind_shear
dwind_profile_plane = (
Expand Down
28 changes: 23 additions & 5 deletions floris/simulation/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class Grid(ABC, BaseClass):
n_wind_directions: int = field(init=False)
n_wind_speeds: int = field(init=False)
n_turbines: int = field(init=False)
grid_shape: tuple[int, int, int, int, int] = field(init=False)
x_sorted: NDArrayFloat = field(init=False, validator=validate_5DArray_shape)
y_sorted: NDArrayFloat = field(init=False, validator=validate_5DArray_shape)
z_sorted: NDArrayFloat = field(init=False, validator=validate_5DArray_shape)
Expand Down Expand Up @@ -123,12 +124,16 @@ def grid_resolution_validator(self, instance: attrs.Attribute, value: int | Iter
isinstance(self, (TurbineGrid, TurbineCubatureGrid, PointsGrid)):
return
elif isinstance(value, Iterable) and isinstance(self, FlowFieldPlanarGrid):
assert type(value[0]) is int
assert type(value[1]) is int
if not (len(value) == 2 and all(isinstance(v, int) for v in value)):
raise TypeError(
"`FlowFieldPlanarGrid` must have `grid_resolution` as an iterable of 2 `int`s.",
value
)
elif isinstance(value, Iterable) and isinstance(self, FlowFieldGrid):
assert type(value[0]) is int
assert type(value[1]) is int
assert type(value[2]) is int
if len(value) != 3 or all(isinstance(v, int) for v in value):
raise TypeError(
"'FlowFieldGrid` must have `grid_resolution` as an iterable of 3 `int`s.", value
)
else:
raise TypeError("`grid_resolution` must be of type int or Iterable(int,)")

Expand Down Expand Up @@ -244,6 +249,7 @@ def set_grid(self) -> None:
),
dtype=floris_float_type
)
self.grid_shape = template_grid.shape
# Calculate the radial distance from the center of the turbine rotor.
# If a grid resolution of 1 is selected, create a disc_grid of zeros, as
# np.linspace would just return the starting value of -1 * disc_area_radius
Expand Down Expand Up @@ -365,6 +371,7 @@ def set_grid(self) -> None:
),
dtype=floris_float_type
)
self.grid_shape = template_grid.shape
_x = x[:, :, :, None, None] * template_grid
_y = y[:, :, :, None, None] * template_grid
_z = z[:, :, :, None, None] * template_grid
Expand Down Expand Up @@ -509,6 +516,7 @@ 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
"""
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, *self.grid_resolution)

# These are the rotated coordinates of the wind turbines based on the wind direction
x, y, z, self.x_center_of_rotation, self.y_center_of_rotation = rotate_coordinates_rel_west(
Expand Down Expand Up @@ -605,6 +613,9 @@ def set_grid(self) -> None:
if self.x2_bounds is None:
self.x2_bounds = (np.min(y) - 2 * max_diameter, np.max(y) + 2 * max_diameter)

grid_resolution = (self.grid_resolution[0], self.grid_resolution[1], 3)
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, *grid_resolution)

# TODO figure out proper z spacing for GCH, currently set to +/- 10.0
x_points, y_points, z_points = np.meshgrid(
np.linspace(self.x1_bounds[0], self.x1_bounds[1], int(self.grid_resolution[0])),
Expand All @@ -628,6 +639,9 @@ def set_grid(self) -> None:
if self.x2_bounds is None:
self.x2_bounds = (0.001, 6 * np.max(z))

grid_resolution = (1, self.grid_resolution[0], self.grid_resolution[1])
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, *grid_resolution)

x_points, y_points, z_points = np.meshgrid(
np.array([float(self.planar_coordinate)]),
np.linspace(self.x1_bounds[0], self.x1_bounds[1], int(self.grid_resolution[0])),
Expand All @@ -646,6 +660,9 @@ def set_grid(self) -> None:
if self.x2_bounds is None:
self.x2_bounds = (0.001, 6 * np.max(z))

grid_resolution = (self.grid_resolution[0], 1, self.grid_resolution[1])
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, *grid_resolution)

x_points, y_points, z_points = np.meshgrid(
np.linspace(self.x1_bounds[0], self.x1_bounds[1], int(self.grid_resolution[0])),
np.array([float(self.planar_coordinate)]),
Expand Down Expand Up @@ -714,6 +731,7 @@ def set_grid(self) -> None:
Set points for calculation based on a series of user-supplied coordinates.
"""
point_coordinates = np.array(list(zip(self.points_x, self.points_y, self.points_z)))
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, self.points_x.shape[0], 1, 1)

# These are the rotated coordinates of the wind turbines based on the wind direction
x, y, z, _, _ = rotate_coordinates_rel_west(
Expand Down

0 comments on commit f2a0dd4

Please sign in to comment.