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
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
|
|
3
|
-
from foxes.core import PartialWakesModel, Data
|
|
4
3
|
from foxes.models.wake_models.axisymmetric import AxisymmetricWakeModel
|
|
5
4
|
from foxes.utils.two_circles import calc_area
|
|
6
5
|
import foxes.variables as FV
|
|
7
6
|
import foxes.constants as FC
|
|
8
7
|
|
|
8
|
+
from .centre import PartialCentre
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
class PartialAxiwake(PartialCentre):
|
|
11
12
|
"""
|
|
12
13
|
Partial wake calculation for axial wake models.
|
|
13
14
|
|
|
@@ -22,14 +23,12 @@ class PartialAxiwake(PartialWakesModel):
|
|
|
22
23
|
----------
|
|
23
24
|
n: int
|
|
24
25
|
The number of radial evaluation points
|
|
25
|
-
rotor_model: foxes.core.RotorModel
|
|
26
|
-
The rotor model, default is the one from the algorithm
|
|
27
26
|
|
|
28
27
|
:group: models.partial_wakes
|
|
29
28
|
|
|
30
29
|
"""
|
|
31
30
|
|
|
32
|
-
def __init__(self, n
|
|
31
|
+
def __init__(self, n=6):
|
|
33
32
|
"""
|
|
34
33
|
Constructor.
|
|
35
34
|
|
|
@@ -37,147 +36,93 @@ class PartialAxiwake(PartialWakesModel):
|
|
|
37
36
|
----------
|
|
38
37
|
n: int
|
|
39
38
|
The number of radial evaluation points
|
|
40
|
-
wake_models: list of foxes.core.WakeModel, optional
|
|
41
|
-
The wake models, default are the ones from the algorithm
|
|
42
|
-
wake_frame: foxes.core.WakeFrame, optional
|
|
43
|
-
The wake frame, default is the one from the algorithm
|
|
44
|
-
rotor_model: foxes.core.RotorModel, optional
|
|
45
|
-
The rotor model, default is the one from the algorithm
|
|
46
39
|
|
|
47
40
|
"""
|
|
48
|
-
super().__init__(
|
|
49
|
-
|
|
41
|
+
super().__init__()
|
|
50
42
|
self.n = n
|
|
51
|
-
self.rotor_model = rotor_model
|
|
52
43
|
|
|
53
44
|
def __repr__(self):
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
def initialize(self, algo, verbosity=0):
|
|
57
|
-
"""
|
|
58
|
-
Initializes the model.
|
|
59
|
-
|
|
60
|
-
Parameters
|
|
61
|
-
----------
|
|
62
|
-
algo: foxes.core.Algorithm
|
|
63
|
-
The calculation algorithm
|
|
64
|
-
verbosity: int
|
|
65
|
-
The verbosity level, 0 = silent
|
|
66
|
-
|
|
67
|
-
"""
|
|
68
|
-
if self.rotor_model is None:
|
|
69
|
-
self.rotor_model = algo.rotor_model
|
|
70
|
-
super().initialize(algo, verbosity)
|
|
71
|
-
|
|
72
|
-
for w in self.wake_models:
|
|
73
|
-
if not isinstance(w, AxisymmetricWakeModel):
|
|
74
|
-
raise TypeError(
|
|
75
|
-
f"Partial wakes '{self.name}': Cannot be applied to wake model '{w.name}', since not an AxisymmetricWakeModel"
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
def sub_models(self):
|
|
79
|
-
"""
|
|
80
|
-
List of all sub-models
|
|
81
|
-
|
|
82
|
-
Returns
|
|
83
|
-
-------
|
|
84
|
-
smdls: list of foxes.core.Model
|
|
85
|
-
All sub models
|
|
86
|
-
|
|
87
|
-
"""
|
|
88
|
-
return super().sub_models() + [self.rotor_model]
|
|
89
|
-
|
|
90
|
-
def new_wake_deltas(self, algo, mdata, fdata):
|
|
91
|
-
"""
|
|
92
|
-
Creates new initial wake deltas, filled
|
|
93
|
-
with zeros.
|
|
94
|
-
|
|
95
|
-
Parameters
|
|
96
|
-
----------
|
|
97
|
-
algo: foxes.core.Algorithm
|
|
98
|
-
The calculation algorithm
|
|
99
|
-
mdata: foxes.core.Data
|
|
100
|
-
The model data
|
|
101
|
-
fdata: foxes.core.Data
|
|
102
|
-
The farm data
|
|
103
|
-
|
|
104
|
-
Returns
|
|
105
|
-
-------
|
|
106
|
-
wake_deltas: dict
|
|
107
|
-
Keys: Variable name str, values: any
|
|
108
|
-
pdata: foxes.core.Data
|
|
109
|
-
The evaluation point data
|
|
110
|
-
|
|
111
|
-
"""
|
|
112
|
-
pdata = Data.from_points(points=fdata[FV.TXYH])
|
|
45
|
+
return f"{type(self).__name__}(n={self.n})"
|
|
113
46
|
|
|
114
|
-
|
|
115
|
-
for w in self.wake_models:
|
|
116
|
-
w.init_wake_deltas(algo, mdata, fdata, pdata, wake_deltas)
|
|
117
|
-
|
|
118
|
-
return wake_deltas, pdata
|
|
119
|
-
|
|
120
|
-
def contribute_to_wake_deltas(
|
|
47
|
+
def contribute(
|
|
121
48
|
self,
|
|
122
49
|
algo,
|
|
123
50
|
mdata,
|
|
124
51
|
fdata,
|
|
125
|
-
|
|
126
|
-
|
|
52
|
+
tdata,
|
|
53
|
+
downwind_index,
|
|
127
54
|
wake_deltas,
|
|
55
|
+
wmodel,
|
|
128
56
|
):
|
|
129
57
|
"""
|
|
130
|
-
Modifies wake deltas
|
|
131
|
-
specified wake source turbines.
|
|
58
|
+
Modifies wake deltas at target points by
|
|
59
|
+
contributions from the specified wake source turbines.
|
|
132
60
|
|
|
133
61
|
Parameters
|
|
134
62
|
----------
|
|
135
63
|
algo: foxes.core.Algorithm
|
|
136
64
|
The calculation algorithm
|
|
137
|
-
mdata: foxes.core.
|
|
65
|
+
mdata: foxes.core.MData
|
|
138
66
|
The model data
|
|
139
|
-
fdata: foxes.core.
|
|
67
|
+
fdata: foxes.core.FData
|
|
140
68
|
The farm data
|
|
141
|
-
|
|
142
|
-
The
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
wake_deltas:
|
|
147
|
-
The wake deltas
|
|
148
|
-
|
|
69
|
+
tdata: foxes.core.TData
|
|
70
|
+
The target point data
|
|
71
|
+
downwind_index: int
|
|
72
|
+
The index of the wake causing turbine
|
|
73
|
+
in the downwnd order
|
|
74
|
+
wake_deltas: dict
|
|
75
|
+
The wake deltas. Key: variable name,
|
|
76
|
+
value: numpy.ndarray with shape
|
|
77
|
+
(n_states, n_targets, n_tpoints, ...)
|
|
78
|
+
wmodel: foxes.core.WakeModel
|
|
79
|
+
The wake model
|
|
149
80
|
|
|
150
81
|
"""
|
|
82
|
+
if not isinstance(wmodel, AxisymmetricWakeModel):
|
|
83
|
+
raise TypeError(
|
|
84
|
+
f"Partial wakes '{self.name}': Cannot be applied to wake model '{wmodel.name}', since not an AxisymmetricWakeModel"
|
|
85
|
+
)
|
|
86
|
+
|
|
151
87
|
# prepare:
|
|
152
88
|
n_states = mdata.n_states
|
|
153
|
-
|
|
154
|
-
|
|
89
|
+
n_targets = tdata.n_targets
|
|
90
|
+
|
|
91
|
+
# get D:
|
|
92
|
+
D = self.get_data(
|
|
93
|
+
FV.D,
|
|
94
|
+
FC.STATE_TARGET,
|
|
95
|
+
lookup="w",
|
|
96
|
+
algo=algo,
|
|
97
|
+
fdata=fdata,
|
|
98
|
+
tdata=tdata,
|
|
99
|
+
downwind_index=downwind_index,
|
|
100
|
+
upcast=True,
|
|
101
|
+
)
|
|
155
102
|
|
|
156
103
|
# calc coordinates to rotor centres:
|
|
157
|
-
wcoos =
|
|
158
|
-
algo, mdata, fdata, pdata, states_source_turbine
|
|
159
|
-
)
|
|
104
|
+
wcoos = algo.wake_frame.get_wake_coos(algo, mdata, fdata, tdata, downwind_index)
|
|
160
105
|
|
|
161
106
|
# prepare x and r coordinates:
|
|
162
|
-
x = wcoos[
|
|
163
|
-
n = wcoos[
|
|
107
|
+
x = np.round(wcoos[..., 0, 0], 12)
|
|
108
|
+
n = wcoos[..., 0, 1:3]
|
|
164
109
|
R = np.linalg.norm(n, axis=-1)
|
|
165
|
-
r = np.zeros((n_states,
|
|
110
|
+
r = np.zeros((n_states, n_targets, self.n), dtype=FC.DTYPE)
|
|
166
111
|
del wcoos
|
|
167
112
|
|
|
168
113
|
# prepare circle section area calculation:
|
|
169
|
-
A = np.zeros((n_states,
|
|
114
|
+
A = np.zeros((n_states, n_targets, self.n), dtype=FC.DTYPE)
|
|
170
115
|
weights = np.zeros_like(A)
|
|
171
116
|
|
|
172
117
|
# get normalized 2D vector between rotor and wake centres:
|
|
173
|
-
sel = R > 0
|
|
118
|
+
sel = R > 0
|
|
174
119
|
if np.any(sel):
|
|
175
120
|
n[sel] /= R[sel][:, None]
|
|
176
121
|
if np.any(~sel):
|
|
177
122
|
n[:, :, 0][~sel] = 1
|
|
178
123
|
|
|
179
124
|
# case wake centre outside rotor disk:
|
|
180
|
-
sel = (x >
|
|
125
|
+
sel = (x > 0) & (R > D / 2)
|
|
181
126
|
if np.any(sel):
|
|
182
127
|
n_sel = np.sum(sel)
|
|
183
128
|
Rsel = np.zeros((n_sel, self.n + 1), dtype=FC.DTYPE)
|
|
@@ -199,7 +144,7 @@ class PartialAxiwake(PartialWakesModel):
|
|
|
199
144
|
del hA, Rsel, Dsel, R1, R2
|
|
200
145
|
|
|
201
146
|
# case wake centre inside rotor disk:
|
|
202
|
-
sel = (x >
|
|
147
|
+
sel = (x > 0) & (R < D / 2)
|
|
203
148
|
if np.any(sel):
|
|
204
149
|
n_sel = np.sum(sel)
|
|
205
150
|
Rsel = np.zeros((n_sel, self.n + 1), dtype=FC.DTYPE)
|
|
@@ -225,101 +170,29 @@ class PartialAxiwake(PartialWakesModel):
|
|
|
225
170
|
weights[sel] = hA / np.sum(hA, axis=-1)[:, None]
|
|
226
171
|
del hA, hr, Rsel, Dsel, R1, R2
|
|
227
172
|
|
|
228
|
-
# evaluate wake
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
for v, wdel in wdeltas.items():
|
|
235
|
-
d = np.einsum("ps,ps->p", wdel, weights[sp_sel])
|
|
236
|
-
|
|
237
|
-
try:
|
|
238
|
-
superp = w.superp[v]
|
|
239
|
-
except KeyError:
|
|
240
|
-
raise KeyError(
|
|
241
|
-
f"Model '{self.name}': Missing wake superposition entry for variable '{v}' in wake model '{w.name}', found {sorted(list(w.superp.keys()))}"
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
wake_deltas[v] = superp.calc_wakes_plus_wake(
|
|
245
|
-
algo,
|
|
246
|
-
mdata,
|
|
247
|
-
fdata,
|
|
248
|
-
pdata,
|
|
249
|
-
states_source_turbine,
|
|
250
|
-
sp_sel,
|
|
251
|
-
v,
|
|
252
|
-
wake_deltas[v],
|
|
253
|
-
d,
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
def evaluate_results(
|
|
257
|
-
self,
|
|
258
|
-
algo,
|
|
259
|
-
mdata,
|
|
260
|
-
fdata,
|
|
261
|
-
pdata,
|
|
262
|
-
wake_deltas,
|
|
263
|
-
states_turbine,
|
|
264
|
-
amb_res=None,
|
|
265
|
-
):
|
|
266
|
-
"""
|
|
267
|
-
Updates the farm data according to the wake
|
|
268
|
-
deltas.
|
|
269
|
-
|
|
270
|
-
Parameters
|
|
271
|
-
----------
|
|
272
|
-
algo: foxes.core.Algorithm
|
|
273
|
-
The calculation algorithm
|
|
274
|
-
mdata: foxes.core.Data
|
|
275
|
-
The model data
|
|
276
|
-
fdata: foxes.core.Data
|
|
277
|
-
The farm data
|
|
278
|
-
Modified in-place by this function
|
|
279
|
-
pdata: foxes.core.Data
|
|
280
|
-
The evaluation point data
|
|
281
|
-
wake_deltas: Any
|
|
282
|
-
The wake deltas object, created by the
|
|
283
|
-
`new_wake_deltas` function and filled
|
|
284
|
-
by `contribute_to_wake_deltas`
|
|
285
|
-
states_turbine: numpy.ndarray of int
|
|
286
|
-
For each state, the index of one turbine
|
|
287
|
-
for which to evaluate the wake deltas.
|
|
288
|
-
Shape: (n_states,)
|
|
289
|
-
amb_res: dict, optional
|
|
290
|
-
Ambient states results. Keys: var str, values:
|
|
291
|
-
numpy.ndarray of shape (n_states, n_points)
|
|
173
|
+
# evaluate wake model:
|
|
174
|
+
wdeltas, st_sel = wmodel.calc_wakes_x_r(
|
|
175
|
+
algo, mdata, fdata, tdata, downwind_index, x, r
|
|
176
|
+
)
|
|
292
177
|
|
|
293
|
-
|
|
178
|
+
for v, wdel in wdeltas.items():
|
|
179
|
+
d = np.einsum("sn,sn->s", wdel, weights[st_sel])
|
|
294
180
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
181
|
+
try:
|
|
182
|
+
superp = wmodel.superp[v]
|
|
183
|
+
except KeyError:
|
|
184
|
+
raise KeyError(
|
|
185
|
+
f"Model '{self.name}': Missing wake superposition entry for variable '{v}' in wake model '{wmodel.name}', found {sorted(list(wmodel.superp.keys()))}"
|
|
186
|
+
)
|
|
298
187
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
188
|
+
wake_deltas[v] = superp.add_wake(
|
|
189
|
+
algo,
|
|
190
|
+
mdata,
|
|
191
|
+
fdata,
|
|
192
|
+
tdata,
|
|
193
|
+
downwind_index,
|
|
194
|
+
st_sel,
|
|
195
|
+
v,
|
|
196
|
+
wake_deltas[v],
|
|
197
|
+
d[:, None],
|
|
303
198
|
)
|
|
304
|
-
|
|
305
|
-
wres = {}
|
|
306
|
-
st_sel = (np.arange(n_states), states_turbine)
|
|
307
|
-
for v, ares in amb_res.items():
|
|
308
|
-
wres[v] = ares.reshape(n_states, n_turbines, n_rpoints)[st_sel]
|
|
309
|
-
|
|
310
|
-
wdel = {}
|
|
311
|
-
for v, d in wake_deltas.items():
|
|
312
|
-
wdel[v] = d.reshape(n_states, n_turbines, 1)[st_sel]
|
|
313
|
-
for w in self.wake_models:
|
|
314
|
-
w.finalize_wake_deltas(algo, mdata, fdata, pdata, wres, wdel)
|
|
315
|
-
|
|
316
|
-
for v in wres.keys():
|
|
317
|
-
if v in wake_deltas:
|
|
318
|
-
wres[v] += wdel[v]
|
|
319
|
-
if amb_res_in:
|
|
320
|
-
amb_res[v][st_sel] = wres[v]
|
|
321
|
-
wres[v] = wres[v][:, None]
|
|
322
|
-
|
|
323
|
-
self.rotor_model.eval_rpoint_results(
|
|
324
|
-
algo, mdata, fdata, wres, weights, states_turbine=states_turbine
|
|
325
|
-
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
import foxes.variables as FV
|
|
4
|
+
import foxes.constants as FC
|
|
5
|
+
from .rotor_points import RotorPoints
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PartialCentre(RotorPoints):
|
|
9
|
+
"""
|
|
10
|
+
Partial wakes calculated only at the
|
|
11
|
+
rotor centre point.
|
|
12
|
+
|
|
13
|
+
:group: models.partial_wakes
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def get_wake_points(self, algo, mdata, fdata):
|
|
18
|
+
"""
|
|
19
|
+
Get the wake calculation points, and their
|
|
20
|
+
weights.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
algo: foxes.core.Algorithm
|
|
25
|
+
The calculation algorithm
|
|
26
|
+
mdata: foxes.core.MData
|
|
27
|
+
The model data
|
|
28
|
+
fdata: foxes.core.FData
|
|
29
|
+
The farm data
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
rpoints: numpy.ndarray
|
|
34
|
+
The wake calculation points, shape:
|
|
35
|
+
(n_states, n_turbines, n_tpoints, 3)
|
|
36
|
+
rweights: numpy.ndarray
|
|
37
|
+
The target point weights, shape: (n_tpoints,)
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
return fdata[FV.TXYH][:, :, None], np.ones(1, dtype=FC.DTYPE)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from
|
|
1
|
+
from .segregated import PartialSegregated
|
|
2
2
|
from foxes.models.rotor_models.grid import GridRotor
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
class PartialGrid(
|
|
5
|
+
class PartialGrid(PartialSegregated):
|
|
6
6
|
"""
|
|
7
7
|
Partial wakes on a grid rotor that may
|
|
8
8
|
differ from the one in the algorithm.
|
|
@@ -11,72 +11,16 @@ class PartialGrid(PartialDistSlicedWake):
|
|
|
11
11
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
def __init__(
|
|
15
|
-
self, n, wake_models=None, wake_frame=None, rotor_model=None, **kwargs
|
|
16
|
-
):
|
|
14
|
+
def __init__(self, *args, **kwargs):
|
|
17
15
|
"""
|
|
18
16
|
Constructor.
|
|
19
17
|
|
|
20
18
|
Parameters
|
|
21
19
|
----------
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
wake_models: list of foxes.core.WakeModel, optional
|
|
25
|
-
The wake models, default are the ones from the algorithm
|
|
26
|
-
wake_frame: foxes.core.WakeFrame, optional
|
|
27
|
-
The wake frame, default is the one from the algorithm
|
|
28
|
-
rotor_model: foxes.core.RotorModel, optional
|
|
29
|
-
The rotor model, default is the one from the algorithm
|
|
20
|
+
args: tuple, optional
|
|
21
|
+
Parameters for GridRotor
|
|
30
22
|
kwargs: dict, optional
|
|
31
|
-
|
|
23
|
+
Parameters for GridRotor
|
|
32
24
|
|
|
33
25
|
"""
|
|
34
|
-
super().__init__(
|
|
35
|
-
|
|
36
|
-
if not isinstance(self.grotor, GridRotor):
|
|
37
|
-
raise ValueError(
|
|
38
|
-
f"Wrong grotor type, expecting {GridRotor.__name__}, got {type(self.grotor).__name__}"
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
def contribute_to_wake_deltas(
|
|
42
|
-
self,
|
|
43
|
-
algo,
|
|
44
|
-
mdata,
|
|
45
|
-
fdata,
|
|
46
|
-
pdata,
|
|
47
|
-
states_source_turbine,
|
|
48
|
-
wake_deltas,
|
|
49
|
-
):
|
|
50
|
-
"""
|
|
51
|
-
Modifies wake deltas by contributions from the
|
|
52
|
-
specified wake source turbines.
|
|
53
|
-
|
|
54
|
-
Parameters
|
|
55
|
-
----------
|
|
56
|
-
algo: foxes.core.Algorithm
|
|
57
|
-
The calculation algorithm
|
|
58
|
-
mdata: foxes.core.Data
|
|
59
|
-
The model data
|
|
60
|
-
fdata: foxes.core.Data
|
|
61
|
-
The farm data
|
|
62
|
-
pdata: foxes.core.Data
|
|
63
|
-
The evaluation point data
|
|
64
|
-
states_source_turbine: numpy.ndarray of int
|
|
65
|
-
For each state, one turbine index corresponding
|
|
66
|
-
to the wake causing turbine. Shape: (n_states,)
|
|
67
|
-
wake_deltas: Any
|
|
68
|
-
The wake deltas object created by the
|
|
69
|
-
`new_wake_deltas` function
|
|
70
|
-
|
|
71
|
-
"""
|
|
72
|
-
|
|
73
|
-
# evaluate grid rotor:
|
|
74
|
-
wcoos = self.wake_frame.get_wake_coos(
|
|
75
|
-
algo, mdata, fdata, pdata, states_source_turbine
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
# evaluate wake models:
|
|
79
|
-
for w in self.wake_models:
|
|
80
|
-
w.contribute_to_wake_deltas(
|
|
81
|
-
algo, mdata, fdata, pdata, states_source_turbine, wcoos, wake_deltas
|
|
82
|
-
)
|
|
26
|
+
super().__init__(GridRotor(*args, calc_vars=[], **kwargs))
|