foxes 0.7.4.25__py3-none-any.whl → 0.8.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of foxes might be problematic. Click here for more details.
- foxes/VERSION +1 -1
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/METADATA +20 -116
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/RECORD +7 -33
- foxes/opt/__init__.py +0 -9
- foxes/opt/constraints/__init__.py +0 -6
- foxes/opt/constraints/area_geometry.py +0 -214
- foxes/opt/constraints/min_dist.py +0 -239
- foxes/opt/core/__init__.py +0 -9
- foxes/opt/core/farm_constraint.py +0 -96
- foxes/opt/core/farm_objective.py +0 -97
- foxes/opt/core/farm_opt_problem.py +0 -346
- foxes/opt/core/farm_vars_problem.py +0 -219
- foxes/opt/core/pop_states.py +0 -206
- foxes/opt/objectives/__init__.py +0 -6
- foxes/opt/objectives/farm_vars.py +0 -323
- foxes/opt/objectives/max_n_turbines.py +0 -142
- foxes/opt/problems/__init__.py +0 -7
- foxes/opt/problems/layout/__init__.py +0 -9
- foxes/opt/problems/layout/farm_layout.py +0 -137
- foxes/opt/problems/layout/geom_layouts/__init__.py +0 -10
- foxes/opt/problems/layout/geom_layouts/constraints.py +0 -802
- foxes/opt/problems/layout/geom_layouts/geom_layout.py +0 -290
- foxes/opt/problems/layout/geom_layouts/geom_layout_gridded.py +0 -276
- foxes/opt/problems/layout/geom_layouts/geom_reggrid.py +0 -351
- foxes/opt/problems/layout/geom_layouts/geom_reggrids.py +0 -482
- foxes/opt/problems/layout/geom_layouts/objectives.py +0 -666
- foxes/opt/problems/layout/reggrids_layout.py +0 -417
- foxes/opt/problems/layout/regular_layout.py +0 -350
- foxes/opt/problems/opt_farm_vars.py +0 -586
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/LICENSE +0 -0
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/WHEEL +0 -0
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/top_level.txt +0 -0
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/zip-safe +0 -0
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from copy import deepcopy
|
|
3
|
-
|
|
4
|
-
from foxes.opt.core import FarmVarsProblem, FarmOptProblem
|
|
5
|
-
from foxes.models.turbine_models import Calculator
|
|
6
|
-
import foxes.variables as FV
|
|
7
|
-
import foxes.constants as FC
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class RegularLayoutOptProblem(FarmVarsProblem):
|
|
11
|
-
"""
|
|
12
|
-
Places turbines on a regular grid and optimizes
|
|
13
|
-
its parameters.
|
|
14
|
-
|
|
15
|
-
Attributes
|
|
16
|
-
----------
|
|
17
|
-
min_spacing: float
|
|
18
|
-
The minimal turbine spacing
|
|
19
|
-
|
|
20
|
-
:group: opt.problems.layout
|
|
21
|
-
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
SPACING_X = "spacing_x"
|
|
25
|
-
SPACING_Y = "spacing_y"
|
|
26
|
-
OFFSET_X = "offset_X"
|
|
27
|
-
OFFSET_Y = "offset_Y"
|
|
28
|
-
ANGLE = "angle"
|
|
29
|
-
|
|
30
|
-
def __init__(
|
|
31
|
-
self,
|
|
32
|
-
name,
|
|
33
|
-
algo,
|
|
34
|
-
min_spacing,
|
|
35
|
-
**kwargs,
|
|
36
|
-
):
|
|
37
|
-
"""
|
|
38
|
-
Constructor.
|
|
39
|
-
|
|
40
|
-
Parameters
|
|
41
|
-
----------
|
|
42
|
-
name: str
|
|
43
|
-
The problem's name
|
|
44
|
-
algo: foxes.core.Algorithm
|
|
45
|
-
The algorithm
|
|
46
|
-
min_spacing: float
|
|
47
|
-
The minimal turbine spacing
|
|
48
|
-
kwargs: dict, optional
|
|
49
|
-
Additional parameters for `FarmVarsProblem`
|
|
50
|
-
|
|
51
|
-
"""
|
|
52
|
-
super().__init__(name, algo, **kwargs)
|
|
53
|
-
self.min_spacing = min_spacing
|
|
54
|
-
|
|
55
|
-
def initialize(self, verbosity=1, **kwargs):
|
|
56
|
-
"""
|
|
57
|
-
Initialize the object.
|
|
58
|
-
|
|
59
|
-
Parameters
|
|
60
|
-
----------
|
|
61
|
-
verbosity: int
|
|
62
|
-
The verbosity level, 0 = silent
|
|
63
|
-
kwargs: dict, optional
|
|
64
|
-
Additional parameters for super class init
|
|
65
|
-
|
|
66
|
-
"""
|
|
67
|
-
self._mname = self.name + "_calc"
|
|
68
|
-
for t in self.algo.farm.turbines:
|
|
69
|
-
if self._mname not in t.models:
|
|
70
|
-
t.models.append(self._mname)
|
|
71
|
-
self._turbine = deepcopy(self.farm.turbines[-1])
|
|
72
|
-
|
|
73
|
-
self.algo.mbook.turbine_models[self._mname] = Calculator(
|
|
74
|
-
in_vars=[FC.VALID, FV.P, FV.CT],
|
|
75
|
-
out_vars=[FC.VALID, FV.P, FV.CT],
|
|
76
|
-
func=lambda valid, P, ct, st_sel: (valid, P * valid, ct * valid),
|
|
77
|
-
pre_rotor=False,
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
b = self.farm.boundary
|
|
81
|
-
assert b is not None, f"Problem '{self.name}': Missing wind farm boundary."
|
|
82
|
-
pmax = b.p_max()
|
|
83
|
-
pmin = b.p_min()
|
|
84
|
-
self._pmin = pmin
|
|
85
|
-
self._xy0 = 0.5 * (pmin + pmax)
|
|
86
|
-
self._halfspan = (pmax - pmin) / 2
|
|
87
|
-
self._halflen = np.linalg.norm(self._halfspan)
|
|
88
|
-
self.max_spacing = 2 * (self._halflen + self.min_spacing)
|
|
89
|
-
self._halfn = int(self._halflen / self.min_spacing)
|
|
90
|
-
if self._halfn * self.min_spacing < self._halflen:
|
|
91
|
-
self._halfn += 1
|
|
92
|
-
self._nrow = 2 * self._halfn + 1
|
|
93
|
-
self._nturb = self._nrow**2
|
|
94
|
-
|
|
95
|
-
if verbosity > 0:
|
|
96
|
-
print(f"Problem '{self.name}':")
|
|
97
|
-
print(f" xy0 = {self._xy0}")
|
|
98
|
-
print(f" span = {np.linalg.norm(self._halfspan*2):.2f}")
|
|
99
|
-
print(f" min spacing = {self.min_spacing:.2f}")
|
|
100
|
-
print(f" max spacing = {self.max_spacing:.2f}")
|
|
101
|
-
print(f" n row turbns = {self._nrow}")
|
|
102
|
-
print(f" n turbines = {self._nturb}")
|
|
103
|
-
print(f" turbine mdls = {self._turbine.models}")
|
|
104
|
-
|
|
105
|
-
if self.farm.n_turbines < self._nturb:
|
|
106
|
-
for i in range(self._nturb - self.farm.n_turbines):
|
|
107
|
-
ti = len(self.farm.turbines)
|
|
108
|
-
self.farm.turbines.append(deepcopy(self._turbine))
|
|
109
|
-
self.farm.turbines[-1].index = ti
|
|
110
|
-
self.farm.turbines[-1].name = f"T{ti}"
|
|
111
|
-
elif self.farm.n_turbines > self._nturb:
|
|
112
|
-
self.farm.turbines = self.farm.turbines[: self._nturb]
|
|
113
|
-
self.algo.n_turbines = self._nturb
|
|
114
|
-
|
|
115
|
-
super().initialize(
|
|
116
|
-
pre_rotor_vars=[FV.X, FV.Y, FC.VALID],
|
|
117
|
-
post_rotor_vars=[],
|
|
118
|
-
verbosity=verbosity,
|
|
119
|
-
**kwargs,
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
def var_names_float(self):
|
|
123
|
-
"""
|
|
124
|
-
The names of float variables.
|
|
125
|
-
|
|
126
|
-
Returns
|
|
127
|
-
-------
|
|
128
|
-
names: list of str
|
|
129
|
-
The names of the float variables
|
|
130
|
-
|
|
131
|
-
"""
|
|
132
|
-
return [
|
|
133
|
-
self.SPACING_X,
|
|
134
|
-
self.SPACING_Y,
|
|
135
|
-
self.OFFSET_X,
|
|
136
|
-
self.OFFSET_Y,
|
|
137
|
-
self.ANGLE,
|
|
138
|
-
]
|
|
139
|
-
|
|
140
|
-
def initial_values_float(self):
|
|
141
|
-
"""
|
|
142
|
-
The initial values of the float variables.
|
|
143
|
-
|
|
144
|
-
Returns
|
|
145
|
-
-------
|
|
146
|
-
values: numpy.ndarray
|
|
147
|
-
Initial float values, shape: (n_vars_float,)
|
|
148
|
-
|
|
149
|
-
"""
|
|
150
|
-
return [self.min_spacing, self.min_spacing, 0.0, 0.0, 0.0]
|
|
151
|
-
|
|
152
|
-
def min_values_float(self):
|
|
153
|
-
"""
|
|
154
|
-
The minimal values of the float variables.
|
|
155
|
-
|
|
156
|
-
Use -numpy.inf for unbounded.
|
|
157
|
-
|
|
158
|
-
Returns
|
|
159
|
-
-------
|
|
160
|
-
values: numpy.ndarray
|
|
161
|
-
Minimal float values, shape: (n_vars_float,)
|
|
162
|
-
|
|
163
|
-
"""
|
|
164
|
-
return [
|
|
165
|
-
self.min_spacing,
|
|
166
|
-
self.min_spacing,
|
|
167
|
-
-self._halfspan[0] - self.min_spacing,
|
|
168
|
-
-self._halfspan[1] - self.min_spacing,
|
|
169
|
-
0.0,
|
|
170
|
-
]
|
|
171
|
-
|
|
172
|
-
def max_values_float(self):
|
|
173
|
-
"""
|
|
174
|
-
The maximal values of the float variables.
|
|
175
|
-
|
|
176
|
-
Use numpy.inf for unbounded.
|
|
177
|
-
|
|
178
|
-
Returns
|
|
179
|
-
-------
|
|
180
|
-
values: numpy.ndarray
|
|
181
|
-
Maximal float values, shape: (n_vars_float,)
|
|
182
|
-
|
|
183
|
-
"""
|
|
184
|
-
return [
|
|
185
|
-
self.max_spacing,
|
|
186
|
-
self.max_spacing,
|
|
187
|
-
self._halfspan[0] + self.min_spacing,
|
|
188
|
-
self._halfspan[1] + self.min_spacing,
|
|
189
|
-
90.0,
|
|
190
|
-
]
|
|
191
|
-
|
|
192
|
-
def opt2farm_vars_individual(self, vars_int, vars_float):
|
|
193
|
-
"""
|
|
194
|
-
Translates optimization variables to farm variables
|
|
195
|
-
|
|
196
|
-
Parameters
|
|
197
|
-
----------
|
|
198
|
-
vars_int: numpy.ndarray
|
|
199
|
-
The integer optimization variable values,
|
|
200
|
-
shape: (n_vars_int,)
|
|
201
|
-
vars_float: numpy.ndarray
|
|
202
|
-
The float optimization variable values,
|
|
203
|
-
shape: (n_vars_float,)
|
|
204
|
-
|
|
205
|
-
Returns
|
|
206
|
-
-------
|
|
207
|
-
farm_vars: dict
|
|
208
|
-
The foxes farm variables. Key: var name,
|
|
209
|
-
value: numpy.ndarray with values, shape:
|
|
210
|
-
(n_states, n_sel_turbines)
|
|
211
|
-
|
|
212
|
-
"""
|
|
213
|
-
|
|
214
|
-
dx, dy, ox, oy, a = vars_float
|
|
215
|
-
n_states = self.algo.n_states
|
|
216
|
-
nx = self._nrow
|
|
217
|
-
ny = self._nrow
|
|
218
|
-
|
|
219
|
-
a = np.deg2rad(a)
|
|
220
|
-
nax = np.array([np.cos(a), np.sin(a), 0.0], dtype=FC.DTYPE)
|
|
221
|
-
nay = np.cross(np.array([0.0, 0.0, 1.0], dtype=FC.DTYPE), nax)
|
|
222
|
-
x0 = self._xy0 + np.array([ox, oy], dtype=FC.DTYPE)
|
|
223
|
-
|
|
224
|
-
pts = np.zeros((n_states, nx, ny, 2), dtype=FC.DTYPE)
|
|
225
|
-
pts[:] = (
|
|
226
|
-
x0[None, None, None, :]
|
|
227
|
-
+ np.arange(nx)[None, :, None, None] * dx * nax[None, None, None, :2]
|
|
228
|
-
+ np.arange(ny)[None, None, :, None] * dy * nay[None, None, None, :2]
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
pts = pts.reshape(n_states, nx * ny, 2)
|
|
232
|
-
valid = self.farm.boundary.points_inside(pts.reshape(n_states * nx * ny, 2))
|
|
233
|
-
|
|
234
|
-
farm_vars = {
|
|
235
|
-
FV.X: pts[:, :, 0],
|
|
236
|
-
FV.Y: pts[:, :, 1],
|
|
237
|
-
FC.VALID: valid.reshape(n_states, nx * ny).astype(FC.DTYPE),
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return farm_vars
|
|
241
|
-
|
|
242
|
-
def opt2farm_vars_population(self, vars_int, vars_float, n_states):
|
|
243
|
-
"""
|
|
244
|
-
Translates optimization variables to farm variables
|
|
245
|
-
|
|
246
|
-
Parameters
|
|
247
|
-
----------
|
|
248
|
-
vars_int: numpy.ndarray
|
|
249
|
-
The integer optimization variable values,
|
|
250
|
-
shape: (n_pop, n_vars_int)
|
|
251
|
-
vars_float: numpy.ndarray
|
|
252
|
-
The float optimization variable values,
|
|
253
|
-
shape: (n_pop, n_vars_float)
|
|
254
|
-
n_states: int
|
|
255
|
-
The number of original (non-pop) states
|
|
256
|
-
|
|
257
|
-
Returns
|
|
258
|
-
-------
|
|
259
|
-
farm_vars: dict
|
|
260
|
-
The foxes farm variables. Key: var name,
|
|
261
|
-
value: numpy.ndarray with values, shape:
|
|
262
|
-
(n_pop, n_states, n_sel_turbines)
|
|
263
|
-
|
|
264
|
-
"""
|
|
265
|
-
n_pop = len(vars_float)
|
|
266
|
-
n_turbines = self.farm.n_turbines
|
|
267
|
-
dx = vars_float[:, 0]
|
|
268
|
-
dy = vars_float[:, 1]
|
|
269
|
-
ox = vars_float[:, 2]
|
|
270
|
-
oy = vars_float[:, 3]
|
|
271
|
-
nx = self._nrow
|
|
272
|
-
ny = self._nrow
|
|
273
|
-
a = vars_float[:, 4]
|
|
274
|
-
N = self._nturb
|
|
275
|
-
|
|
276
|
-
a = np.deg2rad(a)
|
|
277
|
-
nax = np.stack([np.cos(a), np.sin(a), np.zeros_like(a)], axis=-1)
|
|
278
|
-
naz = np.zeros_like(nax)
|
|
279
|
-
naz[..., 2] = 1
|
|
280
|
-
nay = np.cross(naz, nax)
|
|
281
|
-
|
|
282
|
-
pts = np.zeros((n_pop, n_states, nx, ny, 2), dtype=FC.DTYPE)
|
|
283
|
-
pts[:] = self._xy0[None, None, None, None, :]
|
|
284
|
-
pts[..., 0] += ox[:, None, None, None]
|
|
285
|
-
pts[..., 1] += oy[:, None, None, None]
|
|
286
|
-
pts[:] += (
|
|
287
|
-
np.arange(nx)[None, None, :, None, None]
|
|
288
|
-
* dx[:, None, None, None, None]
|
|
289
|
-
* nax[:, None, None, None, :2]
|
|
290
|
-
+ np.arange(ny)[None, None, None, :, None]
|
|
291
|
-
* dy[:, None, None, None, None]
|
|
292
|
-
* nay[:, None, None, None, :2]
|
|
293
|
-
)
|
|
294
|
-
|
|
295
|
-
qts = np.zeros((n_pop, n_states, n_turbines, 2))
|
|
296
|
-
qts[:, :N] = pts.reshape(n_pop, n_states, N, 2)
|
|
297
|
-
del pts
|
|
298
|
-
|
|
299
|
-
valid = self.farm.boundary.points_inside(
|
|
300
|
-
qts.reshape(n_pop * n_states * n_turbines, 2)
|
|
301
|
-
)
|
|
302
|
-
|
|
303
|
-
farm_vars = {
|
|
304
|
-
FV.X: qts[:, :, :, 0],
|
|
305
|
-
FV.Y: qts[:, :, :, 1],
|
|
306
|
-
FC.VALID: valid.reshape(n_pop, n_states, n_turbines).astype(FC.DTYPE),
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return farm_vars
|
|
310
|
-
|
|
311
|
-
def finalize_individual(self, vars_int, vars_float, verbosity=1):
|
|
312
|
-
"""
|
|
313
|
-
Finalization, given the champion data.
|
|
314
|
-
|
|
315
|
-
Parameters
|
|
316
|
-
----------
|
|
317
|
-
vars_int: np.array
|
|
318
|
-
The optimal integer variable values, shape: (n_vars_int,)
|
|
319
|
-
vars_float: np.array
|
|
320
|
-
The optimal float variable values, shape: (n_vars_float,)
|
|
321
|
-
verbosity: int
|
|
322
|
-
The verbosity level, 0 = silent
|
|
323
|
-
|
|
324
|
-
Returns
|
|
325
|
-
-------
|
|
326
|
-
problem_results: Any
|
|
327
|
-
The results of the variable application
|
|
328
|
-
to the problem
|
|
329
|
-
objs: np.array
|
|
330
|
-
The objective function values, shape: (n_objectives,)
|
|
331
|
-
cons: np.array
|
|
332
|
-
The constraints values, shape: (n_constraints,)
|
|
333
|
-
|
|
334
|
-
"""
|
|
335
|
-
farm_vars = self.opt2farm_vars_individual(vars_int, vars_float)
|
|
336
|
-
sel = np.where(farm_vars[FC.VALID][0])[0]
|
|
337
|
-
x = farm_vars[FV.X][0, sel]
|
|
338
|
-
y = farm_vars[FV.Y][0, sel]
|
|
339
|
-
|
|
340
|
-
self.farm.turbines = [t for i, t in enumerate(self.farm.turbines) if i in sel]
|
|
341
|
-
for i, t in enumerate(self.farm.turbines):
|
|
342
|
-
t.xy = np.array([x[i], y[i]], dtype=FC.DTYPE)
|
|
343
|
-
t.models = [m for m in t.models if m not in [self.name, self._mname]]
|
|
344
|
-
t.index = i
|
|
345
|
-
t.name = f"T{i}"
|
|
346
|
-
self.algo.update_n_turbines()
|
|
347
|
-
|
|
348
|
-
return FarmOptProblem.finalize_individual(
|
|
349
|
-
self, vars_int, vars_float, verbosity=1
|
|
350
|
-
)
|