foxes 1.0__py3-none-any.whl → 1.1.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.
- docs/source/conf.py +0 -1
- examples/states_lookup_table/run.py +1 -1
- examples/timeseries/run.py +11 -4
- foxes/algorithms/downwind/downwind.py +18 -13
- foxes/algorithms/downwind/models/farm_wakes_calc.py +1 -1
- foxes/algorithms/downwind/models/init_farm_data.py +1 -1
- foxes/algorithms/downwind/models/point_wakes_calc.py +1 -1
- foxes/algorithms/downwind/models/reorder_farm_output.py +1 -1
- foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +1 -1
- foxes/algorithms/iterative/iterative.py +1 -1
- foxes/algorithms/iterative/models/farm_wakes_calc.py +1 -1
- foxes/algorithms/iterative/models/urelax.py +3 -3
- foxes/algorithms/sequential/models/plugin.py +4 -4
- foxes/algorithms/sequential/models/seq_state.py +1 -1
- foxes/constants.py +5 -5
- foxes/core/algorithm.py +2 -2
- foxes/core/data_calc_model.py +2 -2
- foxes/core/engine.py +20 -10
- foxes/core/farm_controller.py +3 -3
- foxes/core/farm_data_model.py +1 -1
- foxes/core/ground_model.py +2 -2
- foxes/core/model.py +122 -108
- foxes/core/partial_wakes_model.py +1 -1
- foxes/core/point_data_model.py +2 -2
- foxes/core/states.py +1 -1
- foxes/core/turbine_type.py +2 -2
- foxes/core/wake_frame.py +8 -30
- foxes/core/wake_model.py +3 -2
- foxes/core/wake_superposition.py +1 -1
- foxes/data/windio/windio_5turbines_timeseries.yaml +9 -15
- foxes/engines/__init__.py +1 -0
- foxes/engines/dask.py +13 -6
- foxes/engines/multiprocess.py +5 -8
- foxes/engines/numpy.py +8 -26
- foxes/engines/pool.py +10 -24
- foxes/engines/ray.py +79 -0
- foxes/engines/single.py +3 -1
- foxes/input/farm_layout/from_json.py +1 -1
- foxes/input/states/__init__.py +1 -0
- foxes/input/states/field_data_nc.py +4 -4
- foxes/input/states/multi_height.py +4 -4
- foxes/input/states/scan_ws.py +1 -1
- foxes/input/states/single.py +1 -1
- foxes/input/states/slice_data_nc.py +681 -0
- foxes/input/states/states_table.py +3 -3
- foxes/input/windio/__init__.py +1 -1
- foxes/input/windio/read_attributes.py +8 -2
- foxes/input/windio/read_fields.py +3 -0
- foxes/input/windio/read_outputs.py +8 -2
- foxes/input/windio/windio.py +6 -2
- foxes/models/farm_models/turbine2farm.py +1 -1
- foxes/models/ground_models/wake_mirror.py +2 -2
- foxes/models/model_book.py +29 -2
- foxes/models/partial_wakes/axiwake.py +3 -3
- foxes/models/partial_wakes/top_hat.py +2 -2
- foxes/models/point_models/set_uniform_data.py +1 -1
- foxes/models/point_models/tke2ti.py +1 -1
- foxes/models/point_models/wake_deltas.py +1 -1
- foxes/models/rotor_models/grid.py +2 -2
- foxes/models/turbine_models/calculator.py +4 -4
- foxes/models/turbine_models/kTI_model.py +22 -6
- foxes/models/turbine_models/lookup_table.py +3 -2
- foxes/models/turbine_types/PCt_file.py +5 -5
- foxes/models/turbine_types/PCt_from_two.py +5 -5
- foxes/models/turbine_types/TBL_file.py +80 -0
- foxes/models/turbine_types/__init__.py +1 -0
- foxes/models/turbine_types/lookup.py +5 -5
- foxes/models/turbine_types/null_type.py +3 -3
- foxes/models/turbine_types/wsrho2PCt_from_two.py +7 -7
- foxes/models/turbine_types/wsti2PCt_from_two.py +9 -9
- foxes/models/vertical_profiles/__init__.py +1 -1
- foxes/models/wake_frames/dynamic_wakes.py +2 -2
- foxes/models/wake_frames/farm_order.py +2 -2
- foxes/models/wake_frames/rotor_wd.py +2 -2
- foxes/models/wake_frames/seq_dynamic_wakes.py +5 -11
- foxes/models/wake_frames/streamlines.py +2 -2
- foxes/models/wake_frames/timelines.py +2 -2
- foxes/models/wake_frames/yawed_wakes.py +3 -3
- foxes/models/wake_models/dist_sliced.py +1 -1
- foxes/models/wake_models/induction/rankine_half_body.py +1 -1
- foxes/models/wake_models/induction/rathmann.py +76 -22
- foxes/models/wake_models/induction/self_similar.py +76 -26
- foxes/models/wake_models/induction/vortex_sheet.py +84 -46
- foxes/models/wake_models/ti/crespo_hernandez.py +6 -4
- foxes/models/wake_models/ti/iec_ti.py +7 -5
- foxes/models/wake_models/wind/bastankhah14.py +6 -4
- foxes/models/wake_models/wind/bastankhah16.py +9 -9
- foxes/models/wake_models/wind/jensen.py +3 -2
- foxes/models/wake_models/wind/turbopark.py +14 -11
- foxes/models/wake_superpositions/ti_linear.py +1 -1
- foxes/models/wake_superpositions/ti_max.py +1 -1
- foxes/models/wake_superpositions/ti_pow.py +1 -1
- foxes/models/wake_superpositions/ti_quadratic.py +1 -1
- foxes/models/wake_superpositions/ws_linear.py +8 -7
- foxes/models/wake_superpositions/ws_max.py +8 -7
- foxes/models/wake_superpositions/ws_pow.py +8 -7
- foxes/models/wake_superpositions/ws_product.py +5 -5
- foxes/models/wake_superpositions/ws_quadratic.py +8 -7
- foxes/output/farm_layout.py +14 -10
- foxes/output/farm_results_eval.py +1 -1
- foxes/output/grids.py +1 -1
- foxes/output/results_writer.py +2 -2
- foxes/output/rose_plot.py +3 -3
- foxes/output/seq_plugins/seq_flow_ani_plugin.py +2 -2
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +2 -2
- foxes/output/state_turbine_map.py +1 -1
- foxes/utils/abl/neutral.py +2 -2
- foxes/utils/abl/stable.py +2 -2
- foxes/utils/abl/unstable.py +2 -2
- foxes/utils/data_book.py +1 -1
- foxes/utils/dict.py +23 -0
- foxes/utils/exec_python.py +1 -1
- foxes/utils/factory.py +29 -1
- foxes/utils/geom2d/circle.py +1 -1
- foxes/utils/geom2d/polygon.py +1 -1
- foxes/utils/geopandas_utils.py +2 -2
- foxes/utils/load.py +2 -2
- foxes/utils/pandas_helpers.py +1 -1
- foxes/utils/xarray_utils.py +1 -1
- foxes/variables.py +3 -3
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/METADATA +8 -6
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/RECORD +127 -125
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/WHEEL +1 -1
- foxes/utils/geopandas_helpers.py +0 -294
- /examples/{induction_RHB → induction}/run.py +0 -0
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/LICENSE +0 -0
- {foxes-1.0.dist-info → foxes-1.1.1.dist-info}/top_level.txt +0 -0
|
@@ -37,11 +37,11 @@ class WsTI2PCtFromTwo(TurbineType):
|
|
|
37
37
|
rpars_ct: dict, optional
|
|
38
38
|
Parameters for pandas ct file reading
|
|
39
39
|
ipars_P: dict, optional
|
|
40
|
-
Parameters for scipy.interpolate.interpn
|
|
40
|
+
Parameters for scipy.interpolate.interpn
|
|
41
41
|
ipars_ct: dict, optional
|
|
42
|
-
Parameters for scipy.interpolate.interpn
|
|
42
|
+
Parameters for scipy.interpolate.interpn
|
|
43
43
|
rho: float
|
|
44
|
-
The air
|
|
44
|
+
The air density for which the data is valid
|
|
45
45
|
or None for no correction
|
|
46
46
|
|
|
47
47
|
:group: models.turbine_types
|
|
@@ -73,7 +73,7 @@ class WsTI2PCtFromTwo(TurbineType):
|
|
|
73
73
|
data_source_ct: str or pandas.DataFrame
|
|
74
74
|
The file path for the ct curve, static name, or data
|
|
75
75
|
rho: float, optional
|
|
76
|
-
The air
|
|
76
|
+
The air density for which the data is valid
|
|
77
77
|
or None for no correction
|
|
78
78
|
p_ct: float
|
|
79
79
|
The exponent for yaw dependency of ct
|
|
@@ -88,9 +88,9 @@ class WsTI2PCtFromTwo(TurbineType):
|
|
|
88
88
|
pd_file_read_pars_ct: dict
|
|
89
89
|
Parameters for pandas ct file reading
|
|
90
90
|
interpn_pars_P: dict, optional
|
|
91
|
-
Parameters for scipy.interpolate.interpn
|
|
91
|
+
Parameters for scipy.interpolate.interpn
|
|
92
92
|
interpn_pars_ct: dict, optional
|
|
93
|
-
Parameters for scipy.interpolate.interpn
|
|
93
|
+
Parameters for scipy.interpolate.interpn
|
|
94
94
|
parameters: dict, optional
|
|
95
95
|
Additional parameters for TurbineType class
|
|
96
96
|
|
|
@@ -129,7 +129,7 @@ class WsTI2PCtFromTwo(TurbineType):
|
|
|
129
129
|
|
|
130
130
|
def needs_rews2(self):
|
|
131
131
|
"""
|
|
132
|
-
Returns flag for
|
|
132
|
+
Returns flag for requiring REWS2 variable
|
|
133
133
|
|
|
134
134
|
Returns
|
|
135
135
|
-------
|
|
@@ -141,7 +141,7 @@ class WsTI2PCtFromTwo(TurbineType):
|
|
|
141
141
|
|
|
142
142
|
def needs_rews3(self):
|
|
143
143
|
"""
|
|
144
|
-
Returns flag for
|
|
144
|
+
Returns flag for requiring REWS3 variable
|
|
145
145
|
|
|
146
146
|
Returns
|
|
147
147
|
-------
|
|
@@ -241,7 +241,7 @@ class WsTI2PCtFromTwo(TurbineType):
|
|
|
241
241
|
print()
|
|
242
242
|
|
|
243
243
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
244
|
-
"""
|
|
244
|
+
"""
|
|
245
245
|
The main model calculation.
|
|
246
246
|
|
|
247
247
|
This function is executed on a single chunk of data,
|
|
@@ -120,7 +120,7 @@ class DynamicWakes(WakeFrame):
|
|
|
120
120
|
self.UPDATE = self.var("update")
|
|
121
121
|
|
|
122
122
|
def calc_order(self, algo, mdata, fdata):
|
|
123
|
-
"""
|
|
123
|
+
"""
|
|
124
124
|
Calculates the order of turbine evaluation.
|
|
125
125
|
|
|
126
126
|
This function is executed on a single chunk of data,
|
|
@@ -347,7 +347,7 @@ class DynamicWakes(WakeFrame):
|
|
|
347
347
|
The target point data
|
|
348
348
|
downwind_index: int
|
|
349
349
|
The index of the wake causing turbine
|
|
350
|
-
in the
|
|
350
|
+
in the downwind order
|
|
351
351
|
|
|
352
352
|
Returns
|
|
353
353
|
-------
|
|
@@ -69,7 +69,7 @@ class FarmOrder(WakeFrame):
|
|
|
69
69
|
return [self.base_frame]
|
|
70
70
|
|
|
71
71
|
def calc_order(self, algo, mdata, fdata):
|
|
72
|
-
"""
|
|
72
|
+
"""
|
|
73
73
|
Calculates the order of turbine evaluation.
|
|
74
74
|
|
|
75
75
|
This function is executed on a single chunk of data,
|
|
@@ -118,7 +118,7 @@ class FarmOrder(WakeFrame):
|
|
|
118
118
|
The target point data
|
|
119
119
|
downwind_index: int
|
|
120
120
|
The index of the wake causing turbine
|
|
121
|
-
in the
|
|
121
|
+
in the downwind order
|
|
122
122
|
|
|
123
123
|
Returns
|
|
124
124
|
-------
|
|
@@ -36,7 +36,7 @@ class RotorWD(WakeFrame):
|
|
|
36
36
|
self.var_wd = var_wd
|
|
37
37
|
|
|
38
38
|
def calc_order(self, algo, mdata, fdata):
|
|
39
|
-
"""
|
|
39
|
+
"""
|
|
40
40
|
Calculates the order of turbine evaluation.
|
|
41
41
|
|
|
42
42
|
This function is executed on a single chunk of data,
|
|
@@ -86,7 +86,7 @@ class RotorWD(WakeFrame):
|
|
|
86
86
|
The target point data
|
|
87
87
|
downwind_index: int
|
|
88
88
|
The index of the wake causing turbine
|
|
89
|
-
in the
|
|
89
|
+
in the downwind order
|
|
90
90
|
|
|
91
91
|
Returns
|
|
92
92
|
-------
|
|
@@ -96,7 +96,7 @@ class SeqDynamicWakes(FarmOrder):
|
|
|
96
96
|
)
|
|
97
97
|
|
|
98
98
|
def calc_order(self, algo, mdata, fdata):
|
|
99
|
-
"""
|
|
99
|
+
"""
|
|
100
100
|
Calculates the order of turbine evaluation.
|
|
101
101
|
|
|
102
102
|
This function is executed on a single chunk of data,
|
|
@@ -142,7 +142,7 @@ class SeqDynamicWakes(FarmOrder):
|
|
|
142
142
|
The target point data
|
|
143
143
|
downwind_index: int
|
|
144
144
|
The index of the wake causing turbine
|
|
145
|
-
in the
|
|
145
|
+
in the downwind order
|
|
146
146
|
|
|
147
147
|
Returns
|
|
148
148
|
-------
|
|
@@ -230,7 +230,6 @@ class SeqDynamicWakes(FarmOrder):
|
|
|
230
230
|
tdata,
|
|
231
231
|
target,
|
|
232
232
|
states0=None,
|
|
233
|
-
upcast=False,
|
|
234
233
|
):
|
|
235
234
|
"""
|
|
236
235
|
Return data that is required for computing the
|
|
@@ -253,17 +252,12 @@ class SeqDynamicWakes(FarmOrder):
|
|
|
253
252
|
FC.STATE_TARGET, FC.STATE_TARGET_TPOINT
|
|
254
253
|
states0: numpy.ndarray, optional
|
|
255
254
|
The states of wake creation
|
|
256
|
-
upcast: bool
|
|
257
|
-
Flag for ensuring targets dimension,
|
|
258
|
-
otherwise dimension 1 is entered
|
|
259
255
|
|
|
260
256
|
Returns
|
|
261
257
|
-------
|
|
262
258
|
data: numpy.ndarray
|
|
263
259
|
Data for wake modelling, shape:
|
|
264
260
|
(n_states, n_turbines) or (n_states, n_target)
|
|
265
|
-
dims: tuple
|
|
266
|
-
The data dimensions
|
|
267
261
|
|
|
268
262
|
"""
|
|
269
263
|
if states0 is None and FC.STATE_SOURCE_ORDERI in tdata:
|
|
@@ -288,9 +282,9 @@ class SeqDynamicWakes(FarmOrder):
|
|
|
288
282
|
data = data[:, :, 0]
|
|
289
283
|
else:
|
|
290
284
|
data = np.einsum("stp,p->st", data, tdata[FC.TWEIGHTS])
|
|
291
|
-
return data
|
|
285
|
+
return data
|
|
292
286
|
elif target == FC.STATE_TARGET_TPOINT:
|
|
293
|
-
return data
|
|
287
|
+
return data
|
|
294
288
|
else:
|
|
295
289
|
raise ValueError(
|
|
296
290
|
f"Cannot handle target '{target}', choices are {FC.STATE_TARGET}, {FC.STATE_TARGET_TPOINT}"
|
|
@@ -298,7 +292,7 @@ class SeqDynamicWakes(FarmOrder):
|
|
|
298
292
|
|
|
299
293
|
else:
|
|
300
294
|
return super().get_wake_modelling_data(
|
|
301
|
-
algo, variable, downwind_index, fdata, tdata, target, states0
|
|
295
|
+
algo, variable, downwind_index, fdata, tdata, target, states0
|
|
302
296
|
)
|
|
303
297
|
|
|
304
298
|
def get_centreline_points(self, algo, mdata, fdata, downwind_index, x):
|
|
@@ -165,7 +165,7 @@ class Streamlines2D(WakeFrame):
|
|
|
165
165
|
return coos.reshape(n_states, n_targets, n_tpoints, 3)
|
|
166
166
|
|
|
167
167
|
def calc_order(self, algo, mdata, fdata):
|
|
168
|
-
"""
|
|
168
|
+
"""
|
|
169
169
|
Calculates the order of turbine evaluation.
|
|
170
170
|
|
|
171
171
|
This function is executed on a single chunk of data,
|
|
@@ -230,7 +230,7 @@ class Streamlines2D(WakeFrame):
|
|
|
230
230
|
The target point data
|
|
231
231
|
downwind_index: int
|
|
232
232
|
The index of the wake causing turbine
|
|
233
|
-
in the
|
|
233
|
+
in the downwind order
|
|
234
234
|
|
|
235
235
|
Returns
|
|
236
236
|
-------
|
|
@@ -264,7 +264,7 @@ class Timelines(WakeFrame):
|
|
|
264
264
|
self.timelines_data = data.pop("data")
|
|
265
265
|
|
|
266
266
|
def calc_order(self, algo, mdata, fdata):
|
|
267
|
-
"""
|
|
267
|
+
"""
|
|
268
268
|
Calculates the order of turbine evaluation.
|
|
269
269
|
|
|
270
270
|
This function is executed on a single chunk of data,
|
|
@@ -312,7 +312,7 @@ class Timelines(WakeFrame):
|
|
|
312
312
|
The target point data
|
|
313
313
|
downwind_index: int
|
|
314
314
|
The index of the wake causing turbine
|
|
315
|
-
in the
|
|
315
|
+
in the downwind order
|
|
316
316
|
|
|
317
317
|
Returns
|
|
318
318
|
-------
|
|
@@ -137,7 +137,7 @@ class YawedWakes(WakeFrame):
|
|
|
137
137
|
super().initialize(algo, verbosity, force)
|
|
138
138
|
|
|
139
139
|
def calc_order(self, algo, mdata, fdata):
|
|
140
|
-
"""
|
|
140
|
+
"""
|
|
141
141
|
Calculates the order of turbine evaluation.
|
|
142
142
|
|
|
143
143
|
This function is executed on a single chunk of data,
|
|
@@ -177,7 +177,7 @@ class YawedWakes(WakeFrame):
|
|
|
177
177
|
downwind_index=downwind_index,
|
|
178
178
|
accept_nan=False,
|
|
179
179
|
)
|
|
180
|
-
gamma
|
|
180
|
+
gamma = gamma * np.pi / 180
|
|
181
181
|
|
|
182
182
|
# get k:
|
|
183
183
|
k = self.wake_k(
|
|
@@ -248,7 +248,7 @@ class YawedWakes(WakeFrame):
|
|
|
248
248
|
The target point data
|
|
249
249
|
downwind_index: int
|
|
250
250
|
The index of the wake causing turbine
|
|
251
|
-
in the
|
|
251
|
+
in the downwind order
|
|
252
252
|
|
|
253
253
|
Returns
|
|
254
254
|
-------
|
|
@@ -142,7 +142,7 @@ class DistSlicedWakeModel(WakeModel):
|
|
|
142
142
|
The target point data
|
|
143
143
|
downwind_index: int
|
|
144
144
|
The index of the wake causing turbine
|
|
145
|
-
in the
|
|
145
|
+
in the downwind order
|
|
146
146
|
wake_coos: numpy.ndarray
|
|
147
147
|
The wake frame coordinates of the evaluation
|
|
148
148
|
points, shape: (n_states, n_targets, n_tpoints, 3)
|
|
@@ -134,7 +134,7 @@ class RankineHalfBody(TurbineInductionModel):
|
|
|
134
134
|
The target point data
|
|
135
135
|
downwind_index: int
|
|
136
136
|
The index of the wake causing turbine
|
|
137
|
-
in the
|
|
137
|
+
in the downwind order
|
|
138
138
|
wake_coos: numpy.ndarray
|
|
139
139
|
The wake frame coordinates of the evaluation
|
|
140
140
|
points, shape: (n_states, n_targets, n_tpoints, 3)
|
|
@@ -31,27 +31,35 @@ class Rathmann(TurbineInductionModel):
|
|
|
31
31
|
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
|
-
def __init__(
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
superposition="ws_linear",
|
|
37
|
+
induction="Madsen",
|
|
38
|
+
pre_rotor_only=False,
|
|
39
|
+
):
|
|
35
40
|
"""
|
|
36
41
|
Constructor.
|
|
37
42
|
|
|
38
43
|
Parameters
|
|
39
44
|
----------
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
superposition: str
|
|
46
|
+
The wind speed superposition
|
|
42
47
|
induction: foxes.core.AxialInductionModel or str
|
|
43
48
|
The induction model
|
|
49
|
+
pre_rotor_only: bool
|
|
50
|
+
Calculate only the pre-rotor region
|
|
44
51
|
|
|
45
52
|
"""
|
|
46
53
|
super().__init__()
|
|
47
54
|
self.induction = induction
|
|
48
55
|
self.pre_rotor_only = pre_rotor_only
|
|
56
|
+
self._superp_name = superposition
|
|
49
57
|
|
|
50
58
|
def __repr__(self):
|
|
51
59
|
iname = (
|
|
52
60
|
self.induction if isinstance(self.induction, str) else self.induction.name
|
|
53
61
|
)
|
|
54
|
-
return f"{type(self).__name__}(induction={iname})"
|
|
62
|
+
return f"{type(self).__name__}({self._superp_name}, induction={iname})"
|
|
55
63
|
|
|
56
64
|
def sub_models(self):
|
|
57
65
|
"""
|
|
@@ -63,7 +71,7 @@ class Rathmann(TurbineInductionModel):
|
|
|
63
71
|
All sub models
|
|
64
72
|
|
|
65
73
|
"""
|
|
66
|
-
return [self.induction]
|
|
74
|
+
return [self._superp, self.induction]
|
|
67
75
|
|
|
68
76
|
def initialize(self, algo, verbosity=0, force=False):
|
|
69
77
|
"""
|
|
@@ -79,6 +87,7 @@ class Rathmann(TurbineInductionModel):
|
|
|
79
87
|
Overwrite existing data
|
|
80
88
|
|
|
81
89
|
"""
|
|
90
|
+
self._superp = algo.mbook.wake_superpositions[self._superp_name]
|
|
82
91
|
if isinstance(self.induction, str):
|
|
83
92
|
self.induction = algo.mbook.axial_induction[self.induction]
|
|
84
93
|
super().initialize(algo, verbosity, force)
|
|
@@ -133,7 +142,7 @@ class Rathmann(TurbineInductionModel):
|
|
|
133
142
|
The target point data
|
|
134
143
|
downwind_index: int
|
|
135
144
|
The index of the wake causing turbine
|
|
136
|
-
in the
|
|
145
|
+
in the downwind order
|
|
137
146
|
wake_coos: numpy.ndarray
|
|
138
147
|
The wake frame coordinates of the evaluation
|
|
139
148
|
points, shape: (n_states, n_targets, n_tpoints, 3)
|
|
@@ -155,18 +164,6 @@ class Rathmann(TurbineInductionModel):
|
|
|
155
164
|
downwind_index=downwind_index,
|
|
156
165
|
)
|
|
157
166
|
|
|
158
|
-
# get ws:
|
|
159
|
-
ws = self.get_data(
|
|
160
|
-
FV.REWS,
|
|
161
|
-
FC.STATE_TARGET_TPOINT,
|
|
162
|
-
lookup="w",
|
|
163
|
-
algo=algo,
|
|
164
|
-
fdata=fdata,
|
|
165
|
-
tdata=tdata,
|
|
166
|
-
upcast=True,
|
|
167
|
-
downwind_index=downwind_index,
|
|
168
|
-
)
|
|
169
|
-
|
|
170
167
|
# get D
|
|
171
168
|
R = 0.5 * self.get_data(
|
|
172
169
|
FV.D,
|
|
@@ -203,8 +200,19 @@ class Rathmann(TurbineInductionModel):
|
|
|
203
200
|
if np.any(sp_sel):
|
|
204
201
|
xr = x_R[sp_sel]
|
|
205
202
|
a = self.induction.ct2a(ct[sp_sel])
|
|
206
|
-
blockage =
|
|
207
|
-
|
|
203
|
+
blockage = a * mu(xr) * G(xr, r_R[sp_sel]) # eqn 10
|
|
204
|
+
|
|
205
|
+
self._superp.add_wake(
|
|
206
|
+
algo,
|
|
207
|
+
mdata,
|
|
208
|
+
fdata,
|
|
209
|
+
tdata,
|
|
210
|
+
downwind_index,
|
|
211
|
+
sp_sel,
|
|
212
|
+
FV.WS,
|
|
213
|
+
wake_deltas[FV.WS],
|
|
214
|
+
-blockage,
|
|
215
|
+
)
|
|
208
216
|
|
|
209
217
|
# ws delta behind rotor
|
|
210
218
|
if not self.pre_rotor_only:
|
|
@@ -213,7 +221,53 @@ class Rathmann(TurbineInductionModel):
|
|
|
213
221
|
if np.any(sp_sel):
|
|
214
222
|
xr = x_R[sp_sel]
|
|
215
223
|
a = self.induction.ct2a(ct[sp_sel])
|
|
216
|
-
blockage =
|
|
217
|
-
|
|
224
|
+
blockage = a * mu(-xr) * G(-xr, r_R[sp_sel]) # eqn 10
|
|
225
|
+
|
|
226
|
+
self._superp.add_wake(
|
|
227
|
+
algo,
|
|
228
|
+
mdata,
|
|
229
|
+
fdata,
|
|
230
|
+
tdata,
|
|
231
|
+
downwind_index,
|
|
232
|
+
sp_sel,
|
|
233
|
+
FV.WS,
|
|
234
|
+
wake_deltas[FV.WS],
|
|
235
|
+
blockage,
|
|
236
|
+
)
|
|
218
237
|
|
|
219
238
|
return wake_deltas
|
|
239
|
+
|
|
240
|
+
def finalize_wake_deltas(
|
|
241
|
+
self,
|
|
242
|
+
algo,
|
|
243
|
+
mdata,
|
|
244
|
+
fdata,
|
|
245
|
+
amb_results,
|
|
246
|
+
wake_deltas,
|
|
247
|
+
):
|
|
248
|
+
"""
|
|
249
|
+
Finalize the wake calculation.
|
|
250
|
+
|
|
251
|
+
Modifies wake_deltas on the fly.
|
|
252
|
+
|
|
253
|
+
Parameters
|
|
254
|
+
----------
|
|
255
|
+
algo: foxes.core.Algorithm
|
|
256
|
+
The calculation algorithm
|
|
257
|
+
mdata: foxes.core.MData
|
|
258
|
+
The model data
|
|
259
|
+
fdata: foxes.core.FData
|
|
260
|
+
The farm data
|
|
261
|
+
amb_results: dict
|
|
262
|
+
The ambient results, key: variable name str,
|
|
263
|
+
values: numpy.ndarray with shape
|
|
264
|
+
(n_states, n_targets, n_tpoints)
|
|
265
|
+
wake_deltas: dict
|
|
266
|
+
The wake deltas object at the selected target
|
|
267
|
+
turbines. Key: variable str, value: numpy.ndarray
|
|
268
|
+
with shape (n_states, n_targets, n_tpoints)
|
|
269
|
+
|
|
270
|
+
"""
|
|
271
|
+
wake_deltas[FV.WS] = self._superp.calc_final_wake_delta(
|
|
272
|
+
algo, mdata, fdata, FV.WS, amb_results[FV.WS], wake_deltas[FV.WS]
|
|
273
|
+
)
|
|
@@ -38,30 +38,39 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
38
38
|
|
|
39
39
|
"""
|
|
40
40
|
|
|
41
|
-
def __init__(
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
superposition="ws_linear",
|
|
44
|
+
induction="Madsen",
|
|
45
|
+
gamma=1.1,
|
|
46
|
+
pre_rotor_only=False,
|
|
47
|
+
):
|
|
42
48
|
"""
|
|
43
49
|
Constructor.
|
|
44
50
|
|
|
45
51
|
Parameters
|
|
46
52
|
----------
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
superposition: str
|
|
54
|
+
The wind speed superposition.
|
|
49
55
|
induction: foxes.core.AxialInductionModel or str
|
|
50
56
|
The induction model
|
|
51
57
|
gamma: float, default=1.1
|
|
52
58
|
The parameter that multiplies Ct in the ct2a calculation
|
|
59
|
+
pre_rotor_only: bool
|
|
60
|
+
Calculate only the pre-rotor region
|
|
53
61
|
|
|
54
62
|
"""
|
|
55
63
|
super().__init__()
|
|
56
64
|
self.induction = induction
|
|
57
65
|
self.pre_rotor_only = pre_rotor_only
|
|
58
66
|
self.gamma = gamma
|
|
67
|
+
self._superp_name = superposition
|
|
59
68
|
|
|
60
69
|
def __repr__(self):
|
|
61
70
|
iname = (
|
|
62
71
|
self.induction if isinstance(self.induction, str) else self.induction.name
|
|
63
72
|
)
|
|
64
|
-
return f"{type(self).__name__}(
|
|
73
|
+
return f"{type(self).__name__}({self._superp_name}, induction={iname}, gamma={self.gamma})"
|
|
65
74
|
|
|
66
75
|
def sub_models(self):
|
|
67
76
|
"""
|
|
@@ -73,7 +82,7 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
73
82
|
All sub models
|
|
74
83
|
|
|
75
84
|
"""
|
|
76
|
-
return [self.induction]
|
|
85
|
+
return [self._superp, self.induction]
|
|
77
86
|
|
|
78
87
|
def initialize(self, algo, verbosity=0, force=False):
|
|
79
88
|
"""
|
|
@@ -89,6 +98,7 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
89
98
|
Overwrite existing data
|
|
90
99
|
|
|
91
100
|
"""
|
|
101
|
+
self._superp = algo.mbook.wake_superpositions[self._superp_name]
|
|
92
102
|
if isinstance(self.induction, str):
|
|
93
103
|
self.induction = algo.mbook.axial_induction[self.induction]
|
|
94
104
|
super().initialize(algo, verbosity, force)
|
|
@@ -163,7 +173,7 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
163
173
|
The target point data
|
|
164
174
|
downwind_index: int
|
|
165
175
|
The index of the wake causing turbine
|
|
166
|
-
in the
|
|
176
|
+
in the downwind order
|
|
167
177
|
wake_coos: numpy.ndarray
|
|
168
178
|
The wake frame coordinates of the evaluation
|
|
169
179
|
points, shape: (n_states, n_targets, n_tpoints, 3)
|
|
@@ -185,18 +195,6 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
185
195
|
downwind_index=downwind_index,
|
|
186
196
|
)
|
|
187
197
|
|
|
188
|
-
# get ws
|
|
189
|
-
ws = self.get_data(
|
|
190
|
-
FV.REWS,
|
|
191
|
-
FC.STATE_TARGET_TPOINT,
|
|
192
|
-
lookup="w",
|
|
193
|
-
algo=algo,
|
|
194
|
-
fdata=fdata,
|
|
195
|
-
tdata=tdata,
|
|
196
|
-
upcast=True,
|
|
197
|
-
downwind_index=downwind_index,
|
|
198
|
-
)
|
|
199
|
-
|
|
200
198
|
# get R
|
|
201
199
|
R = 0.5 * self.get_data(
|
|
202
200
|
FV.D,
|
|
@@ -218,10 +216,19 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
218
216
|
if np.any(sp_sel):
|
|
219
217
|
# velocity eqn 10 from [1]
|
|
220
218
|
xr = x_R[sp_sel]
|
|
221
|
-
blockage = (
|
|
222
|
-
|
|
219
|
+
blockage = self._a(ct[sp_sel], xr) * self._rad_fn(xr, r_R[sp_sel])
|
|
220
|
+
|
|
221
|
+
self._superp.add_wake(
|
|
222
|
+
algo,
|
|
223
|
+
mdata,
|
|
224
|
+
fdata,
|
|
225
|
+
tdata,
|
|
226
|
+
downwind_index,
|
|
227
|
+
sp_sel,
|
|
228
|
+
FV.WS,
|
|
229
|
+
wake_deltas[FV.WS],
|
|
230
|
+
-blockage,
|
|
223
231
|
)
|
|
224
|
-
wake_deltas[FV.WS][sp_sel] -= blockage
|
|
225
232
|
|
|
226
233
|
# set area behind to mirrored value EXCEPT for area behind turbine
|
|
227
234
|
if not self.pre_rotor_only:
|
|
@@ -229,11 +236,54 @@ class SelfSimilar(TurbineInductionModel):
|
|
|
229
236
|
if np.any(sp_sel):
|
|
230
237
|
# velocity eqn 10 from [1]
|
|
231
238
|
xr = x_R[sp_sel]
|
|
232
|
-
blockage = (
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
239
|
+
blockage = self._a(ct[sp_sel], -xr) * self._rad_fn(-xr, r_R[sp_sel])
|
|
240
|
+
|
|
241
|
+
# wdelta[sp_sel] += blockage
|
|
242
|
+
self._superp.add_wake(
|
|
243
|
+
algo,
|
|
244
|
+
mdata,
|
|
245
|
+
fdata,
|
|
246
|
+
tdata,
|
|
247
|
+
downwind_index,
|
|
248
|
+
sp_sel,
|
|
249
|
+
FV.WS,
|
|
250
|
+
wake_deltas[FV.WS],
|
|
251
|
+
blockage,
|
|
236
252
|
)
|
|
237
|
-
wake_deltas[FV.WS][sp_sel] += blockage
|
|
238
253
|
|
|
239
254
|
return wake_deltas
|
|
255
|
+
|
|
256
|
+
def finalize_wake_deltas(
|
|
257
|
+
self,
|
|
258
|
+
algo,
|
|
259
|
+
mdata,
|
|
260
|
+
fdata,
|
|
261
|
+
amb_results,
|
|
262
|
+
wake_deltas,
|
|
263
|
+
):
|
|
264
|
+
"""
|
|
265
|
+
Finalize the wake calculation.
|
|
266
|
+
|
|
267
|
+
Modifies wake_deltas on the fly.
|
|
268
|
+
|
|
269
|
+
Parameters
|
|
270
|
+
----------
|
|
271
|
+
algo: foxes.core.Algorithm
|
|
272
|
+
The calculation algorithm
|
|
273
|
+
mdata: foxes.core.MData
|
|
274
|
+
The model data
|
|
275
|
+
fdata: foxes.core.FData
|
|
276
|
+
The farm data
|
|
277
|
+
amb_results: dict
|
|
278
|
+
The ambient results, key: variable name str,
|
|
279
|
+
values: numpy.ndarray with shape
|
|
280
|
+
(n_states, n_targets, n_tpoints)
|
|
281
|
+
wake_deltas: dict
|
|
282
|
+
The wake deltas object at the selected target
|
|
283
|
+
turbines. Key: variable str, value: numpy.ndarray
|
|
284
|
+
with shape (n_states, n_targets, n_tpoints)
|
|
285
|
+
|
|
286
|
+
"""
|
|
287
|
+
wake_deltas[FV.WS] = self._superp.calc_final_wake_delta(
|
|
288
|
+
algo, mdata, fdata, FV.WS, amb_results[FV.WS], wake_deltas[FV.WS]
|
|
289
|
+
)
|