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.

Files changed (33) hide show
  1. foxes/VERSION +1 -1
  2. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/METADATA +20 -116
  3. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/RECORD +7 -33
  4. foxes/opt/__init__.py +0 -9
  5. foxes/opt/constraints/__init__.py +0 -6
  6. foxes/opt/constraints/area_geometry.py +0 -214
  7. foxes/opt/constraints/min_dist.py +0 -239
  8. foxes/opt/core/__init__.py +0 -9
  9. foxes/opt/core/farm_constraint.py +0 -96
  10. foxes/opt/core/farm_objective.py +0 -97
  11. foxes/opt/core/farm_opt_problem.py +0 -346
  12. foxes/opt/core/farm_vars_problem.py +0 -219
  13. foxes/opt/core/pop_states.py +0 -206
  14. foxes/opt/objectives/__init__.py +0 -6
  15. foxes/opt/objectives/farm_vars.py +0 -323
  16. foxes/opt/objectives/max_n_turbines.py +0 -142
  17. foxes/opt/problems/__init__.py +0 -7
  18. foxes/opt/problems/layout/__init__.py +0 -9
  19. foxes/opt/problems/layout/farm_layout.py +0 -137
  20. foxes/opt/problems/layout/geom_layouts/__init__.py +0 -10
  21. foxes/opt/problems/layout/geom_layouts/constraints.py +0 -802
  22. foxes/opt/problems/layout/geom_layouts/geom_layout.py +0 -290
  23. foxes/opt/problems/layout/geom_layouts/geom_layout_gridded.py +0 -276
  24. foxes/opt/problems/layout/geom_layouts/geom_reggrid.py +0 -351
  25. foxes/opt/problems/layout/geom_layouts/geom_reggrids.py +0 -482
  26. foxes/opt/problems/layout/geom_layouts/objectives.py +0 -666
  27. foxes/opt/problems/layout/reggrids_layout.py +0 -417
  28. foxes/opt/problems/layout/regular_layout.py +0 -350
  29. foxes/opt/problems/opt_farm_vars.py +0 -586
  30. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/LICENSE +0 -0
  31. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/WHEEL +0 -0
  32. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/top_level.txt +0 -0
  33. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/zip-safe +0 -0
