foxes 0.6.1__py3-none-any.whl → 0.7__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/algorithms/downwind/downwind.py +131 -65
- foxes/algorithms/downwind/models/__init__.py +2 -1
- foxes/algorithms/downwind/models/farm_wakes_calc.py +87 -55
- foxes/algorithms/downwind/models/init_farm_data.py +134 -0
- foxes/algorithms/downwind/models/point_wakes_calc.py +54 -65
- foxes/algorithms/downwind/models/{calc_order.py → reorder_farm_output.py} +28 -26
- foxes/algorithms/iterative/iterative.py +100 -51
- foxes/algorithms/iterative/models/convergence.py +3 -3
- foxes/algorithms/iterative/models/farm_wakes_calc.py +55 -48
- foxes/algorithms/sequential/models/seq_state.py +7 -6
- foxes/algorithms/sequential/sequential.py +81 -44
- foxes/constants.py +33 -18
- foxes/core/__init__.py +2 -2
- foxes/core/algorithm.py +31 -12
- foxes/core/data.py +335 -41
- foxes/core/data_calc_model.py +27 -23
- foxes/core/farm_controller.py +27 -28
- foxes/core/farm_data_model.py +26 -4
- foxes/core/model.py +186 -129
- foxes/core/partial_wakes_model.py +84 -81
- foxes/core/point_data_model.py +51 -18
- foxes/core/rotor_model.py +59 -77
- foxes/core/states.py +6 -6
- foxes/core/turbine_model.py +4 -4
- foxes/core/turbine_type.py +24 -0
- foxes/core/vertical_profile.py +3 -3
- foxes/core/wake_frame.py +91 -50
- foxes/core/wake_model.py +74 -43
- foxes/core/wake_superposition.py +29 -26
- foxes/input/farm_layout/__init__.py +1 -0
- foxes/input/farm_layout/from_random.py +49 -0
- foxes/input/states/__init__.py +1 -1
- foxes/input/states/create/__init__.py +1 -0
- foxes/input/states/create/random_abl_states.py +6 -2
- foxes/input/states/create/random_timeseries.py +56 -0
- foxes/input/states/field_data_nc.py +12 -8
- foxes/input/states/multi_height.py +24 -14
- foxes/input/states/scan_ws.py +13 -17
- foxes/input/states/single.py +28 -20
- foxes/input/states/states_table.py +22 -18
- foxes/models/axial_induction_models/betz.py +1 -1
- foxes/models/farm_models/turbine2farm.py +2 -2
- foxes/models/model_book.py +40 -14
- foxes/models/partial_wakes/__init__.py +2 -2
- foxes/models/partial_wakes/axiwake.py +73 -200
- foxes/models/partial_wakes/centre.py +40 -0
- foxes/models/partial_wakes/grid.py +7 -63
- foxes/models/partial_wakes/rotor_points.py +53 -147
- foxes/models/partial_wakes/segregated.py +158 -0
- foxes/models/partial_wakes/top_hat.py +88 -196
- foxes/models/point_models/set_uniform_data.py +4 -4
- foxes/models/point_models/tke2ti.py +4 -4
- foxes/models/point_models/wake_deltas.py +4 -4
- foxes/models/rotor_models/centre.py +15 -19
- foxes/models/rotor_models/grid.py +2 -1
- foxes/models/rotor_models/levels.py +2 -1
- foxes/models/turbine_models/__init__.py +0 -1
- foxes/models/turbine_models/calculator.py +11 -7
- foxes/models/turbine_models/kTI_model.py +13 -11
- foxes/models/turbine_models/lookup_table.py +22 -9
- foxes/models/turbine_models/power_mask.py +81 -51
- foxes/models/turbine_models/rotor_centre_calc.py +17 -20
- foxes/models/turbine_models/sector_management.py +5 -6
- foxes/models/turbine_models/set_farm_vars.py +49 -20
- foxes/models/turbine_models/table_factors.py +5 -5
- foxes/models/turbine_models/thrust2ct.py +9 -5
- foxes/models/turbine_models/yaw2yawm.py +7 -13
- foxes/models/turbine_models/yawm2yaw.py +7 -11
- foxes/models/turbine_types/PCt_file.py +84 -3
- foxes/models/turbine_types/PCt_from_two.py +7 -3
- foxes/models/turbine_types/null_type.py +2 -2
- foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -2
- foxes/models/turbine_types/wsti2PCt_from_two.py +6 -2
- foxes/models/wake_frames/farm_order.py +26 -22
- foxes/models/wake_frames/rotor_wd.py +32 -31
- foxes/models/wake_frames/seq_dynamic_wakes.py +112 -64
- foxes/models/wake_frames/streamlines.py +51 -47
- foxes/models/wake_frames/timelines.py +59 -47
- foxes/models/wake_frames/yawed_wakes.py +63 -40
- foxes/models/wake_models/axisymmetric.py +31 -35
- foxes/models/wake_models/dist_sliced.py +50 -56
- foxes/models/wake_models/gaussian.py +33 -35
- foxes/models/wake_models/induction/rankine_half_body.py +79 -87
- foxes/models/wake_models/induction/rathmann.py +56 -63
- foxes/models/wake_models/induction/self_similar.py +59 -62
- foxes/models/wake_models/ti/crespo_hernandez.py +83 -74
- foxes/models/wake_models/ti/iec_ti.py +65 -75
- foxes/models/wake_models/top_hat.py +60 -69
- foxes/models/wake_models/wake_mirror.py +49 -54
- foxes/models/wake_models/wind/bastankhah14.py +44 -66
- foxes/models/wake_models/wind/bastankhah16.py +84 -111
- foxes/models/wake_models/wind/jensen.py +67 -89
- foxes/models/wake_models/wind/turbopark.py +93 -133
- foxes/models/wake_superpositions/ti_linear.py +33 -27
- foxes/models/wake_superpositions/ti_max.py +33 -27
- foxes/models/wake_superpositions/ti_pow.py +35 -27
- foxes/models/wake_superpositions/ti_quadratic.py +33 -27
- foxes/models/wake_superpositions/ws_linear.py +39 -32
- foxes/models/wake_superpositions/ws_max.py +40 -33
- foxes/models/wake_superpositions/ws_pow.py +39 -32
- foxes/models/wake_superpositions/ws_product.py +35 -28
- foxes/models/wake_superpositions/ws_quadratic.py +39 -32
- foxes/opt/constraints/min_dist.py +1 -1
- foxes/opt/objectives/farm_vars.py +1 -1
- foxes/opt/problems/layout/farm_layout.py +38 -97
- foxes/output/__init__.py +1 -0
- foxes/output/farm_results_eval.py +1 -1
- foxes/output/flow_plots_2d/flow_plots.py +2 -0
- foxes/output/flow_plots_2d/get_fig.py +2 -0
- foxes/output/grids.py +1 -1
- foxes/output/rose_plot.py +3 -3
- foxes/output/rotor_point_plots.py +117 -0
- foxes/output/turbine_type_curves.py +2 -2
- foxes/utils/__init__.py +2 -1
- foxes/utils/load.py +29 -0
- foxes/utils/random_xy.py +56 -0
- foxes/utils/runners/runners.py +13 -1
- foxes/utils/windrose_plot.py +1 -1
- foxes/variables.py +10 -0
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/METADATA +13 -7
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/RECORD +126 -122
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/WHEEL +1 -1
- foxes/models/partial_wakes/distsliced.py +0 -322
- foxes/models/partial_wakes/mapped.py +0 -252
- foxes/models/turbine_models/set_XYHD.py +0 -130
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/LICENSE +0 -0
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/top_level.txt +0 -0
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/zip-safe +0 -0
|
@@ -11,7 +11,7 @@ def create_random_abl_states(
|
|
|
11
11
|
"""
|
|
12
12
|
Create random abl states.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Parameters
|
|
15
15
|
----------
|
|
16
16
|
n_states: int
|
|
17
17
|
The number of states
|
|
@@ -32,7 +32,7 @@ def create_random_abl_states(
|
|
|
32
32
|
data: pandas.DataFrame
|
|
33
33
|
The created states data
|
|
34
34
|
|
|
35
|
-
:group: input.states
|
|
35
|
+
:group: input.states.create
|
|
36
36
|
|
|
37
37
|
"""
|
|
38
38
|
|
|
@@ -70,6 +70,10 @@ def write_random_abl_states(
|
|
|
70
70
|
**kwargs
|
|
71
71
|
):
|
|
72
72
|
"""
|
|
73
|
+
Writes random abl states to file
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
73
77
|
file_path: str
|
|
74
78
|
Path to the file
|
|
75
79
|
n_states: int
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
import foxes.variables as FV
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def random_timseries_data(
|
|
8
|
+
n_times,
|
|
9
|
+
data_ranges=None,
|
|
10
|
+
start_time="2000-01-01 00:00:00",
|
|
11
|
+
freq="h",
|
|
12
|
+
seed=None,
|
|
13
|
+
iname="Time",
|
|
14
|
+
):
|
|
15
|
+
"""
|
|
16
|
+
Creates random uniform timeseries data
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
n_times: int
|
|
21
|
+
The number of time steps
|
|
22
|
+
data_ranges: dict, optional
|
|
23
|
+
The data ranges. Key: variable name,
|
|
24
|
+
value: tuple, [min, max) values
|
|
25
|
+
start_time: str
|
|
26
|
+
The first time stamp in the series
|
|
27
|
+
freq: str
|
|
28
|
+
The time period range frequency
|
|
29
|
+
seed: int, optional
|
|
30
|
+
The random seed
|
|
31
|
+
iname: str
|
|
32
|
+
The index name
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
sdata: pandas.DataFrame
|
|
37
|
+
The timeseries data
|
|
38
|
+
|
|
39
|
+
:group: input.states.create
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
if seed:
|
|
43
|
+
np.random.seed(seed)
|
|
44
|
+
|
|
45
|
+
dranges = {FV.WS: (0.0, 30.0), FV.WD: (0.0, 360.0)}
|
|
46
|
+
if data_ranges:
|
|
47
|
+
dranges.update(data_ranges)
|
|
48
|
+
|
|
49
|
+
times = pd.period_range(start=start_time, periods=n_times, freq=freq)
|
|
50
|
+
times = times.astype(str).astype("datetime64[ns]")
|
|
51
|
+
sdata = pd.DataFrame(
|
|
52
|
+
index=times,
|
|
53
|
+
data={v: np.random.uniform(d[0], d[1], n_times) for v, d in dranges.items()},
|
|
54
|
+
)
|
|
55
|
+
sdata.index.name = iname
|
|
56
|
+
return sdata
|
|
@@ -421,7 +421,7 @@ class FieldDataNC(States):
|
|
|
421
421
|
"""
|
|
422
422
|
return self._weights
|
|
423
423
|
|
|
424
|
-
def calculate(self, algo, mdata, fdata,
|
|
424
|
+
def calculate(self, algo, mdata, fdata, tdata):
|
|
425
425
|
""" "
|
|
426
426
|
The main model calculation.
|
|
427
427
|
|
|
@@ -432,22 +432,26 @@ class FieldDataNC(States):
|
|
|
432
432
|
----------
|
|
433
433
|
algo: foxes.core.Algorithm
|
|
434
434
|
The calculation algorithm
|
|
435
|
-
mdata: foxes.core.
|
|
435
|
+
mdata: foxes.core.MData
|
|
436
436
|
The model data
|
|
437
|
-
fdata: foxes.core.
|
|
437
|
+
fdata: foxes.core.FData
|
|
438
438
|
The farm data
|
|
439
|
-
|
|
440
|
-
The point data
|
|
439
|
+
tdata: foxes.core.TData
|
|
440
|
+
The target point data
|
|
441
441
|
|
|
442
442
|
Returns
|
|
443
443
|
-------
|
|
444
444
|
results: dict
|
|
445
445
|
The resulting data, keys: output variable str.
|
|
446
|
-
Values: numpy.ndarray with shape
|
|
446
|
+
Values: numpy.ndarray with shape
|
|
447
|
+
(n_states, n_targets, n_tpoints)
|
|
447
448
|
|
|
448
449
|
"""
|
|
449
450
|
# prepare:
|
|
450
|
-
|
|
451
|
+
n_states = tdata.n_states
|
|
452
|
+
n_targets = tdata.n_targets
|
|
453
|
+
n_tpoints = tdata.n_tpoints
|
|
454
|
+
points = tdata[FC.TARGETS].reshape(n_states, n_targets * n_tpoints, 3)
|
|
451
455
|
n_pts = points.shape[1]
|
|
452
456
|
n_states = fdata.n_states
|
|
453
457
|
|
|
@@ -571,4 +575,4 @@ class FieldDataNC(States):
|
|
|
571
575
|
(n_states, n_pts), self.fixed_vars[v], dtype=FC.DTYPE
|
|
572
576
|
)
|
|
573
577
|
|
|
574
|
-
return out
|
|
578
|
+
return {v: d.reshape(n_states, n_targets, n_tpoints) for v, d in out.items()}
|
|
@@ -192,13 +192,13 @@ class MultiHeightStates(States):
|
|
|
192
192
|
isorg = False
|
|
193
193
|
else:
|
|
194
194
|
isorg = True
|
|
195
|
+
data = self.data_source
|
|
195
196
|
|
|
196
197
|
if self.states_sel is not None:
|
|
197
198
|
data = data.iloc[self.states_sel]
|
|
198
199
|
elif self.states_loc is not None:
|
|
199
200
|
data = data.loc[self.states_loc]
|
|
200
|
-
|
|
201
|
-
data = data
|
|
201
|
+
|
|
202
202
|
self._N = len(data.index)
|
|
203
203
|
self._inds = data.index.to_numpy()
|
|
204
204
|
|
|
@@ -308,7 +308,7 @@ class MultiHeightStates(States):
|
|
|
308
308
|
"""
|
|
309
309
|
return self._weights
|
|
310
310
|
|
|
311
|
-
def calculate(self, algo, mdata, fdata,
|
|
311
|
+
def calculate(self, algo, mdata, fdata, tdata):
|
|
312
312
|
""" "
|
|
313
313
|
The main model calculation.
|
|
314
314
|
|
|
@@ -319,24 +319,29 @@ class MultiHeightStates(States):
|
|
|
319
319
|
----------
|
|
320
320
|
algo: foxes.core.Algorithm
|
|
321
321
|
The calculation algorithm
|
|
322
|
-
mdata: foxes.core.
|
|
322
|
+
mdata: foxes.core.MData
|
|
323
323
|
The model data
|
|
324
|
-
fdata: foxes.core.
|
|
324
|
+
fdata: foxes.core.FData
|
|
325
325
|
The farm data
|
|
326
|
-
|
|
327
|
-
The point data
|
|
326
|
+
tdata: foxes.core.TData
|
|
327
|
+
The target point data
|
|
328
328
|
|
|
329
329
|
Returns
|
|
330
330
|
-------
|
|
331
331
|
results: dict
|
|
332
332
|
The resulting data, keys: output variable str.
|
|
333
|
-
Values: numpy.ndarray with shape
|
|
333
|
+
Values: numpy.ndarray with shape
|
|
334
|
+
(n_states, n_targets, n_tpoints)
|
|
334
335
|
|
|
335
336
|
"""
|
|
337
|
+
n_states = tdata.n_states
|
|
338
|
+
n_targets = tdata.n_targets
|
|
339
|
+
n_tpoints = tdata.n_tpoints
|
|
336
340
|
h = mdata[self.H]
|
|
337
|
-
z =
|
|
341
|
+
z = tdata[FC.TARGETS][..., 2].reshape(n_states, n_targets * n_tpoints)
|
|
338
342
|
n_h = len(h)
|
|
339
343
|
vrs = list(mdata[self.VARS])
|
|
344
|
+
n_vars = len(vrs)
|
|
340
345
|
|
|
341
346
|
coeffs = np.zeros((n_h, n_h), dtype=FC.DTYPE)
|
|
342
347
|
np.fill_diagonal(coeffs, 1.0)
|
|
@@ -364,24 +369,29 @@ class MultiHeightStates(States):
|
|
|
364
369
|
raise KeyError(
|
|
365
370
|
f"States '{self.name}': Found variable '{FV.WD}', but missing variable '{FV.WS}'"
|
|
366
371
|
)
|
|
367
|
-
uv = np.einsum("shd,sph->spd", uvh, ires)
|
|
372
|
+
uv = np.einsum("shd,sph->spd", uvh, ires).reshape(
|
|
373
|
+
n_states, n_targets, n_tpoints, 2
|
|
374
|
+
)
|
|
368
375
|
del uvh
|
|
369
376
|
|
|
370
|
-
ires = np.einsum("svh,sph->
|
|
377
|
+
ires = np.einsum("svh,sph->vsp", mdata[self.DATA], ires).reshape(
|
|
378
|
+
n_vars, n_states, n_targets, n_tpoints
|
|
379
|
+
)
|
|
371
380
|
|
|
372
381
|
results = {}
|
|
373
382
|
for v in self.ovars:
|
|
374
|
-
results[v] = pdata[v]
|
|
375
383
|
if has_wd and v == FV.WD:
|
|
376
384
|
results[v] = uv2wd(uv, axis=-1)
|
|
377
385
|
elif has_wd and v == FV.WS:
|
|
378
386
|
results[v] = np.linalg.norm(uv, axis=-1)
|
|
379
387
|
elif v in self.fixed_vars:
|
|
388
|
+
results[v] = np.zeros((n_states, n_targets, n_tpoints), dtype=FC.DTYPE)
|
|
380
389
|
results[v][:] = self.fixed_vars[v]
|
|
381
390
|
elif v in self._solo.keys():
|
|
382
|
-
results[v]
|
|
391
|
+
results[v] = np.zeros((n_states, n_targets, n_tpoints), dtype=FC.DTYPE)
|
|
392
|
+
results[v][:] = mdata[self.var(v)][:, None, None]
|
|
383
393
|
else:
|
|
384
|
-
results[v] = ires[
|
|
394
|
+
results[v] = ires[vrs.index(v)]
|
|
385
395
|
|
|
386
396
|
return results
|
|
387
397
|
|
foxes/input/states/scan_ws.py
CHANGED
|
@@ -129,7 +129,7 @@ class ScanWS(States):
|
|
|
129
129
|
"""
|
|
130
130
|
return np.full((self.N, algo.n_turbines), 1.0 / self.N, dtype=FC.DTYPE)
|
|
131
131
|
|
|
132
|
-
def calculate(self, algo, mdata, fdata,
|
|
132
|
+
def calculate(self, algo, mdata, fdata, tdata):
|
|
133
133
|
""" "
|
|
134
134
|
The main model calculation.
|
|
135
135
|
|
|
@@ -140,33 +140,29 @@ class ScanWS(States):
|
|
|
140
140
|
----------
|
|
141
141
|
algo: foxes.core.Algorithm
|
|
142
142
|
The calculation algorithm
|
|
143
|
-
mdata: foxes.core.
|
|
143
|
+
mdata: foxes.core.MData
|
|
144
144
|
The model data
|
|
145
|
-
fdata: foxes.core.
|
|
145
|
+
fdata: foxes.core.FData
|
|
146
146
|
The farm data
|
|
147
|
-
|
|
148
|
-
The point data
|
|
147
|
+
tdata: foxes.core.TData
|
|
148
|
+
The target point data
|
|
149
149
|
|
|
150
150
|
Returns
|
|
151
151
|
-------
|
|
152
152
|
results: dict
|
|
153
153
|
The resulting data, keys: output variable str.
|
|
154
|
-
Values: numpy.ndarray with shape
|
|
154
|
+
Values: numpy.ndarray with shape
|
|
155
|
+
(n_states, n_targets, n_tpoints)
|
|
155
156
|
|
|
156
157
|
"""
|
|
157
|
-
|
|
158
|
+
tdata[FV.WS] = np.zeros_like(tdata[FC.TARGETS][..., 0])
|
|
159
|
+
tdata[FV.WS][:] = mdata[self.WS][:, None, None]
|
|
158
160
|
|
|
159
161
|
if self.wd is not None:
|
|
160
|
-
|
|
161
|
-
(pdata.n_states, pdata.n_points), self.wd, dtype=FC.DTYPE
|
|
162
|
-
)
|
|
162
|
+
tdata[FV.WD] = np.full_like(tdata[FV.WS], self.wd)
|
|
163
163
|
if self.ti is not None:
|
|
164
|
-
|
|
165
|
-
(pdata.n_states, pdata.n_points), self.ti, dtype=FC.DTYPE
|
|
166
|
-
)
|
|
164
|
+
tdata[FV.TI] = np.full_like(tdata[FV.WS], self.ti)
|
|
167
165
|
if self.rho is not None:
|
|
168
|
-
|
|
169
|
-
(pdata.n_states, pdata.n_points), self.rho, dtype=FC.DTYPE
|
|
170
|
-
)
|
|
166
|
+
tdata[FV.RHO] = np.full_like(tdata[FV.WS], self.rho)
|
|
171
167
|
|
|
172
|
-
return {v:
|
|
168
|
+
return {v: tdata[v] for v in self.output_point_vars(algo)}
|
foxes/input/states/single.py
CHANGED
|
@@ -165,7 +165,7 @@ class SingleStateStates(States):
|
|
|
165
165
|
"""
|
|
166
166
|
return np.ones((1, algo.n_turbines), dtype=FC.DTYPE)
|
|
167
167
|
|
|
168
|
-
def calculate(self, algo, mdata, fdata,
|
|
168
|
+
def calculate(self, algo, mdata, fdata, tdata):
|
|
169
169
|
""" "
|
|
170
170
|
The main model calculation.
|
|
171
171
|
|
|
@@ -176,44 +176,52 @@ class SingleStateStates(States):
|
|
|
176
176
|
----------
|
|
177
177
|
algo: foxes.core.Algorithm
|
|
178
178
|
The calculation algorithm
|
|
179
|
-
mdata: foxes.core.
|
|
179
|
+
mdata: foxes.core.MData
|
|
180
180
|
The model data
|
|
181
|
-
fdata: foxes.core.
|
|
181
|
+
fdata: foxes.core.FData
|
|
182
182
|
The farm data
|
|
183
|
-
|
|
184
|
-
The point data
|
|
183
|
+
tdata: foxes.core.TData
|
|
184
|
+
The target point data
|
|
185
185
|
|
|
186
186
|
Returns
|
|
187
187
|
-------
|
|
188
188
|
results: dict
|
|
189
189
|
The resulting data, keys: output variable str.
|
|
190
|
-
Values: numpy.ndarray with shape
|
|
190
|
+
Values: numpy.ndarray with shape
|
|
191
|
+
(n_states, n_targets, n_tpoints)
|
|
191
192
|
|
|
192
193
|
"""
|
|
193
|
-
|
|
194
194
|
if self.ws is not None:
|
|
195
|
-
|
|
196
|
-
(
|
|
195
|
+
tdata[FV.WS] = np.full(
|
|
196
|
+
(tdata.n_states, tdata.n_targets, tdata.n_tpoints),
|
|
197
|
+
self.ws,
|
|
198
|
+
dtype=FC.DTYPE,
|
|
197
199
|
)
|
|
198
200
|
if self.wd is not None:
|
|
199
|
-
|
|
200
|
-
(
|
|
201
|
+
tdata[FV.WD] = np.full(
|
|
202
|
+
(tdata.n_states, tdata.n_targets, tdata.n_tpoints),
|
|
203
|
+
self.wd,
|
|
204
|
+
dtype=FC.DTYPE,
|
|
201
205
|
)
|
|
202
206
|
if self.ti is not None:
|
|
203
|
-
|
|
204
|
-
(
|
|
207
|
+
tdata[FV.TI] = np.full(
|
|
208
|
+
(tdata.n_states, tdata.n_targets, tdata.n_tpoints),
|
|
209
|
+
self.ti,
|
|
210
|
+
dtype=FC.DTYPE,
|
|
205
211
|
)
|
|
206
212
|
if self.rho is not None:
|
|
207
|
-
|
|
208
|
-
(
|
|
213
|
+
tdata[FV.RHO] = np.full(
|
|
214
|
+
(tdata.n_states, tdata.n_targets, tdata.n_tpoints),
|
|
215
|
+
self.rho,
|
|
216
|
+
dtype=FC.DTYPE,
|
|
209
217
|
)
|
|
210
218
|
|
|
211
219
|
if len(self._profiles):
|
|
212
|
-
z =
|
|
220
|
+
z = tdata[FC.TARGETS][..., 2]
|
|
213
221
|
for k, v in self.profdata.items():
|
|
214
|
-
|
|
222
|
+
tdata[k] = v
|
|
215
223
|
for v, p in self._profiles.items():
|
|
216
|
-
pres = p.calculate(
|
|
217
|
-
|
|
224
|
+
pres = p.calculate(tdata, z)
|
|
225
|
+
tdata[v] = pres
|
|
218
226
|
|
|
219
|
-
return {v:
|
|
227
|
+
return {v: tdata[v] for v in self.output_point_vars(algo)}
|
|
@@ -309,7 +309,7 @@ class StatesTable(States):
|
|
|
309
309
|
"""
|
|
310
310
|
return self._weights
|
|
311
311
|
|
|
312
|
-
def calculate(self, algo, mdata, fdata,
|
|
312
|
+
def calculate(self, algo, mdata, fdata, tdata):
|
|
313
313
|
""" "
|
|
314
314
|
The main model calculation.
|
|
315
315
|
|
|
@@ -320,37 +320,41 @@ class StatesTable(States):
|
|
|
320
320
|
----------
|
|
321
321
|
algo: foxes.core.Algorithm
|
|
322
322
|
The calculation algorithm
|
|
323
|
-
mdata: foxes.core.
|
|
323
|
+
mdata: foxes.core.MData
|
|
324
324
|
The model data
|
|
325
|
-
fdata: foxes.core.
|
|
325
|
+
fdata: foxes.core.FData
|
|
326
326
|
The farm data
|
|
327
|
-
|
|
328
|
-
The point data
|
|
327
|
+
tdata: foxes.core.TData
|
|
328
|
+
The target point data
|
|
329
329
|
|
|
330
330
|
Returns
|
|
331
331
|
-------
|
|
332
332
|
results: dict
|
|
333
333
|
The resulting data, keys: output variable str.
|
|
334
|
-
Values: numpy.ndarray with shape
|
|
334
|
+
Values: numpy.ndarray with shape
|
|
335
|
+
(n_states, n_targets, n_tpoints)
|
|
335
336
|
|
|
336
337
|
"""
|
|
337
|
-
z = pdata[FC.POINTS][:, :, 2]
|
|
338
|
-
|
|
339
338
|
for i, v in enumerate(self._tvars):
|
|
340
|
-
if v in
|
|
341
|
-
|
|
339
|
+
if v in tdata:
|
|
340
|
+
tdata[v][:] = mdata[self.DATA][:, i, None, None]
|
|
342
341
|
else:
|
|
343
|
-
|
|
344
|
-
|
|
342
|
+
tdata[v] = np.zeros(
|
|
343
|
+
(tdata.n_states, tdata.n_targets, tdata.n_tpoints), dtype=FC.DTYPE
|
|
344
|
+
)
|
|
345
|
+
tdata[v][:] = mdata[self.DATA][:, i, None, None]
|
|
346
|
+
tdata.dims[v] = (FC.STATE, FC.TARGET, FC.TPOINT)
|
|
345
347
|
|
|
346
348
|
for v, f in self.fixed_vars.items():
|
|
347
|
-
|
|
349
|
+
tdata[v] = np.full(
|
|
350
|
+
(tdata.n_states, tdata.n_targets, tdata.n_tpoints), f, dtype=FC.DTYPE
|
|
351
|
+
)
|
|
348
352
|
|
|
353
|
+
z = tdata[FC.TARGETS][..., 2]
|
|
349
354
|
for v, p in self._profiles.items():
|
|
350
|
-
|
|
351
|
-
pdata[v] = pres
|
|
355
|
+
tdata[v] = p.calculate(tdata, z)
|
|
352
356
|
|
|
353
|
-
return {v:
|
|
357
|
+
return {v: tdata[v] for v in self.output_point_vars(algo)}
|
|
354
358
|
|
|
355
359
|
def finalize(self, algo, verbosity=0):
|
|
356
360
|
"""
|
|
@@ -472,8 +476,8 @@ class TabStates(StatesTable):
|
|
|
472
476
|
)
|
|
473
477
|
ws0 = 0.5 * (ws0[:-1] + ws0[1:])
|
|
474
478
|
|
|
475
|
-
n_ws = self._tab_data.
|
|
476
|
-
n_wd = self._tab_data.
|
|
479
|
+
n_ws = self._tab_data.sizes["ws"]
|
|
480
|
+
n_wd = self._tab_data.sizes["wd"]
|
|
477
481
|
ws = np.zeros((n_ws, n_wd), dtype=FC.DTYPE)
|
|
478
482
|
wd = np.zeros((n_ws, n_wd), dtype=FC.DTYPE)
|
|
479
483
|
ws[:] = ws0[:, None]
|
|
@@ -75,9 +75,9 @@ class Turbine2FarmModel(FarmModel):
|
|
|
75
75
|
----------
|
|
76
76
|
algo: foxes.core.Algorithm
|
|
77
77
|
The calculation algorithm
|
|
78
|
-
mdata: foxes.core.
|
|
78
|
+
mdata: foxes.core.MData
|
|
79
79
|
The model data
|
|
80
|
-
fdata: foxes.core.
|
|
80
|
+
fdata: foxes.core.FData
|
|
81
81
|
The farm data
|
|
82
82
|
**parameters: dict, optional
|
|
83
83
|
Init parameters forwarded to the turbine model
|
foxes/models/model_book.py
CHANGED
|
@@ -14,6 +14,7 @@ from foxes.core import (
|
|
|
14
14
|
WakeSuperposition,
|
|
15
15
|
WakeModel,
|
|
16
16
|
AxialInductionModel,
|
|
17
|
+
TurbineInductionModel,
|
|
17
18
|
)
|
|
18
19
|
|
|
19
20
|
|
|
@@ -93,16 +94,16 @@ class ModelBook:
|
|
|
93
94
|
self.turbine_types = Dict(name="turbine_types")
|
|
94
95
|
self.turbine_types["null_type"] = fm.turbine_types.NullType()
|
|
95
96
|
self.turbine_types["NREL5MW"] = fm.turbine_types.PCtFile(
|
|
96
|
-
"NREL-5MW-D126-H90.csv"
|
|
97
|
+
"NREL-5MW-D126-H90.csv", rho=1.225
|
|
97
98
|
)
|
|
98
99
|
self.turbine_types["DTU10MW"] = fm.turbine_types.PCtFile(
|
|
99
|
-
"DTU-10MW-D178d3-H119.csv"
|
|
100
|
+
"DTU-10MW-D178d3-H119.csv", rho=1.225
|
|
100
101
|
)
|
|
101
102
|
self.turbine_types["IEA15MW"] = fm.turbine_types.PCtFile(
|
|
102
|
-
"IEA-15MW-D240-H150.csv"
|
|
103
|
+
"IEA-15MW-D240-H150.csv", rho=1.225
|
|
103
104
|
)
|
|
104
105
|
self.turbine_types["IWT7.5MW"] = fm.turbine_types.PCtFile(
|
|
105
|
-
"IWT-7d5MW-D164-H100.csv"
|
|
106
|
+
"IWT-7d5MW-D164-H100.csv", rho=1.225
|
|
106
107
|
)
|
|
107
108
|
if Pct_file is not None:
|
|
108
109
|
self.turbine_types["Pct"] = fm.turbine_types.PCtFile(Pct_file)
|
|
@@ -148,24 +149,21 @@ class ModelBook:
|
|
|
148
149
|
name="partial_wakes",
|
|
149
150
|
rotor_points=fm.partial_wakes.RotorPoints(),
|
|
150
151
|
top_hat=fm.partial_wakes.PartialTopHat(),
|
|
151
|
-
|
|
152
|
-
auto=fm.partial_wakes.Mapped(),
|
|
152
|
+
centre=fm.partial_wakes.PartialCentre(),
|
|
153
153
|
)
|
|
154
154
|
nlst = list(range(2, 11)) + [20]
|
|
155
155
|
for n in nlst:
|
|
156
156
|
self.partial_wakes[f"axiwake{n}"] = fm.partial_wakes.PartialAxiwake(n)
|
|
157
157
|
for n in nlist:
|
|
158
|
-
self.partial_wakes[f"
|
|
159
|
-
fm.partial_wakes.PartialDistSlicedWake(n)
|
|
160
|
-
)
|
|
161
|
-
for n in nlist:
|
|
162
|
-
self.partial_wakes[f"grid{n**2}"] = fm.partial_wakes.PartialGrid(n)
|
|
158
|
+
self.partial_wakes[f"grid{n**2}"] = fm.partial_wakes.PartialGrid(n=n)
|
|
163
159
|
|
|
164
160
|
self.wake_frames = Dict(
|
|
165
161
|
name="wake_frames",
|
|
166
162
|
rotor_wd=fm.wake_frames.RotorWD(var_wd=FV.WD),
|
|
167
163
|
rotor_wd_farmo=fm.wake_frames.FarmOrder(),
|
|
168
164
|
yawed=fm.wake_frames.YawedWakes(),
|
|
165
|
+
yawed_k002=fm.wake_frames.YawedWakes(k=0.02),
|
|
166
|
+
yawed_k004=fm.wake_frames.YawedWakes(k=0.04),
|
|
169
167
|
)
|
|
170
168
|
stps = [1.0, 5.0, 10.0, 50.0, 100.0, 500.0]
|
|
171
169
|
for s in stps:
|
|
@@ -246,7 +244,7 @@ class ModelBook:
|
|
|
246
244
|
"linear_amb",
|
|
247
245
|
"linear_amb_lim",
|
|
248
246
|
"quadratic",
|
|
249
|
-
"
|
|
247
|
+
"quadratic_lim",
|
|
250
248
|
"quadratic_amb",
|
|
251
249
|
"quadratic_amb_lim",
|
|
252
250
|
"cubic",
|
|
@@ -416,13 +414,12 @@ class ModelBook:
|
|
|
416
414
|
)
|
|
417
415
|
|
|
418
416
|
self.wake_models[f"RHB"] = fm.wake_models.induction.RankineHalfBody()
|
|
417
|
+
self.wake_models[f"Rathmann"] = fm.wake_models.induction.Rathmann()
|
|
419
418
|
self.wake_models[f"SelfSimilar"] = fm.wake_models.induction.SelfSimilar()
|
|
420
419
|
self.wake_models[f"SelfSimilar2020"] = (
|
|
421
420
|
fm.wake_models.induction.SelfSimilar2020()
|
|
422
421
|
)
|
|
423
422
|
|
|
424
|
-
self.wake_models[f"Rathmann"] = fm.wake_models.induction.Rathmann()
|
|
425
|
-
|
|
426
423
|
self.sources = Dict(
|
|
427
424
|
name="sources",
|
|
428
425
|
point_models=self.point_models,
|
|
@@ -518,6 +515,35 @@ class ModelBook:
|
|
|
518
515
|
self.sources[model_type][name] = bclass.new(class_name, *args, **kwargs)
|
|
519
516
|
return self.sources[model_type][name]
|
|
520
517
|
|
|
518
|
+
def default_partial_wakes(self, wake_model):
|
|
519
|
+
"""
|
|
520
|
+
Gets a default partial wakes model name
|
|
521
|
+
for a given wake model
|
|
522
|
+
|
|
523
|
+
Parameters
|
|
524
|
+
----------
|
|
525
|
+
wake_model: foxes.core.WakeModel
|
|
526
|
+
The wake model
|
|
527
|
+
|
|
528
|
+
Returns
|
|
529
|
+
-------
|
|
530
|
+
pwake: str
|
|
531
|
+
The partial wake model name
|
|
532
|
+
|
|
533
|
+
"""
|
|
534
|
+
if isinstance(wake_model, TurbineInductionModel):
|
|
535
|
+
return "grid9"
|
|
536
|
+
elif isinstance(wake_model, fm.wake_models.TopHatWakeModel):
|
|
537
|
+
return "top_hat"
|
|
538
|
+
elif isinstance(wake_model, fm.wake_models.AxisymmetricWakeModel):
|
|
539
|
+
return "axiwake6"
|
|
540
|
+
elif isinstance(wake_model, fm.wake_models.DistSlicedWakeModel):
|
|
541
|
+
return "grid9"
|
|
542
|
+
else:
|
|
543
|
+
raise TypeError(
|
|
544
|
+
f"No default partial wakes model defined for wake model type '{type(wake_model).__name__}'"
|
|
545
|
+
)
|
|
546
|
+
|
|
521
547
|
def finalize(self, algo, verbosity=0):
|
|
522
548
|
"""
|
|
523
549
|
Finalizes the model.
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Partial wake models.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from .centre import PartialCentre
|
|
5
6
|
from .rotor_points import RotorPoints
|
|
6
7
|
from .top_hat import PartialTopHat
|
|
7
8
|
from .axiwake import PartialAxiwake
|
|
8
|
-
from .
|
|
9
|
+
from .segregated import PartialSegregated
|
|
9
10
|
from .grid import PartialGrid
|
|
10
|
-
from .mapped import Mapped
|