Skip to content

Commit f2a0dd4

Browse files
committed
add grid shape as an attribute defined in set_grid
1 parent 324b1a5 commit f2a0dd4

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

floris/simulation/flow_field.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ class FlowField(BaseClass):
4747
heterogenous_inflow_config: dict = field(default=None)
4848
multidim_conditions: dict = field(default=None)
4949

50-
n_wind_directions: int = field(init=False)
5150
n_wind_speeds: int = field(init=False)
51+
n_wind_directions: int = field(init=False)
5252
n_turbines: int = field(init=False, default=0)
53-
grid_resolution: int = field(init=False, default=0)
53+
grid_shape: tuple[int, int, int, int, int] = field(init=False, default=(0, 0, 0, 0, 0))
5454

5555
u_initial_sorted: NDArrayFloat = array_5D_field
5656
v_initial_sorted: NDArrayFloat = array_5D_field
@@ -113,6 +113,18 @@ def het_map_validator(self, instance: attrs.Attribute, value: list | None) -> No
113113
"The het_map's wind direction dimension not equal to number of wind directions."
114114
)
115115

116+
@grid_shape.validator
117+
def grid_shape_validator(self, attribute: attrs.Attribute, value: tuple) -> None:
118+
"""Validates that ``grid_shape`` is length-5 tuple of integers.
119+
120+
Args:
121+
attribute (attrs.Attribute): The attrs Attribute data.
122+
value (tuple): A length-5 tuple of integers.
123+
"""
124+
if len(value) != 5:
125+
raise ValueError("`grid_shape` must be a tuple of 5 integer values.")
126+
if not all(isinstance(v, int) for v in value):
127+
raise TypeError("`grid_shape` must be a tuple of 5 integer values.")
116128

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

137149
wind_profile_plane = (grid.z_sorted / self.reference_wind_height) ** self.wind_shear
138150
dwind_profile_plane = (

floris/simulation/grid.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class Grid(ABC, BaseClass):
7979
n_wind_directions: int = field(init=False)
8080
n_wind_speeds: int = field(init=False)
8181
n_turbines: int = field(init=False)
82+
grid_shape: tuple[int, int, int, int, int] = field(init=False)
8283
x_sorted: NDArrayFloat = field(init=False, validator=validate_5DArray_shape)
8384
y_sorted: NDArrayFloat = field(init=False, validator=validate_5DArray_shape)
8485
z_sorted: NDArrayFloat = field(init=False, validator=validate_5DArray_shape)
@@ -123,12 +124,16 @@ def grid_resolution_validator(self, instance: attrs.Attribute, value: int | Iter
123124
isinstance(self, (TurbineGrid, TurbineCubatureGrid, PointsGrid)):
124125
return
125126
elif isinstance(value, Iterable) and isinstance(self, FlowFieldPlanarGrid):
126-
assert type(value[0]) is int
127-
assert type(value[1]) is int
127+
if not (len(value) == 2 and all(isinstance(v, int) for v in value)):
128+
raise TypeError(
129+
"`FlowFieldPlanarGrid` must have `grid_resolution` as an iterable of 2 `int`s.",
130+
value
131+
)
128132
elif isinstance(value, Iterable) and isinstance(self, FlowFieldGrid):
129-
assert type(value[0]) is int
130-
assert type(value[1]) is int
131-
assert type(value[2]) is int
133+
if len(value) != 3 or all(isinstance(v, int) for v in value):
134+
raise TypeError(
135+
"'FlowFieldGrid` must have `grid_resolution` as an iterable of 3 `int`s.", value
136+
)
132137
else:
133138
raise TypeError("`grid_resolution` must be of type int or Iterable(int,)")
134139

@@ -244,6 +249,7 @@ def set_grid(self) -> None:
244249
),
245250
dtype=floris_float_type
246251
)
252+
self.grid_shape = template_grid.shape
247253
# Calculate the radial distance from the center of the turbine rotor.
248254
# If a grid resolution of 1 is selected, create a disc_grid of zeros, as
249255
# np.linspace would just return the starting value of -1 * disc_area_radius
@@ -365,6 +371,7 @@ def set_grid(self) -> None:
365371
),
366372
dtype=floris_float_type
367373
)
374+
self.grid_shape = template_grid.shape
368375
_x = x[:, :, :, None, None] * template_grid
369376
_y = y[:, :, :, None, None] * template_grid
370377
_z = z[:, :, :, None, None] * template_grid
@@ -509,6 +516,7 @@ def set_grid(self) -> None:
509516
First, sort the turbines so that we know the bounds in the correct orientation.
510517
Then, create the grid based on this wind-from-left orientation
511518
"""
519+
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, *self.grid_resolution)
512520

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

616+
grid_resolution = (self.grid_resolution[0], self.grid_resolution[1], 3)
617+
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, *grid_resolution)
618+
608619
# TODO figure out proper z spacing for GCH, currently set to +/- 10.0
609620
x_points, y_points, z_points = np.meshgrid(
610621
np.linspace(self.x1_bounds[0], self.x1_bounds[1], int(self.grid_resolution[0])),
@@ -628,6 +639,9 @@ def set_grid(self) -> None:
628639
if self.x2_bounds is None:
629640
self.x2_bounds = (0.001, 6 * np.max(z))
630641

642+
grid_resolution = (1, self.grid_resolution[0], self.grid_resolution[1])
643+
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, *grid_resolution)
644+
631645
x_points, y_points, z_points = np.meshgrid(
632646
np.array([float(self.planar_coordinate)]),
633647
np.linspace(self.x1_bounds[0], self.x1_bounds[1], int(self.grid_resolution[0])),
@@ -646,6 +660,9 @@ def set_grid(self) -> None:
646660
if self.x2_bounds is None:
647661
self.x2_bounds = (0.001, 6 * np.max(z))
648662

663+
grid_resolution = (self.grid_resolution[0], 1, self.grid_resolution[1])
664+
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, *grid_resolution)
665+
649666
x_points, y_points, z_points = np.meshgrid(
650667
np.linspace(self.x1_bounds[0], self.x1_bounds[1], int(self.grid_resolution[0])),
651668
np.array([float(self.planar_coordinate)]),
@@ -714,6 +731,7 @@ def set_grid(self) -> None:
714731
Set points for calculation based on a series of user-supplied coordinates.
715732
"""
716733
point_coordinates = np.array(list(zip(self.points_x, self.points_y, self.points_z)))
734+
self.grid_shape = (self.n_wind_directions, self.n_wind_speeds, self.points_x.shape[0], 1, 1)
717735

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

0 commit comments

Comments
 (0)