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.top_hat import TopHatWakeModel
|
|
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 PartialTopHat(PartialCentre):
|
|
11
12
|
"""
|
|
12
13
|
Partial wakes for top-hat models.
|
|
13
14
|
|
|
@@ -23,21 +24,17 @@ class PartialTopHat(PartialWakesModel):
|
|
|
23
24
|
|
|
24
25
|
"""
|
|
25
26
|
|
|
26
|
-
def __init__(self,
|
|
27
|
+
def __init__(self, rotor_model=None):
|
|
27
28
|
"""
|
|
28
29
|
Constructor.
|
|
29
30
|
|
|
30
31
|
Parameters
|
|
31
32
|
----------
|
|
32
|
-
wake_models: list of foxes.core.WakeModel, optional
|
|
33
|
-
The wake models, default are the ones from the algorithm
|
|
34
|
-
wake_frame: foxes.core.WakeFrame, optional
|
|
35
|
-
The wake frame, default is the one from the algorithm
|
|
36
33
|
rotor_model: foxes.core.RotorModel, optional
|
|
37
34
|
The rotor model, default is the one from the algorithm
|
|
38
35
|
|
|
39
36
|
"""
|
|
40
|
-
super().__init__(
|
|
37
|
+
super().__init__()
|
|
41
38
|
self.rotor_model = rotor_model
|
|
42
39
|
|
|
43
40
|
def initialize(self, algo, verbosity=0):
|
|
@@ -57,12 +54,6 @@ class PartialTopHat(PartialWakesModel):
|
|
|
57
54
|
|
|
58
55
|
super().initialize(algo, verbosity)
|
|
59
56
|
|
|
60
|
-
for w in self.wake_models:
|
|
61
|
-
if not isinstance(w, TopHatWakeModel):
|
|
62
|
-
raise TypeError(
|
|
63
|
-
f"Partial wakes '{self.name}': Cannot be applied to wake model '{w.name}', since not a TopHatWakeModel"
|
|
64
|
-
)
|
|
65
|
-
|
|
66
57
|
self.WCOOS_ID = self.var("WCOOS_ID")
|
|
67
58
|
self.WCOOS_X = self.var("WCOOS_X")
|
|
68
59
|
self.WCOOS_R = self.var("WCOOS_R")
|
|
@@ -79,211 +70,112 @@ class PartialTopHat(PartialWakesModel):
|
|
|
79
70
|
"""
|
|
80
71
|
return super().sub_models() + [self.rotor_model]
|
|
81
72
|
|
|
82
|
-
def
|
|
83
|
-
"""
|
|
84
|
-
Creates new initial wake deltas, filled
|
|
85
|
-
with zeros.
|
|
86
|
-
|
|
87
|
-
Parameters
|
|
88
|
-
----------
|
|
89
|
-
algo: foxes.core.Algorithm
|
|
90
|
-
The calculation algorithm
|
|
91
|
-
mdata: foxes.core.Data
|
|
92
|
-
The model data
|
|
93
|
-
fdata: foxes.core.Data
|
|
94
|
-
The farm data
|
|
95
|
-
|
|
96
|
-
Returns
|
|
97
|
-
-------
|
|
98
|
-
wake_deltas: dict
|
|
99
|
-
Keys: Variable name str, values: any
|
|
100
|
-
pdata: foxes.core.Data
|
|
101
|
-
The evaluation point data
|
|
102
|
-
|
|
103
|
-
"""
|
|
104
|
-
pdata = Data.from_points(points=fdata[FV.TXYH])
|
|
105
|
-
|
|
106
|
-
wake_deltas = {}
|
|
107
|
-
for w in self.wake_models:
|
|
108
|
-
w.init_wake_deltas(algo, mdata, fdata, pdata, wake_deltas)
|
|
109
|
-
|
|
110
|
-
return wake_deltas, pdata
|
|
111
|
-
|
|
112
|
-
def contribute_to_wake_deltas(
|
|
73
|
+
def contribute(
|
|
113
74
|
self,
|
|
114
75
|
algo,
|
|
115
76
|
mdata,
|
|
116
77
|
fdata,
|
|
117
|
-
|
|
118
|
-
|
|
78
|
+
tdata,
|
|
79
|
+
downwind_index,
|
|
119
80
|
wake_deltas,
|
|
81
|
+
wmodel,
|
|
120
82
|
):
|
|
121
83
|
"""
|
|
122
|
-
Modifies wake deltas
|
|
123
|
-
specified wake source turbines.
|
|
84
|
+
Modifies wake deltas at target points by
|
|
85
|
+
contributions from the specified wake source turbines.
|
|
124
86
|
|
|
125
87
|
Parameters
|
|
126
88
|
----------
|
|
127
89
|
algo: foxes.core.Algorithm
|
|
128
90
|
The calculation algorithm
|
|
129
|
-
mdata: foxes.core.
|
|
91
|
+
mdata: foxes.core.MData
|
|
130
92
|
The model data
|
|
131
|
-
fdata: foxes.core.
|
|
93
|
+
fdata: foxes.core.FData
|
|
132
94
|
The farm data
|
|
133
|
-
|
|
134
|
-
The
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
wake_deltas:
|
|
139
|
-
The wake deltas
|
|
140
|
-
|
|
95
|
+
tdata: foxes.core.TData
|
|
96
|
+
The target point data
|
|
97
|
+
downwind_index: int
|
|
98
|
+
The index of the wake causing turbine
|
|
99
|
+
in the downwnd order
|
|
100
|
+
wake_deltas: dict
|
|
101
|
+
The wake deltas. Key: variable name,
|
|
102
|
+
value: numpy.ndarray with shape
|
|
103
|
+
(n_states, n_targets, n_tpoints, ...)
|
|
104
|
+
wmodel: foxes.core.WakeModel
|
|
105
|
+
The wake model
|
|
141
106
|
|
|
142
107
|
"""
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (
|
|
148
|
-
self.WCOOS_ID not in mdata
|
|
149
|
-
or mdata[self.WCOOS_ID] != states_source_turbine[0]
|
|
150
|
-
):
|
|
151
|
-
wcoos = self.wake_frame.get_wake_coos(
|
|
152
|
-
algo, mdata, fdata, pdata, states_source_turbine
|
|
108
|
+
if not isinstance(wmodel, TopHatWakeModel):
|
|
109
|
+
raise TypeError(
|
|
110
|
+
f"Partial wakes '{self.name}': Cannot be applied to wake model '{wmodel.name}', since not a TopHatWakeModel"
|
|
153
111
|
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
112
|
+
|
|
113
|
+
wcoos = algo.wake_frame.get_wake_coos(algo, mdata, fdata, tdata, downwind_index)
|
|
114
|
+
x = wcoos[:, :, 0, 0]
|
|
115
|
+
yz = wcoos[:, :, 0, 1:3]
|
|
116
|
+
del wcoos
|
|
117
|
+
|
|
118
|
+
ct = self.get_data(
|
|
119
|
+
FV.CT,
|
|
120
|
+
FC.STATE_TARGET,
|
|
121
|
+
lookup="w",
|
|
122
|
+
fdata=fdata,
|
|
123
|
+
tdata=tdata,
|
|
124
|
+
downwind_index=downwind_index,
|
|
125
|
+
algo=algo,
|
|
126
|
+
upcast=True,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
sel0 = (ct > 0) & (x > 0)
|
|
167
130
|
if np.any(sel0):
|
|
168
|
-
R =
|
|
169
|
-
|
|
170
|
-
|
|
131
|
+
R = np.linalg.norm(yz, axis=-1)
|
|
132
|
+
del yz
|
|
133
|
+
|
|
134
|
+
D = self.get_data(
|
|
135
|
+
FV.D,
|
|
136
|
+
FC.STATE_TARGET,
|
|
137
|
+
lookup="w",
|
|
138
|
+
fdata=fdata,
|
|
139
|
+
tdata=tdata,
|
|
140
|
+
downwind_index=downwind_index,
|
|
141
|
+
algo=algo,
|
|
142
|
+
upcast=True,
|
|
143
|
+
)
|
|
171
144
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
145
|
+
wr = wmodel.calc_wake_radius(
|
|
146
|
+
algo, mdata, fdata, tdata, downwind_index, x, ct
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
st_sel = sel0 & (wr > R - D / 2)
|
|
150
|
+
if np.any(st_sel):
|
|
151
|
+
x = x[st_sel]
|
|
152
|
+
ct = ct[st_sel]
|
|
153
|
+
wr = wr[st_sel]
|
|
154
|
+
R = R[st_sel]
|
|
155
|
+
D = D[st_sel]
|
|
156
|
+
|
|
157
|
+
clw = wmodel.calc_centreline(
|
|
158
|
+
algo, mdata, fdata, tdata, downwind_index, st_sel, x, wr, ct
|
|
175
159
|
)
|
|
176
160
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
161
|
+
weights = calc_area(D / 2, wr, R) / (np.pi * (D / 2) ** 2)
|
|
162
|
+
|
|
163
|
+
for v, d in clw.items():
|
|
164
|
+
try:
|
|
165
|
+
superp = wmodel.superp[v]
|
|
166
|
+
except KeyError:
|
|
167
|
+
raise KeyError(
|
|
168
|
+
f"Model '{self.name}': Missing wake superposition entry for variable '{v}' in wake model '{wmodel.name}', found {sorted(list(wmodel.superp.keys()))}"
|
|
169
|
+
)
|
|
182
170
|
|
|
183
|
-
|
|
171
|
+
wake_deltas[v] = superp.add_wake(
|
|
184
172
|
algo,
|
|
185
173
|
mdata,
|
|
186
174
|
fdata,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
175
|
+
tdata,
|
|
176
|
+
downwind_index,
|
|
177
|
+
st_sel,
|
|
178
|
+
v,
|
|
179
|
+
wake_deltas[v],
|
|
180
|
+
weights[:, None] * d[:, None],
|
|
193
181
|
)
|
|
194
|
-
del hx, hct
|
|
195
|
-
|
|
196
|
-
hR = R[sel_sp]
|
|
197
|
-
hD = D[sel_sp]
|
|
198
|
-
weights = calc_area(hD / 2, hwr, hR) / (np.pi * (hD / 2) ** 2)
|
|
199
|
-
del hD, hwr, hR
|
|
200
|
-
|
|
201
|
-
for v, d in clw.items():
|
|
202
|
-
try:
|
|
203
|
-
superp = w.superp[v]
|
|
204
|
-
except KeyError:
|
|
205
|
-
raise KeyError(
|
|
206
|
-
f"Model '{self.name}': Missing wake superposition entry for variable '{v}' in wake model '{w.name}', found {sorted(list(w.superp.keys()))}"
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
wake_deltas[v] = superp.calc_wakes_plus_wake(
|
|
210
|
-
algo,
|
|
211
|
-
mdata,
|
|
212
|
-
fdata,
|
|
213
|
-
pdata,
|
|
214
|
-
states_source_turbine,
|
|
215
|
-
sel_sp,
|
|
216
|
-
v,
|
|
217
|
-
wake_deltas[v],
|
|
218
|
-
weights * d,
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
def evaluate_results(
|
|
222
|
-
self,
|
|
223
|
-
algo,
|
|
224
|
-
mdata,
|
|
225
|
-
fdata,
|
|
226
|
-
pdata,
|
|
227
|
-
wake_deltas,
|
|
228
|
-
states_turbine,
|
|
229
|
-
amb_res=None,
|
|
230
|
-
):
|
|
231
|
-
"""
|
|
232
|
-
Updates the farm data according to the wake
|
|
233
|
-
deltas.
|
|
234
|
-
|
|
235
|
-
Parameters
|
|
236
|
-
----------
|
|
237
|
-
algo: foxes.core.Algorithm
|
|
238
|
-
The calculation algorithm
|
|
239
|
-
mdata: foxes.core.Data
|
|
240
|
-
The model data
|
|
241
|
-
fdata: foxes.core.Data
|
|
242
|
-
The farm data
|
|
243
|
-
Modified in-place by this function
|
|
244
|
-
pdata: foxes.core.Data
|
|
245
|
-
The evaluation point data
|
|
246
|
-
wake_deltas: Any
|
|
247
|
-
The wake deltas object, created by the
|
|
248
|
-
`new_wake_deltas` function and filled
|
|
249
|
-
by `contribute_to_wake_deltas`
|
|
250
|
-
states_turbine: numpy.ndarray of int
|
|
251
|
-
For each state, the index of one turbine
|
|
252
|
-
for which to evaluate the wake deltas.
|
|
253
|
-
Shape: (n_states,)
|
|
254
|
-
amb_res: dict, optional
|
|
255
|
-
Ambient states results. Keys: var str, values:
|
|
256
|
-
numpy.ndarray of shape (n_states, n_points)
|
|
257
|
-
|
|
258
|
-
"""
|
|
259
|
-
weights = algo.rotor_model.from_data_or_store(FC.RWEIGHTS, algo, mdata)
|
|
260
|
-
rpoints = algo.rotor_model.from_data_or_store(FC.RPOINTS, algo, mdata)
|
|
261
|
-
n_states, n_turbines, n_rpoints, __ = rpoints.shape
|
|
262
|
-
|
|
263
|
-
amb_res_in = amb_res is not None
|
|
264
|
-
if not amb_res_in:
|
|
265
|
-
amb_res = algo.rotor_model.from_data_or_store(
|
|
266
|
-
FC.AMB_RPOINT_RESULTS, algo, mdata
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
wres = {}
|
|
270
|
-
st_sel = (np.arange(n_states), states_turbine)
|
|
271
|
-
for v, ares in amb_res.items():
|
|
272
|
-
wres[v] = ares.reshape(n_states, n_turbines, n_rpoints)[st_sel]
|
|
273
|
-
|
|
274
|
-
wdel = {}
|
|
275
|
-
for v, d in wake_deltas.items():
|
|
276
|
-
wdel[v] = d.reshape(n_states, n_turbines, 1)[st_sel]
|
|
277
|
-
for w in self.wake_models:
|
|
278
|
-
w.finalize_wake_deltas(algo, mdata, fdata, pdata, wres, wdel)
|
|
279
|
-
|
|
280
|
-
for v in wres.keys():
|
|
281
|
-
if v in wake_deltas:
|
|
282
|
-
wres[v] += wdel[v]
|
|
283
|
-
if amb_res_in:
|
|
284
|
-
amb_res[v][st_sel] = wres[v]
|
|
285
|
-
wres[v] = wres[v][:, None]
|
|
286
|
-
|
|
287
|
-
self.rotor_model.eval_rpoint_results(
|
|
288
|
-
algo, mdata, fdata, wres, weights, states_turbine=states_turbine
|
|
289
|
-
)
|
|
@@ -129,12 +129,12 @@ class SetUniformData(PointDataModel):
|
|
|
129
129
|
----------
|
|
130
130
|
algo: foxes.core.Algorithm
|
|
131
131
|
The calculation algorithm
|
|
132
|
-
mdata: foxes.core.
|
|
132
|
+
mdata: foxes.core.MData
|
|
133
133
|
The model data
|
|
134
|
-
fdata: foxes.core.
|
|
134
|
+
fdata: foxes.core.FData
|
|
135
135
|
The farm data
|
|
136
|
-
|
|
137
|
-
The point data
|
|
136
|
+
tdata: foxes.core.TData
|
|
137
|
+
The target point data
|
|
138
138
|
|
|
139
139
|
Returns
|
|
140
140
|
-------
|
|
@@ -40,12 +40,12 @@ class TKE2TI(PointDataModel):
|
|
|
40
40
|
----------
|
|
41
41
|
algo: foxes.core.Algorithm
|
|
42
42
|
The calculation algorithm
|
|
43
|
-
mdata: foxes.core.
|
|
43
|
+
mdata: foxes.core.MData
|
|
44
44
|
The model data
|
|
45
|
-
fdata: foxes.core.
|
|
45
|
+
fdata: foxes.core.FData
|
|
46
46
|
The farm data
|
|
47
|
-
|
|
48
|
-
The point data
|
|
47
|
+
tdata: foxes.core.TData
|
|
48
|
+
The target point data
|
|
49
49
|
|
|
50
50
|
Returns
|
|
51
51
|
-------
|
|
@@ -62,12 +62,12 @@ class WakeDeltas(PointDataModel):
|
|
|
62
62
|
----------
|
|
63
63
|
algo: foxes.core.Algorithm
|
|
64
64
|
The calculation algorithm
|
|
65
|
-
mdata: foxes.core.
|
|
65
|
+
mdata: foxes.core.MData
|
|
66
66
|
The model data
|
|
67
|
-
fdata: foxes.core.
|
|
67
|
+
fdata: foxes.core.FData
|
|
68
68
|
The farm data
|
|
69
|
-
|
|
70
|
-
The point data
|
|
69
|
+
tdata: foxes.core.TData
|
|
70
|
+
The target point data
|
|
71
71
|
|
|
72
72
|
Returns
|
|
73
73
|
-------
|
|
@@ -69,9 +69,9 @@ class CentreRotor(RotorModel):
|
|
|
69
69
|
----------
|
|
70
70
|
algo: foxes.core.Algorithm
|
|
71
71
|
The calculation algorithm
|
|
72
|
-
mdata: foxes.core.
|
|
72
|
+
mdata: foxes.core.MData
|
|
73
73
|
The model data
|
|
74
|
-
fdata: foxes.core.
|
|
74
|
+
fdata: foxes.core.FData
|
|
75
75
|
The farm data
|
|
76
76
|
|
|
77
77
|
Returns
|
|
@@ -90,7 +90,7 @@ class CentreRotor(RotorModel):
|
|
|
90
90
|
fdata,
|
|
91
91
|
rpoint_results,
|
|
92
92
|
weights,
|
|
93
|
-
|
|
93
|
+
downwind_index=None,
|
|
94
94
|
copy_to_ambient=False,
|
|
95
95
|
):
|
|
96
96
|
"""
|
|
@@ -106,9 +106,9 @@ class CentreRotor(RotorModel):
|
|
|
106
106
|
----------
|
|
107
107
|
algo: foxes.core.Algorithm
|
|
108
108
|
The calculation algorithm
|
|
109
|
-
mdata: foxes.core.
|
|
109
|
+
mdata: foxes.core.MData
|
|
110
110
|
The model data
|
|
111
|
-
fdata: foxes.core.
|
|
111
|
+
fdata: foxes.core.FData
|
|
112
112
|
The farm data
|
|
113
113
|
rpoint_results: dict
|
|
114
114
|
The results at rotor points. Keys: variable str.
|
|
@@ -117,25 +117,21 @@ class CentreRotor(RotorModel):
|
|
|
117
117
|
Else: (n_states, 1, n_rpoints)
|
|
118
118
|
weights: numpy.ndarray
|
|
119
119
|
The rotor point weights, shape: (n_rpoints,)
|
|
120
|
-
|
|
121
|
-
The
|
|
122
|
-
copy_to_ambient: bool
|
|
120
|
+
downwind_index: int, optional
|
|
121
|
+
The index in the downwind order
|
|
122
|
+
copy_to_ambient: bool
|
|
123
123
|
If `True`, the fdata results are copied to ambient
|
|
124
124
|
variables after calculation
|
|
125
125
|
|
|
126
126
|
"""
|
|
127
127
|
if len(weights) > 1:
|
|
128
128
|
return super().eval_rpoint_results(
|
|
129
|
-
algo, mdata, fdata, rpoint_results, weights,
|
|
129
|
+
algo, mdata, fdata, rpoint_results, weights, downwind_index
|
|
130
130
|
)
|
|
131
131
|
|
|
132
132
|
n_states = mdata.n_states
|
|
133
133
|
n_turbines = algo.n_turbines
|
|
134
134
|
|
|
135
|
-
stsel = None
|
|
136
|
-
if states_turbine is not None:
|
|
137
|
-
stsel = (np.arange(n_states), states_turbine)
|
|
138
|
-
|
|
139
135
|
uvp = None
|
|
140
136
|
uv = None
|
|
141
137
|
if (
|
|
@@ -160,11 +156,11 @@ class CentreRotor(RotorModel):
|
|
|
160
156
|
if v == FV.WD or v == FV.YAW:
|
|
161
157
|
if wd is None:
|
|
162
158
|
wd = uv2wd(uv, axis=-1)
|
|
163
|
-
self._set_res(fdata, v, wd,
|
|
159
|
+
self._set_res(fdata, v, wd, downwind_index)
|
|
164
160
|
vdone.append(v)
|
|
165
161
|
|
|
166
162
|
elif v == FV.WS:
|
|
167
|
-
self._set_res(fdata, v, ws[:, :, 0],
|
|
163
|
+
self._set_res(fdata, v, ws[:, :, 0], downwind_index)
|
|
168
164
|
del ws
|
|
169
165
|
vdone.append(v)
|
|
170
166
|
del uv, wd
|
|
@@ -174,17 +170,17 @@ class CentreRotor(RotorModel):
|
|
|
174
170
|
or FV.REWS2 in self.calc_vars
|
|
175
171
|
or FV.REWS3 in self.calc_vars
|
|
176
172
|
):
|
|
177
|
-
if
|
|
173
|
+
if downwind_index is None:
|
|
178
174
|
yaw = fdata[FV.YAW]
|
|
179
175
|
else:
|
|
180
|
-
yaw = fdata[FV.YAW][
|
|
176
|
+
yaw = fdata[FV.YAW][:, downwind_index, None]
|
|
181
177
|
nax = wd2uv(yaw, axis=-1)
|
|
182
178
|
wsp = np.einsum("stpd,std->stp", uvp, nax)
|
|
183
179
|
|
|
184
180
|
for v in self.calc_vars:
|
|
185
181
|
if v == FV.REWS or v == FV.REWS2 or v == FV.REWS3:
|
|
186
182
|
rews = wsp[:, :, 0]
|
|
187
|
-
self._set_res(fdata, v, rews,
|
|
183
|
+
self._set_res(fdata, v, rews, downwind_index)
|
|
188
184
|
del rews
|
|
189
185
|
vdone.append(v)
|
|
190
186
|
|
|
@@ -194,7 +190,7 @@ class CentreRotor(RotorModel):
|
|
|
194
190
|
for v in self.calc_vars:
|
|
195
191
|
if v not in vdone:
|
|
196
192
|
res = rpoint_results[v][:, :, 0]
|
|
197
|
-
self._set_res(fdata, v, res,
|
|
193
|
+
self._set_res(fdata, v, res, downwind_index)
|
|
198
194
|
del res
|
|
199
195
|
if copy_to_ambient and v in FV.var2amb:
|
|
200
196
|
fdata[FV.var2amb[v]] = fdata[v].copy()
|
|
@@ -54,7 +54,8 @@ class GridRotor(RotorModel):
|
|
|
54
54
|
self.nint = nint
|
|
55
55
|
|
|
56
56
|
def __repr__(self):
|
|
57
|
-
|
|
57
|
+
r = "" if self.reduce else ", reduce=False"
|
|
58
|
+
return f"{type(self).__name__}(n={self.n}){r}"
|
|
58
59
|
|
|
59
60
|
def initialize(self, algo, verbosity=0):
|
|
60
61
|
"""
|
|
@@ -51,7 +51,8 @@ class LevelRotor(RotorModel):
|
|
|
51
51
|
self.nint = nint
|
|
52
52
|
|
|
53
53
|
def __repr__(self):
|
|
54
|
-
|
|
54
|
+
r = "" if self.reduce else ", reduce=False"
|
|
55
|
+
return f"{type(self).__name__}(n={self.n}){r}"
|
|
55
56
|
|
|
56
57
|
def initialize(self, algo, verbosity=0):
|
|
57
58
|
"""
|
|
@@ -16,7 +16,7 @@ class Calculator(TurbineModel):
|
|
|
16
16
|
func: Function
|
|
17
17
|
The function: f(in0, in1, ..., stsel) -> (out0, ou1, ...)
|
|
18
18
|
where inX and outY are numpy.ndarrays and
|
|
19
|
-
st_sel is the
|
|
19
|
+
st_sel is the state-turbine selection slice or array.
|
|
20
20
|
All arrays have shape (n_states, n_turbines).
|
|
21
21
|
|
|
22
22
|
:group: models.turbine_models
|
|
@@ -36,7 +36,7 @@ class Calculator(TurbineModel):
|
|
|
36
36
|
func: Function
|
|
37
37
|
The function: f(in0, in1, ..., stsel) -> (out0, ou1, ...)
|
|
38
38
|
where inX and outY are numpy.ndarrays and
|
|
39
|
-
st_sel is the
|
|
39
|
+
st_sel is the state-turbine selection slice or array.
|
|
40
40
|
All arrays have shape (n_states, n_turbines).
|
|
41
41
|
kwargs: dict, optional
|
|
42
42
|
Additional arguments for TurbineModel
|
|
@@ -47,6 +47,10 @@ class Calculator(TurbineModel):
|
|
|
47
47
|
self.out_vars = out_vars
|
|
48
48
|
self.func = func
|
|
49
49
|
|
|
50
|
+
def __repr__(self):
|
|
51
|
+
a = f"{self.in_vars}, {self.out_vars}"
|
|
52
|
+
return f"{type(self).__name__}({a})"
|
|
53
|
+
|
|
50
54
|
def output_farm_vars(self, algo):
|
|
51
55
|
"""
|
|
52
56
|
The variables which are being modified by the model.
|
|
@@ -65,7 +69,7 @@ class Calculator(TurbineModel):
|
|
|
65
69
|
return self.out_vars
|
|
66
70
|
|
|
67
71
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
68
|
-
"""
|
|
72
|
+
"""
|
|
69
73
|
The main model calculation.
|
|
70
74
|
|
|
71
75
|
This function is executed on a single chunk of data,
|
|
@@ -75,13 +79,13 @@ class Calculator(TurbineModel):
|
|
|
75
79
|
----------
|
|
76
80
|
algo: foxes.core.Algorithm
|
|
77
81
|
The calculation algorithm
|
|
78
|
-
mdata: foxes.core.
|
|
82
|
+
mdata: foxes.core.MData
|
|
79
83
|
The model data
|
|
80
|
-
fdata: foxes.core.
|
|
84
|
+
fdata: foxes.core.FData
|
|
81
85
|
The farm data
|
|
82
|
-
st_sel: numpy.ndarray of bool
|
|
86
|
+
st_sel: slice or numpy.ndarray of bool
|
|
83
87
|
The state-turbine selection,
|
|
84
|
-
shape: (n_states, n_turbines)
|
|
88
|
+
for shape: (n_states, n_turbines)
|
|
85
89
|
|
|
86
90
|
Returns
|
|
87
91
|
-------
|
|
@@ -51,10 +51,12 @@ class kTI(TurbineModel):
|
|
|
51
51
|
setattr(self, FV.KB, 0 if kb is None else kb)
|
|
52
52
|
|
|
53
53
|
def __repr__(self):
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
kti = getattr(self, FV.KTI)
|
|
55
|
+
kb = getattr(self, FV.KB)
|
|
56
|
+
ti = getattr(self, self.ti_var)
|
|
57
|
+
tiv = f", ti_val={ti}" if ti is not None else ""
|
|
58
|
+
a = f"kTI={kti}, kb={kb}, ti_var={self.ti_var}{tiv}, k_var={self.k_var}"
|
|
59
|
+
return f"{type(self).__name__}({a})"
|
|
58
60
|
|
|
59
61
|
def output_farm_vars(self, algo):
|
|
60
62
|
"""
|
|
@@ -74,7 +76,7 @@ class kTI(TurbineModel):
|
|
|
74
76
|
return [self.k_var]
|
|
75
77
|
|
|
76
78
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
77
|
-
"""
|
|
79
|
+
"""
|
|
78
80
|
The main model calculation.
|
|
79
81
|
|
|
80
82
|
This function is executed on a single chunk of data,
|
|
@@ -84,13 +86,13 @@ class kTI(TurbineModel):
|
|
|
84
86
|
----------
|
|
85
87
|
algo: foxes.core.Algorithm
|
|
86
88
|
The calculation algorithm
|
|
87
|
-
mdata: foxes.core.
|
|
89
|
+
mdata: foxes.core.MData
|
|
88
90
|
The model data
|
|
89
|
-
fdata: foxes.core.
|
|
91
|
+
fdata: foxes.core.FData
|
|
90
92
|
The farm data
|
|
91
|
-
st_sel: numpy.ndarray of bool
|
|
93
|
+
st_sel: slice or numpy.ndarray of bool
|
|
92
94
|
The state-turbine selection,
|
|
93
|
-
shape: (n_states, n_turbines)
|
|
95
|
+
for shape: (n_states, n_turbines)
|
|
94
96
|
|
|
95
97
|
Returns
|
|
96
98
|
-------
|
|
@@ -99,7 +101,7 @@ class kTI(TurbineModel):
|
|
|
99
101
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
100
102
|
|
|
101
103
|
"""
|
|
102
|
-
|
|
104
|
+
kti = self.get_data(
|
|
103
105
|
FV.KTI, FC.STATE_TURBINE, lookup="sf", fdata=fdata, upcast=True
|
|
104
106
|
)[st_sel]
|
|
105
107
|
kb = self.get_data(
|
|
@@ -113,6 +115,6 @@ class kTI(TurbineModel):
|
|
|
113
115
|
self.k_var, np.zeros((fdata.n_states, fdata.n_turbines), dtype=FC.DTYPE)
|
|
114
116
|
)
|
|
115
117
|
|
|
116
|
-
k[st_sel] =
|
|
118
|
+
k[st_sel] = kti * ti + kb
|
|
117
119
|
|
|
118
120
|
return {self.k_var: k}
|