@@ -1,290 +0,0 @@
1
- import numpy as np
2
- import matplotlib.pyplot as plt
3
- from scipy.spatial.distance import cdist
4
- from iwopy import Problem
5
-
6
- import foxes.constants as FC
7
-
8
-
9
- class GeomLayout(Problem):
10
- """
11
- A layout within a boundary geometry, purely
12
- defined by geometrical optimization (no wakes).
13
-
14
- This optimization problem does not involve
15
- wind farms.
16
-
17
- Attributes
18
- ----------
19
- boundary: foxes.utils.geom2d.AreaGeometry
20
- The boundary geometry
21
- n_turbines: int
22
- The number of turbines in the layout
23
- min_dist: float
24
- The minimal distance between points
25
- D: float
26
- The diameter of circle fully within boundary
27
- calc_valid: bool
28
- Evaluate validity
29
-
30
- :group: opt.problems.layout.geom_layouts
31
-
32
- """
33
-
34
- def __init__(
35
- self,
36
- boundary,
37
- n_turbines,
38
- min_dist=None,
39
- D=None,
40
- calc_valid=None,
41
- ):
42
- """
43
- Constructor.
44
-
45
- Parameters
46
- ----------
47
- boundary: foxes.utils.geom2d.AreaGeometry
48
- The boundary geometry
49
- n_turbines: int
50
- The number of turbines in the layout
51
- min_dist: float, optional
52
- The minimal distance between points
53
- D: float, optional
54
- The diameter of circle fully within boundary
55
- calc_valid: bool, optional
56
- Evaluate validity
57
-
58
- """
59
- super().__init__(name="geom_reg_grids")
60
-
61
- self.boundary = boundary
62
- self.n_turbines = n_turbines
63
- self.D = D
64
- self.min_dist = min_dist
65
- self.calc_valid = calc_valid
66
- if calc_valid is None:
67
- self.calc_valid = min_dist is not None or D is not None
68
-
69
- self._X = [f"x{i}" for i in range(self.n_turbines)]
70
- self._Y = [f"y{i}" for i in range(self.n_turbines)]
71
-
72
- def initialize(self, verbosity=1):
73
- """
74
- Initialize the object.
75
-
76
- Parameters
77
- ----------
78
- verbosity: int
79
- The verbosity level, 0 = silent
80
-
81
- """
82
- super().initialize(verbosity)
83
- self.apply_individual(self.initial_values_int(), self.initial_values_float())
84
-
85
- def var_names_float(self):
86
- """
87
- The names of float variables.
88
-
89
- Returns
90
- -------
91
- names: list of str
92
- The names of the float variables
93
-
94
- """
95
- return list(np.array([self._X, self._Y]).T.flat)
96
-
97
- def initial_values_float(self):
98
- """
99
- The initial values of the float variables.
100
-
101
- Returns
102
- -------
103
- values: numpy.ndarray
104
- Initial float values, shape: (n_vars_float,)
105
-
106
- """
107
- pmin = self.boundary.p_min()
108
- pmax = self.boundary.p_max()
109
- pc = 0.5 * (pmin + pmax)
110
- delta = 0.8 * (pmax - pmin)
111
-
112
- vals = np.zeros((self.n_turbines, 2), dtype=FC.DTYPE)
113
- vals[:] = pc[None, :] - 0.5 * delta[None, :]
114
- vals[:] += (
115
- np.arange(self.n_turbines)[:, None] * delta[None, :] / (self.n_turbines - 1)
116
- )
117
-
118
- return vals.reshape(self.n_turbines * 2)
119
-
120
- def min_values_float(self):
121
- """
122
- The minimal values of the float variables.
123
-
124
- Use -numpy.inf for unbounded.
125
-
126
- Returns
127
- -------
128
- values: numpy.ndarray
129
- Minimal float values, shape: (n_vars_float,)
130
-
131
- """
132
- vals = np.zeros((self.n_turbines, 2), dtype=FC.DTYPE)
133
- vals[:] = self.boundary.p_min()[None, :]
134
- return vals.reshape(self.n_turbines * 2)
135
-
136
- def max_values_float(self):
137
- """
138
- The maximal values of the float variables.
139
-
140
- Use numpy.inf for unbounded.
141
-
142
- Returns
143
- -------
144
- values: numpy.ndarray
145
- Maximal float values, shape: (n_vars_float,)
146
-
147
- """
148
- vals = np.zeros((self.n_turbines, 2), dtype=FC.DTYPE)
149
- vals[:] = self.boundary.p_max()[None, :]
150
- return vals.reshape(self.n_turbines * 2)
151
-
152
- def apply_individual(self, vars_int, vars_float):
153
- """
154
- Apply new variables to the problem.
155
-
156
- Parameters
157
- ----------
158
- vars_int: np.array
159
- The integer variable values, shape: (n_vars_int,)
160
- vars_float: np.array
161
- The float variable values, shape: (n_vars_float,)
162
-
163
- Returns
164
- -------
165
- problem_results: Any
166
- The results of the variable application
167
- to the problem
168
-
169
- """
170
- xy = vars_float.reshape(self.n_turbines, 2)
171
-
172
- valid = None
173
- if self.calc_valid:
174
- if self.D is None:
175
- valid = self.boundary.points_inside(xy)
176
- else:
177
- valid = self.boundary.points_inside(xy) & (
178
- self.boundary.points_distance(xy) >= self.D / 2
179
- )
180
-
181
- if self.min_dist is not None:
182
- dists = cdist(xy, xy)
183
- np.fill_diagonal(dists, 1e20)
184
- dists = np.min(dists, axis=1)
185
- valid[dists < self.min_dist] = False
186
-
187
- return xy, valid
188
-
189
- def apply_population(self, vars_int, vars_float):
190
- """
191
- Apply new variables to the problem,
192
- for a whole population.
193
-
194
- Parameters
195
- ----------
196
- vars_int: np.array
197
- The integer variable values, shape: (n_pop, n_vars_int)
198
- vars_float: np.array
199
- The float variable values, shape: (n_pop, n_vars_float)
200
-
201
- Returns
202
- -------
203
- problem_results: Any
204
- The results of the variable application
205
- to the problem
206
-
207
- """
208
- n_pop = vars_float.shape[0]
209
- xy = vars_float.reshape(n_pop, self.n_turbines, 2)
210
-
211
- valid = None
212
- if self.calc_valid:
213
- qts = xy.reshape(n_pop * self.n_turbines, 2)
214
- if self.D is None:
215
- valid = self.boundary.points_inside(qts)
216
- else:
217
- valid = self.boundary.points_inside(qts) & (
218
- self.boundary.points_distance(qts) >= self.D / 2
219
- )
220
- valid = valid.reshape(n_pop, self.n_turbines)
221
-
222
- if self.min_dist is not None:
223
- for pi in range(n_pop):
224
- dists = cdist(xy[pi], xy[pi])
225
- np.fill_diagonal(dists, 1e20)
226
- dists = np.min(dists, axis=1)
227
- valid[pi, dists < self.min_dist] = False
228
-
229
- return xy, valid
230
-
231
- def get_fig(
232
- self, xy=None, valid=None, ax=None, title=None, true_circle=True, **bargs
233
- ):
234
- """
235
- Return plotly figure axis.
236
-
237
- Parameters
238
- ----------
239
- xy: numpy.ndarary, optional
240
- The xy coordinate array, shape: (n_points, 2)
241
- valid: numpy.ndarray, optional
242
- Boolean array of validity, shape: (n_points,)
243
- ax: pyplot.Axis, optional
244
- The figure axis
245
- title: str, optional
246
- The figure title
247
- true_circle: bool
248
- Draw points as circles with diameter self.D
249
- bars: dict, optional
250
- The boundary plot arguments
251
-
252
- Returns
253
- -------
254
- ax: pyplot.Axis
255
- The figure axis
256
-
257
- """
258
- if ax is None:
259
- __, ax = plt.subplots()
260
-
261
- hbargs = {"fill_mode": "inside_lightgray"}
262
- hbargs.update(bargs)
263
- self.boundary.add_to_figure(ax, **hbargs)
264
-
265
- if xy is not None:
266
- if valid is not None:
267
- xy = xy[valid]
268
- if not true_circle or self.D is None:
269
- ax.scatter(xy[:, 0], xy[:, 1], color="orange")
270
- else:
271
- for x, y in xy:
272
- ax.add_patch(
273
- plt.Circle((x, y), self.D / 2, color="blue", fill=True)
274
- )
275
-
276
- ax.set_aspect("equal", adjustable="box")
277
- ax.set_xlabel("x [m]")
278
- ax.set_ylabel("y [m]")
279
-
280
- if title is None:
281
- if xy is None:
282
- title = f"Optimization area"
283
- else:
284
- l = len(xy) if xy is not None else 0
285
- dists = cdist(xy, xy)
286
- np.fill_diagonal(dists, 1e20)
287
- title = f"N = {l}, min_dist = {np.min(dists):.1f} m"
288
- ax.set_title(title)
289
-
290
- return ax
@@ -1,276 +0,0 @@
1
- import numpy as np
2
- import matplotlib.pyplot as plt
3
- from scipy.spatial.distance import cdist
4
- from iwopy import Problem
5
-
6
- import foxes.constants as FC
7
-
8
-
9
- class GeomLayoutGridded(Problem):
10
- """
11
- A layout within a boundary geometry, purely
12
- defined by geometrical optimization (no wakes),
13
- on a fixes background point grid.
14
-
15
- This optimization problem does not involve
16
- wind farms.
17
-
18
- Attributes
19
- ----------
20
- boundary: foxes.utils.geom2d.AreaGeometry
21
- The boundary geometry
22
- n_turbines: int
23
- The number of turbines in the layout
24
- grid_spacing: float
25
- The background grid spacing
26
- min_dist: float
27
- The minimal distance between points
28
- D: float
29
- The diameter of circle fully within boundary
30
-
31
- :group: opt.problems.layout.geom_layouts
32
-
33
- """
34
-
35
- def __init__(
36
- self,
37
- boundary,
38
- n_turbines,
39
- grid_spacing,
40
- min_dist=None,
41
- D=None,
42
- ):
43
- """
44
- Constructor.
45
-
46
- Parameters
47
- ----------
48
- boundary: foxes.utils.geom2d.AreaGeometry
49
- The boundary geometry
50
- n_turbines: int
51
- The number of turbines in the layout
52
- grid_spacing: float
53
- The background grid spacing
54
- min_dist: float, optional
55
- The minimal distance between points
56
- D: float, optional
57
- The diameter of circle fully within boundary
58
-
59
- """
60
- super().__init__(name="geom_reg_grids")
61
-
62
- self.boundary = boundary
63
- self.n_turbines = n_turbines
64
- self.grid_spacing = grid_spacing
65
- self.D = D
66
- self.min_dist = min_dist
67
-
68
- self._I = [f"i{i}" for i in range(self.n_turbines)]
69
-
70
- def initialize(self, verbosity=1):
71
- """
72
- Initialize the object.
73
-
74
- Parameters
75
- ----------
76
- verbosity: int
77
- The verbosity level, 0 = silent
78
-
79
- """
80
- super().initialize(verbosity)
81
-
82
- pmin = self.boundary.p_min()
83
- pmax = self.boundary.p_max() + self.grid_spacing
84
- self._pts = np.stack(
85
- np.meshgrid(
86
- np.arange(pmin[0], pmax[0], self.grid_spacing),
87
- np.arange(pmin[1], pmax[1], self.grid_spacing),
88
- indexing="ij",
89
- ),
90
- axis=-1,
91
- )
92
- nx, ny = self._pts.shape[:2]
93
- self._pts = self._pts.reshape(nx * ny, 2)
94
-
95
- if self.D is None:
96
- valid = self.boundary.points_inside(self._pts)
97
- else:
98
- valid = self.boundary.points_inside(self._pts) & (
99
- self.boundary.points_distance(self._pts) >= self.D / 2
100
- )
101
- self._pts = self._pts[valid]
102
- self._N = len(self._pts)
103
-
104
- if verbosity > 0:
105
- print(f"Problem '{self.name}': n_bgd_pts = {self._N}")
106
-
107
- if self._N < self.n_turbines:
108
- raise ValueError(
109
- f"Problem '{self.name}': Background grid only provides {self._N} points for {self.n_turbines} turbines"
110
- )
111
-
112
- self.apply_individual(self.initial_values_int(), self.initial_values_float())
113
-
114
- def var_names_int(self):
115
- """
116
- The names of int variables.
117
-
118
- Returns
119
- -------
120
- names: list of str
121
- The names of the int variables
122
-
123
- """
124
- return self._I
125
-
126
- def initial_values_int(self):
127
- """
128
- The initial values of the int variables.
129
-
130
- Returns
131
- -------
132
- values: numpy.ndarray
133
- Initial int values, shape: (n_vars_int,)
134
-
135
- """
136
- return np.arange(self.n_turbines, dtype=FC.ITYPE)
137
-
138
- def min_values_int(self):
139
- """
140
- The minimal values of the int variables.
141
-
142
- Returns
143
- -------
144
- values: numpy.ndarray
145
- Minimal int values, shape: (n_vars_int,)
146
-
147
- """
148
- return np.zeros(self.n_turbines, dtype=FC.ITYPE)
149
-
150
- def max_values_int(self):
151
- """
152
- The maximal values of the int variables.
153
-
154
- Returns
155
- -------
156
- values: numpy.ndarray
157
- Maximal int values, shape: (n_vars_int,)
158
-
159
- """
160
- return np.full(self.n_turbines, self._N - 1, dtype=FC.ITYPE)
161
-
162
- def apply_individual(self, vars_int, vars_float):
163
- """
164
- Apply new variables to the problem.
165
-
166
- Parameters
167
- ----------
168
- vars_int: np.array
169
- The integer variable values, shape: (n_vars_int,)
170
- vars_float: np.array
171
- The float variable values, shape: (n_vars_float,)
172
-
173
- Returns
174
- -------
175
- problem_results: Any
176
- The results of the variable application
177
- to the problem
178
-
179
- """
180
- xy = self._pts[vars_int.astype(FC.ITYPE)]
181
- __, ui = np.unique(vars_int, return_index=True)
182
- valid = np.zeros(self.n_turbines, dtype=bool)
183
- valid[ui] = True
184
- return xy, valid
185
-
186
- def apply_population(self, vars_int, vars_float):
187
- """
188
- Apply new variables to the problem,
189
- for a whole population.
190
-
191
- Parameters
192
- ----------
193
- vars_int: np.array
194
- The integer variable values, shape: (n_pop, n_vars_int)
195
- vars_float: np.array
196
- The float variable values, shape: (n_pop, n_vars_float)
197
-
198
- Returns
199
- -------
200
- problem_results: Any
201
- The results of the variable application
202
- to the problem
203
-
204
- """
205
- n_pop = vars_int.shape[0]
206
-
207
- vint = vars_int.reshape(n_pop * self.n_turbines).astype(FC.ITYPE)
208
- xy = self._pts[vint, :].reshape(n_pop, self.n_turbines, 2)
209
-
210
- valid = np.zeros((n_pop, self.n_turbines), dtype=bool)
211
- for pi in range(n_pop):
212
- __, ui = np.unique(vars_int[pi], return_index=True)
213
- valid[pi, ui] = True
214
-
215
- return xy, valid
216
-
217
- def get_fig(
218
- self, xy=None, valid=None, ax=None, title=None, true_circle=True, **bargs
219
- ):
220
- """
221
- Return plotly figure axis.
222
-
223
- Parameters
224
- ----------
225
- xy: numpy.ndarary, optional
226
- The xy coordinate array, shape: (n_points, 2)
227
- valid: numpy.ndarray, optional
228
- Boolean array of validity, shape: (n_points,)
229
- ax: pyplot.Axis, optional
230
- The figure axis
231
- title: str, optional
232
- The figure title
233
- true_circle: bool
234
- Draw points as circles with diameter self.D
235
- bars: dict, optional
236
- The boundary plot arguments
237
-
238
- Returns
239
- -------
240
- ax: pyplot.Axis
241
- The figure axis
242
-
243
- """
244
- if ax is None:
245
- __, ax = plt.subplots()
246
-
247
- hbargs = {"fill_mode": "inside_lightgray"}
248
- hbargs.update(bargs)
249
- self.boundary.add_to_figure(ax, **hbargs)
250
-
251
- if xy is not None:
252
- if valid is not None:
253
- xy = xy[valid]
254
- if not true_circle or self.D is None:
255
- ax.scatter(xy[:, 0], xy[:, 1], color="orange")
256
- else:
257
- for x, y in xy:
258
- ax.add_patch(
259
- plt.Circle((x, y), self.D / 2, color="blue", fill=True)
260
- )
261
-
262
- ax.set_aspect("equal", adjustable="box")
263
- ax.set_xlabel("x [m]")
264
- ax.set_ylabel("y [m]")
265
-
266
- if title is None:
267
- if xy is None:
268
- title = f"Optimization area"
269
- else:
270
- l = len(xy) if xy is not None else 0
271
- dists = cdist(xy, xy)
272
- np.fill_diagonal(dists, 1e20)
273
- title = f"N = {l}, min_dist = {np.min(dists):.1f} m"
274
- ax.set_title(title)
275
-
276
- return ax