11import numpy as np
2- from twoaxistracking import plotting
2+ from shapely import geometry
33
44
55def _rotate_origin (x , y , rotation_deg ):
@@ -11,22 +11,19 @@ def _rotate_origin(x, y, rotation_deg):
1111 return xx , yy
1212
1313
14- def generate_field_layout (gcr , total_collector_area , L_min , neighbor_order ,
15- aspect_ratio = None , offset = None , rotation = None ,
16- layout_type = None , slope_azimuth = 0 ,
17- slope_tilt = 0 , plot = False ):
14+ def _calculate_min_tracker_spacing (collector_geometry ):
15+ min_tracker_spacing = 2 * collector_geometry .hausdorff_distance (geometry .Point (0 , 0 ))
16+ return min_tracker_spacing
17+
18+
19+ def generate_field_layout (gcr , total_collector_area , min_tracker_spacing ,
20+ neighbor_order , aspect_ratio , offset , rotation ,
21+ slope_azimuth = 0 , slope_tilt = 0 ):
1822 """
1923 Generate a regularly-spaced collector field layout.
2024
2125 Field layout parameters and limits are described in [1]_.
2226
23- Notes
24- -----
25- The field layout can be specified either by selecting a standard layout
26- using the layout_type argument or by specifying the individual layout
27- parameters aspect_ratio, offset, and rotation. For both cases the ground
28- cover ratio (gcr) needs to be specified.
29-
3027 Any length unit can be used as long as the usage is consistent with the
3128 collector geometry.
3229
@@ -36,26 +33,22 @@ def generate_field_layout(gcr, total_collector_area, L_min, neighbor_order,
3633 Ground cover ratio. Ratio of collector area to ground area.
3734 total_collector_area: float
3835 Surface area of one collector.
39- L_min : float
36+ min_tracker_spacing : float
4037 Minimum distance between collectors.
4138 neighbor_order: int
4239 Order of neighbors to include in layout. neighbor_order=1 includes only
4340 the 8 directly adjacent collectors.
44- aspect_ratio: float, optional
41+ aspect_ratio: float
4542 Ratio of the spacing in the primary direction to the secondary.
46- offset: float, optional
43+ offset: float
4744 Relative row offset in the secondary direction as fraction of the
4845 spacing in the primary direction. -0.5 <= offset < 0.5.
49- rotation: float, optional
46+ rotation: float
5047 Counterclockwise rotation of the field in degrees. 0 <= rotation < 180
51- layout_type: {square, square_rotated, hexagon_e_w, hexagon_n_s}, optional
52- Specification of the special layout type (only depend on gcr).
5348 slope_azimuth : float, optional
5449 Direction of normal to slope on horizontal [degrees]
5550 slope_tilt : float, optional
5651 Tilt of slope relative to horizontal [degrees]
57- plot: bool, default: False
58- Whether to plot the field layout.
5952
6053 Returns
6154 -------
@@ -81,48 +74,22 @@ def generate_field_layout(gcr, total_collector_area, L_min, neighbor_order,
8174 .. [1] `Shading and land use in regularly-spaced sun-tracking collectors, Cumpston & Pye.
8275 <https://doi.org/10.1016/j.solener.2014.06.012>`_
8376 """
84- # Consider special layouts which can be defined only by GCR
85- if layout_type == 'square' :
86- aspect_ratio = 1
87- offset = 0
88- rotation = 0
89- # Diagonal layout is the square layout rotated 45 degrees
90- elif layout_type == 'diagonal' :
91- aspect_ratio = 1
92- offset = 0
93- rotation = 45
94- # Hexagonal layouts are defined by aspect_ratio=0.866 and offset=-0.5
95- elif layout_type == 'hexagonal_n_s' :
96- aspect_ratio = np .sqrt (3 )/ 2
97- offset = - 0.5
98- rotation = 0
99- # The hexagonal E-W layout is the hexagonal N-S layout rotated 90 degrees
100- elif layout_type == 'hexagonal_e_w' :
101- aspect_ratio = np .sqrt (3 )/ 2
102- offset = - 0.5
103- rotation = 90
104- elif layout_type is not None :
105- raise ValueError ('The layout type specified was not recognized.' )
106- elif ((aspect_ratio is None ) or (offset is None ) or (rotation is None )):
107- raise ValueError ('Aspect ratio, offset, and rotation needs to be '
108- 'specified when no layout type has not been selected' )
109-
11077 # Check parameters are within their ranges
111- if aspect_ratio < np .sqrt (1 - offset ** 2 ):
112- raise ValueError ('Aspect ratio is too low and not feasible' )
113- if aspect_ratio > total_collector_area / (gcr * L_min ** 2 ):
114- raise ValueError ('Apsect ratio is too high and not feasible' )
11578 if (offset < - 0.5 ) | (offset >= 0.5 ):
11679 raise ValueError ('The specified offset is outside the valid range.' )
11780 if (rotation < 0 ) | (rotation >= 180 ):
11881 raise ValueError ('The specified rotation is outside the valid range.' )
119- # Check if mimimum and maximum ground cover ratios are exceded
120- gcr_max = total_collector_area / (L_min ** 2 * np .sqrt (1 - offset ** 2 ))
121- if (gcr < 0 ) or (gcr > gcr_max ):
122- raise ValueError ('Maximum ground cover ratio exceded.' )
12382 # Check if Lmin is physically possible given the collector area.
124- if (L_min < np .sqrt (4 * total_collector_area / np .pi )):
83+ if (min_tracker_spacing < np .sqrt (4 * total_collector_area / np .pi )):
12584 raise ValueError ('Lmin is not physically possible.' )
85+ # Check if mimimum and maximum ground cover ratios are exceded
86+ gcr_max = total_collector_area / (min_tracker_spacing ** 2 * np .sqrt (1 - offset ** 2 ))
87+ if (gcr < 0 ) or (gcr > gcr_max ):
88+ raise ValueError ('Maximum ground cover ratio exceded or less than 0.' )
89+ if aspect_ratio < np .sqrt (1 - offset ** 2 ):
90+ raise ValueError ('Aspect ratio is too low and not feasible' )
91+ if aspect_ratio > total_collector_area / (gcr * min_tracker_spacing ** 2 ):
92+ raise ValueError ('Aspect ratio is too high and not feasible' )
12693
12794 N = 1 + 2 * neighbor_order # Number of collectors along each side
12895
@@ -156,8 +123,4 @@ def generate_field_layout(gcr, total_collector_area, L_min, neighbor_order,
156123 # positive means collector is higher than reference collector
157124 relative_slope = - np .cos (np .deg2rad (slope_azimuth - relative_azimuth )) * slope_tilt # noqa: E501
158125
159- # Visualize layout
160- if plot :
161- plotting ._plot_field_layout (X , Y , Z , L_min )
162-
163126 return X , Y , Z , tracker_distance , relative_azimuth , relative_slope
0 commit comments