foxes 1.3__py3-none-any.whl → 1.4__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 +3 -3
- examples/abl_states/run.py +2 -2
- examples/compare_rotors_pwakes/run.py +1 -1
- examples/compare_wakes/run.py +1 -2
- examples/dyn_wakes/run.py +29 -6
- examples/induction/run.py +3 -3
- examples/multi_height/run.py +1 -1
- examples/power_mask/run.py +2 -2
- examples/quickstart/run.py +0 -1
- examples/random_timeseries/run.py +3 -4
- examples/scan_row/run.py +3 -3
- examples/sequential/run.py +33 -10
- examples/single_state/run.py +3 -4
- examples/states_lookup_table/run.py +3 -3
- examples/streamline_wakes/run.py +27 -4
- examples/tab_file/run.py +3 -3
- examples/timelines/run.py +29 -5
- examples/timeseries/run.py +3 -3
- examples/timeseries_slurm/run.py +3 -3
- examples/wind_rose/run.py +3 -3
- examples/yawed_wake/run.py +16 -8
- foxes/__init__.py +21 -17
- foxes/algorithms/__init__.py +6 -6
- foxes/algorithms/downwind/__init__.py +2 -2
- foxes/algorithms/downwind/downwind.py +44 -12
- foxes/algorithms/downwind/models/__init__.py +6 -6
- foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -9
- foxes/algorithms/downwind/models/init_farm_data.py +0 -1
- foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
- foxes/algorithms/downwind/models/set_amb_point_results.py +6 -6
- foxes/algorithms/iterative/__init__.py +7 -3
- foxes/algorithms/iterative/iterative.py +1 -2
- foxes/algorithms/iterative/models/__init__.py +7 -3
- foxes/algorithms/iterative/models/farm_wakes_calc.py +9 -5
- foxes/algorithms/sequential/__init__.py +3 -3
- foxes/algorithms/sequential/models/__init__.py +2 -2
- foxes/algorithms/sequential/sequential.py +3 -4
- foxes/config/__init__.py +5 -1
- foxes/constants.py +16 -0
- foxes/core/__init__.py +45 -22
- foxes/core/algorithm.py +0 -1
- foxes/core/data.py +19 -18
- foxes/core/engine.py +9 -13
- foxes/core/farm_controller.py +2 -2
- foxes/core/ground_model.py +4 -13
- foxes/core/model.py +5 -5
- foxes/core/partial_wakes_model.py +147 -10
- foxes/core/point_data_model.py +2 -3
- foxes/core/rotor_model.py +3 -3
- foxes/core/states.py +2 -3
- foxes/core/turbine.py +2 -1
- foxes/core/wake_deflection.py +130 -0
- foxes/core/wake_model.py +222 -9
- foxes/core/wake_superposition.py +122 -4
- foxes/core/wind_farm.py +6 -6
- foxes/data/__init__.py +7 -2
- foxes/data/states/weibull_sectors_12.csv +13 -0
- foxes/data/states/weibull_sectors_12.nc +0 -0
- foxes/engines/__init__.py +14 -15
- foxes/engines/dask.py +39 -14
- foxes/engines/numpy.py +0 -3
- foxes/input/__init__.py +3 -3
- foxes/input/farm_layout/__init__.py +8 -8
- foxes/input/farm_layout/from_csv.py +1 -1
- foxes/input/farm_layout/ring.py +0 -1
- foxes/input/states/__init__.py +22 -12
- foxes/input/states/create/__init__.py +3 -2
- foxes/input/states/field_data_nc.py +10 -24
- foxes/input/states/multi_height.py +9 -6
- foxes/input/states/one_point_flow.py +0 -4
- foxes/input/states/single.py +1 -1
- foxes/input/states/states_table.py +10 -7
- foxes/input/states/weibull_sectors.py +225 -0
- foxes/input/states/wrg_states.py +7 -5
- foxes/input/yaml/__init__.py +9 -3
- foxes/input/yaml/dict.py +19 -19
- foxes/input/yaml/windio/__init__.py +10 -5
- foxes/input/yaml/windio/read_attributes.py +2 -2
- foxes/input/yaml/windio/read_farm.py +5 -5
- foxes/input/yaml/windio/read_fields.py +4 -2
- foxes/input/yaml/windio/read_site.py +52 -0
- foxes/input/yaml/windio/windio.py +1 -1
- foxes/models/__init__.py +15 -14
- foxes/models/axial_induction/__init__.py +2 -2
- foxes/models/farm_controllers/__init__.py +1 -1
- foxes/models/farm_models/__init__.py +1 -1
- foxes/models/ground_models/__init__.py +3 -2
- foxes/models/ground_models/wake_mirror.py +3 -3
- foxes/models/model_book.py +175 -49
- foxes/models/partial_wakes/__init__.py +6 -6
- foxes/models/partial_wakes/axiwake.py +30 -5
- foxes/models/partial_wakes/centre.py +47 -0
- foxes/models/partial_wakes/rotor_points.py +41 -11
- foxes/models/partial_wakes/segregated.py +2 -25
- foxes/models/partial_wakes/top_hat.py +27 -2
- foxes/models/point_models/__init__.py +4 -4
- foxes/models/rotor_models/__init__.py +3 -3
- foxes/models/turbine_models/__init__.py +11 -11
- foxes/models/turbine_models/set_farm_vars.py +0 -1
- foxes/models/turbine_types/PCt_file.py +0 -2
- foxes/models/turbine_types/PCt_from_two.py +0 -2
- foxes/models/turbine_types/__init__.py +9 -9
- foxes/models/vertical_profiles/__init__.py +7 -7
- foxes/models/wake_deflections/__init__.py +3 -0
- foxes/models/{wake_frames/yawed_wakes.py → wake_deflections/bastankhah2016.py} +32 -111
- foxes/models/wake_deflections/jimenez.py +277 -0
- foxes/models/wake_deflections/no_deflection.py +94 -0
- foxes/models/wake_frames/__init__.py +6 -7
- foxes/models/wake_frames/dynamic_wakes.py +12 -3
- foxes/models/wake_frames/rotor_wd.py +3 -1
- foxes/models/wake_frames/seq_dynamic_wakes.py +41 -7
- foxes/models/wake_frames/streamlines.py +8 -6
- foxes/models/wake_frames/timelines.py +9 -3
- foxes/models/wake_models/__init__.py +7 -7
- foxes/models/wake_models/dist_sliced.py +50 -84
- foxes/models/wake_models/gaussian.py +20 -0
- foxes/models/wake_models/induction/__init__.py +5 -5
- foxes/models/wake_models/induction/rankine_half_body.py +30 -71
- foxes/models/wake_models/induction/rathmann.py +65 -64
- foxes/models/wake_models/induction/self_similar.py +65 -68
- foxes/models/wake_models/induction/self_similar2020.py +0 -3
- foxes/models/wake_models/induction/vortex_sheet.py +71 -75
- foxes/models/wake_models/ti/__init__.py +2 -2
- foxes/models/wake_models/ti/crespo_hernandez.py +5 -3
- foxes/models/wake_models/ti/iec_ti.py +6 -4
- foxes/models/wake_models/top_hat.py +58 -7
- foxes/models/wake_models/wind/__init__.py +6 -4
- foxes/models/wake_models/wind/bastankhah14.py +25 -7
- foxes/models/wake_models/wind/bastankhah16.py +35 -3
- foxes/models/wake_models/wind/jensen.py +15 -2
- foxes/models/wake_models/wind/turbopark.py +28 -2
- foxes/models/wake_superpositions/__init__.py +18 -9
- foxes/models/wake_superpositions/ti_linear.py +4 -4
- foxes/models/wake_superpositions/ti_max.py +4 -4
- foxes/models/wake_superpositions/ti_pow.py +4 -4
- foxes/models/wake_superpositions/ti_quadratic.py +4 -4
- foxes/models/wake_superpositions/wind_vector.py +257 -0
- foxes/models/wake_superpositions/ws_linear.py +9 -10
- foxes/models/wake_superpositions/ws_max.py +8 -8
- foxes/models/wake_superpositions/ws_pow.py +8 -8
- foxes/models/wake_superpositions/ws_product.py +4 -4
- foxes/models/wake_superpositions/ws_quadratic.py +8 -8
- foxes/output/__init__.py +21 -19
- foxes/output/farm_layout.py +2 -2
- foxes/output/farm_results_eval.py +15 -15
- foxes/output/flow_plots_2d/__init__.py +2 -2
- foxes/output/flow_plots_2d/get_fig.py +4 -2
- foxes/output/rose_plot.py +3 -3
- foxes/output/seq_plugins/__init__.py +2 -2
- foxes/output/seq_plugins/seq_flow_ani_plugin.py +0 -3
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +0 -1
- foxes/output/turbine_type_curves.py +7 -8
- foxes/utils/__init__.py +37 -19
- foxes/utils/abl/__init__.py +4 -4
- foxes/utils/cubic_roots.py +1 -1
- foxes/utils/data_book.py +4 -3
- foxes/utils/dict.py +3 -3
- foxes/utils/exec_python.py +5 -5
- foxes/utils/factory.py +1 -3
- foxes/utils/geom2d/__init__.py +7 -5
- foxes/utils/geopandas_utils.py +2 -2
- foxes/utils/pandas_utils.py +4 -3
- foxes/utils/tab_files.py +0 -1
- foxes/utils/weibull.py +28 -0
- foxes/utils/wrg_utils.py +3 -1
- foxes/utils/xarray_utils.py +9 -2
- foxes/variables.py +67 -9
- {foxes-1.3.dist-info → foxes-1.4.dist-info}/METADATA +6 -15
- foxes-1.4.dist-info/RECORD +320 -0
- {foxes-1.3.dist-info → foxes-1.4.dist-info}/WHEEL +1 -1
- tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +2 -3
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +1 -1
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +0 -2
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +0 -1
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +0 -1
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +0 -1
- foxes/output/round.py +0 -10
- foxes/utils/pandas_helpers.py +0 -178
- foxes-1.3.dist-info/RECORD +0 -313
- {foxes-1.3.dist-info → foxes-1.4.dist-info}/entry_points.txt +0 -0
- {foxes-1.3.dist-info → foxes-1.4.dist-info/licenses}/LICENSE +0 -0
- {foxes-1.3.dist-info → foxes-1.4.dist-info}/top_level.txt +0 -0
foxes/core/wake_model.py
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
|
-
import numpy as np
|
|
3
2
|
|
|
4
3
|
from foxes.utils import new_instance
|
|
5
4
|
import foxes.variables as FV
|
|
6
|
-
import foxes.constants as FC
|
|
7
5
|
|
|
8
6
|
from .model import Model
|
|
7
|
+
from .wake_superposition import WindVectorWakeSuperposition
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
class WakeModel(Model):
|
|
@@ -16,6 +15,26 @@ class WakeModel(Model):
|
|
|
16
15
|
|
|
17
16
|
"""
|
|
18
17
|
|
|
18
|
+
def __init__(self):
|
|
19
|
+
"""
|
|
20
|
+
Constructor.
|
|
21
|
+
"""
|
|
22
|
+
super().__init__()
|
|
23
|
+
self._has_uv = False
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def affects_ws(self):
|
|
27
|
+
"""
|
|
28
|
+
Flag for wind speed wake models
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
dws: bool
|
|
33
|
+
If True, this model affects wind speed
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
return False
|
|
37
|
+
|
|
19
38
|
@property
|
|
20
39
|
def affects_downwind(self):
|
|
21
40
|
"""
|
|
@@ -30,6 +49,38 @@ class WakeModel(Model):
|
|
|
30
49
|
"""
|
|
31
50
|
return True
|
|
32
51
|
|
|
52
|
+
@property
|
|
53
|
+
def has_uv(self):
|
|
54
|
+
"""
|
|
55
|
+
This model uses wind vector data
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
hasuv: bool
|
|
60
|
+
Flag for wind vector data
|
|
61
|
+
|
|
62
|
+
"""
|
|
63
|
+
return self._has_uv
|
|
64
|
+
|
|
65
|
+
def initialize(self, algo, verbosity=0, force=False):
|
|
66
|
+
"""
|
|
67
|
+
Initializes the model.
|
|
68
|
+
|
|
69
|
+
Parameters
|
|
70
|
+
----------
|
|
71
|
+
algo: foxes.core.Algorithm
|
|
72
|
+
The calculation algorithm
|
|
73
|
+
verbosity: int
|
|
74
|
+
The verbosity level, 0 = silent
|
|
75
|
+
force: bool
|
|
76
|
+
Overwrite existing data
|
|
77
|
+
|
|
78
|
+
"""
|
|
79
|
+
if self.affects_ws and algo.wake_deflection.has_uv:
|
|
80
|
+
self._has_uv = True
|
|
81
|
+
super().initialize(algo, verbosity, force)
|
|
82
|
+
|
|
83
|
+
@abstractmethod
|
|
33
84
|
def new_wake_deltas(self, algo, mdata, fdata, tdata):
|
|
34
85
|
"""
|
|
35
86
|
Creates new empty wake delta arrays.
|
|
@@ -52,7 +103,7 @@ class WakeModel(Model):
|
|
|
52
103
|
wake deltas, shape: (n_states, n_targets, n_tpoints, ...)
|
|
53
104
|
|
|
54
105
|
"""
|
|
55
|
-
|
|
106
|
+
pass
|
|
56
107
|
|
|
57
108
|
@abstractmethod
|
|
58
109
|
def contribute(
|
|
@@ -98,7 +149,7 @@ class WakeModel(Model):
|
|
|
98
149
|
algo,
|
|
99
150
|
mdata,
|
|
100
151
|
fdata,
|
|
101
|
-
|
|
152
|
+
tdata,
|
|
102
153
|
wake_deltas,
|
|
103
154
|
):
|
|
104
155
|
"""
|
|
@@ -114,10 +165,8 @@ class WakeModel(Model):
|
|
|
114
165
|
The model data
|
|
115
166
|
fdata: foxes.core.FData
|
|
116
167
|
The farm data
|
|
117
|
-
|
|
118
|
-
The
|
|
119
|
-
values: numpy.ndarray with shape
|
|
120
|
-
(n_states, n_targets, n_tpoints)
|
|
168
|
+
tdata: foxes.core.TData
|
|
169
|
+
The target point data
|
|
121
170
|
wake_deltas: dict
|
|
122
171
|
The wake deltas object at the selected target
|
|
123
172
|
turbines. Key: variable str, value: numpy.ndarray
|
|
@@ -144,7 +193,171 @@ class WakeModel(Model):
|
|
|
144
193
|
return new_instance(cls, wmodel_type, *args, **kwargs)
|
|
145
194
|
|
|
146
195
|
|
|
147
|
-
class
|
|
196
|
+
class SingleTurbineWakeModel(WakeModel):
|
|
197
|
+
"""
|
|
198
|
+
Abstract base class for wake models that represent
|
|
199
|
+
a single turbine wake
|
|
200
|
+
|
|
201
|
+
Single turbine wake models depend on superposition models.
|
|
202
|
+
|
|
203
|
+
Attributes
|
|
204
|
+
----------
|
|
205
|
+
wind_superposition: str
|
|
206
|
+
The wind superposition model name (vector or compenent model),
|
|
207
|
+
will be looked up in model book
|
|
208
|
+
other_superpositions: dict
|
|
209
|
+
The superpositions for other than (ws, wd) variables.
|
|
210
|
+
Key: variable name str, value: The wake superposition
|
|
211
|
+
model name, will be looked up in model book
|
|
212
|
+
vec_superp: foxes.core.WindVectorWakeSuperposition or None
|
|
213
|
+
The wind vector wake superposition model
|
|
214
|
+
superp: dict
|
|
215
|
+
The superposition dict, key: variable name str,
|
|
216
|
+
value: `foxes.core.WakeSuperposition`
|
|
217
|
+
|
|
218
|
+
:group: models.wake_models
|
|
219
|
+
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
def __init__(self, wind_superposition=None, other_superpositions={}):
|
|
223
|
+
"""
|
|
224
|
+
Constructor.
|
|
225
|
+
|
|
226
|
+
Parameters
|
|
227
|
+
----------
|
|
228
|
+
wind_superposition: str, optional
|
|
229
|
+
The wind superposition model name (vector or compenent model),
|
|
230
|
+
will be looked up in model book
|
|
231
|
+
other_superpositions: dict
|
|
232
|
+
The superpositions for other than (ws, wd) variables.
|
|
233
|
+
Key: variable name str, value: The wake superposition
|
|
234
|
+
model name, will be looked up in model book
|
|
235
|
+
|
|
236
|
+
"""
|
|
237
|
+
super().__init__()
|
|
238
|
+
self.wind_superposition = wind_superposition
|
|
239
|
+
self.other_superpositions = other_superpositions
|
|
240
|
+
self.vec_superp = None
|
|
241
|
+
self.superp = {}
|
|
242
|
+
|
|
243
|
+
for v in [FV.WS, FV.WD]:
|
|
244
|
+
assert v not in other_superpositions, (
|
|
245
|
+
f"Wake model '{self.name}': Found variable '{v}' among 'other_superposition' keyword, use 'wind_superposition' instead"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
self.__has_vector_superp = False
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def has_vector_wind_superp(self):
|
|
252
|
+
"""
|
|
253
|
+
This model uses a wind vector superposition
|
|
254
|
+
|
|
255
|
+
Returns
|
|
256
|
+
-------
|
|
257
|
+
hasv: bool
|
|
258
|
+
Flag for wind vector superposition
|
|
259
|
+
|
|
260
|
+
"""
|
|
261
|
+
return self.__has_vector_superp
|
|
262
|
+
|
|
263
|
+
def sub_models(self):
|
|
264
|
+
"""
|
|
265
|
+
List of all sub-models
|
|
266
|
+
|
|
267
|
+
Returns
|
|
268
|
+
-------
|
|
269
|
+
smdls: list of foxes.core.Model
|
|
270
|
+
Names of all sub models
|
|
271
|
+
|
|
272
|
+
"""
|
|
273
|
+
w = [self.vec_superp] if self.vec_superp is not None else []
|
|
274
|
+
return w + list(self.superp.values())
|
|
275
|
+
|
|
276
|
+
def initialize(self, algo, verbosity=0, force=False):
|
|
277
|
+
"""
|
|
278
|
+
Initializes the model.
|
|
279
|
+
|
|
280
|
+
Parameters
|
|
281
|
+
----------
|
|
282
|
+
algo: foxes.core.Algorithm
|
|
283
|
+
The calculation algorithm
|
|
284
|
+
verbosity: int
|
|
285
|
+
The verbosity level, 0 = silent
|
|
286
|
+
force: bool
|
|
287
|
+
Overwrite existing data
|
|
288
|
+
|
|
289
|
+
"""
|
|
290
|
+
self.superp = {
|
|
291
|
+
v: algo.mbook.wake_superpositions[s]
|
|
292
|
+
for v, s in self.other_superpositions.items()
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if self.wind_superposition is not None:
|
|
296
|
+
self.vec_superp = algo.mbook.wake_superpositions[self.wind_superposition]
|
|
297
|
+
self.__has_vector_superp = isinstance(
|
|
298
|
+
self.vec_superp, WindVectorWakeSuperposition
|
|
299
|
+
)
|
|
300
|
+
if self.__has_vector_superp:
|
|
301
|
+
self._has_uv = True
|
|
302
|
+
else:
|
|
303
|
+
self.superp[FV.WS] = self.vec_superp
|
|
304
|
+
self.vec_superp = None
|
|
305
|
+
|
|
306
|
+
super().initialize(algo, verbosity, force)
|
|
307
|
+
|
|
308
|
+
def finalize_wake_deltas(
|
|
309
|
+
self,
|
|
310
|
+
algo,
|
|
311
|
+
mdata,
|
|
312
|
+
fdata,
|
|
313
|
+
tdata,
|
|
314
|
+
wake_deltas,
|
|
315
|
+
):
|
|
316
|
+
"""
|
|
317
|
+
Finalize the wake calculation.
|
|
318
|
+
|
|
319
|
+
Modifies wake_deltas on the fly.
|
|
320
|
+
|
|
321
|
+
Parameters
|
|
322
|
+
----------
|
|
323
|
+
algo: foxes.core.Algorithm
|
|
324
|
+
The calculation algorithm
|
|
325
|
+
mdata: foxes.core.MData
|
|
326
|
+
The model data
|
|
327
|
+
fdata: foxes.core.FData
|
|
328
|
+
The farm data
|
|
329
|
+
tdata: foxes.core.TData
|
|
330
|
+
The target point data
|
|
331
|
+
wake_deltas: dict
|
|
332
|
+
The wake deltas object at the selected target
|
|
333
|
+
turbines. Key: variable str, value: numpy.ndarray
|
|
334
|
+
with shape (n_states, n_targets, n_tpoints)
|
|
335
|
+
|
|
336
|
+
"""
|
|
337
|
+
for v in wake_deltas.keys():
|
|
338
|
+
if v != FV.UV:
|
|
339
|
+
try:
|
|
340
|
+
wake_deltas[v] = self.superp[v].calc_final_wake_delta(
|
|
341
|
+
algo, mdata, fdata, tdata, v, wake_deltas[v]
|
|
342
|
+
)
|
|
343
|
+
except KeyError:
|
|
344
|
+
raise KeyError(
|
|
345
|
+
f"Wake model '{self.name}': Variable '{v}' appears to be modified, missing superposition model"
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
if FV.UV in wake_deltas:
|
|
349
|
+
assert self.has_vector_wind_superp, (
|
|
350
|
+
f"{self.name}: Expecting wind vector superposition, got '{self.wind_superposition}'"
|
|
351
|
+
)
|
|
352
|
+
dws, dwd = self.vec_superp.calc_final_wake_delta_uv(
|
|
353
|
+
algo, mdata, fdata, tdata, wake_deltas.pop(FV.UV)
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
wake_deltas[FV.WS] = dws
|
|
357
|
+
wake_deltas[FV.WD] = dwd
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class TurbineInductionModel(SingleTurbineWakeModel):
|
|
148
361
|
"""
|
|
149
362
|
Abstract base class for turbine induction models.
|
|
150
363
|
|
foxes/core/wake_superposition.py
CHANGED
|
@@ -74,8 +74,8 @@ class WakeSuperposition(Model):
|
|
|
74
74
|
algo,
|
|
75
75
|
mdata,
|
|
76
76
|
fdata,
|
|
77
|
+
tdata,
|
|
77
78
|
variable,
|
|
78
|
-
amb_results,
|
|
79
79
|
wake_delta,
|
|
80
80
|
):
|
|
81
81
|
"""
|
|
@@ -90,11 +90,10 @@ class WakeSuperposition(Model):
|
|
|
90
90
|
The model data
|
|
91
91
|
fdata: foxes.core.FData
|
|
92
92
|
The farm data
|
|
93
|
+
tdata: foxes.core.TData
|
|
94
|
+
The target point data
|
|
93
95
|
variable: str
|
|
94
96
|
The variable name for which the wake deltas applies
|
|
95
|
-
amb_results: numpy.ndarray
|
|
96
|
-
The ambient results at targets,
|
|
97
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
98
97
|
wake_delta: numpy.ndarray
|
|
99
98
|
The wake deltas at targets, shape:
|
|
100
99
|
(n_states, n_targets, n_tpoints)
|
|
@@ -125,3 +124,122 @@ class WakeSuperposition(Model):
|
|
|
125
124
|
|
|
126
125
|
"""
|
|
127
126
|
return new_instance(cls, superp_type, *args, **kwargs)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class WindVectorWakeSuperposition(Model):
|
|
130
|
+
"""
|
|
131
|
+
Base class for wind vector superposition.
|
|
132
|
+
|
|
133
|
+
Note that it is a matter of the wake model
|
|
134
|
+
if superposition models are used, or if the
|
|
135
|
+
wake model computes the total wake result by
|
|
136
|
+
other means.
|
|
137
|
+
|
|
138
|
+
:group: core
|
|
139
|
+
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
@abstractmethod
|
|
143
|
+
def add_wake_vector(
|
|
144
|
+
self,
|
|
145
|
+
algo,
|
|
146
|
+
mdata,
|
|
147
|
+
fdata,
|
|
148
|
+
tdata,
|
|
149
|
+
downwind_index,
|
|
150
|
+
st_sel,
|
|
151
|
+
wake_delta_uv,
|
|
152
|
+
wake_model_result_uv,
|
|
153
|
+
):
|
|
154
|
+
"""
|
|
155
|
+
Add a wake delta vector to previous wake deltas,
|
|
156
|
+
at rotor points.
|
|
157
|
+
|
|
158
|
+
Parameters
|
|
159
|
+
----------
|
|
160
|
+
algo: foxes.core.Algorithm
|
|
161
|
+
The calculation algorithm
|
|
162
|
+
mdata: foxes.core.MData
|
|
163
|
+
The model data
|
|
164
|
+
fdata: foxes.core.FData
|
|
165
|
+
The farm data
|
|
166
|
+
tdata: foxes.core.TData
|
|
167
|
+
The target point data
|
|
168
|
+
downwind_index: int
|
|
169
|
+
The index of the wake causing turbine
|
|
170
|
+
in the downwind order
|
|
171
|
+
st_sel: numpy.ndarray of bool
|
|
172
|
+
The selection of targets, shape: (n_states, n_targets)
|
|
173
|
+
wake_delta_uv: numpy.ndarray
|
|
174
|
+
The original wind vector wake deltas, shape:
|
|
175
|
+
(n_states, n_targets, n_tpoints, 2)
|
|
176
|
+
wake_model_result_uv: numpy.ndarray
|
|
177
|
+
The new wind vector wake deltas of the selected rotors,
|
|
178
|
+
shape: (n_st_sel, n_tpoints, 2, ...)
|
|
179
|
+
|
|
180
|
+
Returns
|
|
181
|
+
-------
|
|
182
|
+
wdelta_uv: numpy.ndarray
|
|
183
|
+
The updated wind vector wake deltas, shape:
|
|
184
|
+
(n_states, n_targets, n_tpoints, ...)
|
|
185
|
+
|
|
186
|
+
"""
|
|
187
|
+
pass
|
|
188
|
+
|
|
189
|
+
@abstractmethod
|
|
190
|
+
def calc_final_wake_delta_uv(
|
|
191
|
+
self,
|
|
192
|
+
algo,
|
|
193
|
+
mdata,
|
|
194
|
+
fdata,
|
|
195
|
+
tdata,
|
|
196
|
+
wake_delta_uv,
|
|
197
|
+
):
|
|
198
|
+
"""
|
|
199
|
+
Calculate the final wind vector wake delta after adding all
|
|
200
|
+
contributions.
|
|
201
|
+
|
|
202
|
+
Parameters
|
|
203
|
+
----------
|
|
204
|
+
algo: foxes.core.Algorithm
|
|
205
|
+
The calculation algorithm
|
|
206
|
+
mdata: foxes.core.MData
|
|
207
|
+
The model data
|
|
208
|
+
fdata: foxes.core.FData
|
|
209
|
+
The farm data
|
|
210
|
+
tdata: foxes.core.TData
|
|
211
|
+
The target point data
|
|
212
|
+
wake_delta_uv: numpy.ndarray
|
|
213
|
+
The original wind vector wake deltas, shape:
|
|
214
|
+
(n_states, n_targets, n_tpoints, 2)
|
|
215
|
+
|
|
216
|
+
Returns
|
|
217
|
+
-------
|
|
218
|
+
final_wake_delta_ws: numpy.ndarray
|
|
219
|
+
The final wind speed wake delta, which will be added to
|
|
220
|
+
the ambient results by simple plus operation. Shape:
|
|
221
|
+
(n_states, n_targets, n_tpoints)
|
|
222
|
+
final_wake_delta_wd: numpy.ndarray
|
|
223
|
+
The final wind direction wake delta, which will be added to
|
|
224
|
+
the ambient results by simple plus operation. Shape:
|
|
225
|
+
(n_states, n_targets, n_tpoints)
|
|
226
|
+
|
|
227
|
+
"""
|
|
228
|
+
pass
|
|
229
|
+
|
|
230
|
+
@classmethod
|
|
231
|
+
def new(cls, superp_type, *args, **kwargs):
|
|
232
|
+
"""
|
|
233
|
+
Run-time wind wake superposition model factory.
|
|
234
|
+
|
|
235
|
+
Parameters
|
|
236
|
+
----------
|
|
237
|
+
superp_type: str
|
|
238
|
+
The selected derived class name
|
|
239
|
+
args: tuple, optional
|
|
240
|
+
Additional parameters for constructor
|
|
241
|
+
kwargs: dict, optional
|
|
242
|
+
Additional parameters for constructor
|
|
243
|
+
|
|
244
|
+
"""
|
|
245
|
+
return new_instance(cls, superp_type, *args, **kwargs)
|
foxes/core/wind_farm.py
CHANGED
|
@@ -124,12 +124,12 @@ class WindFarm:
|
|
|
124
124
|
|
|
125
125
|
if extra_space is not None:
|
|
126
126
|
if isinstance(extra_space, str):
|
|
127
|
-
assert (
|
|
128
|
-
algo
|
|
129
|
-
)
|
|
130
|
-
assert (
|
|
131
|
-
|
|
132
|
-
)
|
|
127
|
+
assert algo is not None, (
|
|
128
|
+
f"WindFarm: require algo argument for extra_space '{extra_space}'"
|
|
129
|
+
)
|
|
130
|
+
assert len(extra_space) > 1 and extra_space[-1] == "D", (
|
|
131
|
+
f"Expecting float or str like '2.5D', got extra_space = '{extra_space}'"
|
|
132
|
+
)
|
|
133
133
|
extra_space = float(extra_space[:-1])
|
|
134
134
|
rds = self.get_rotor_diameters(algo)
|
|
135
135
|
if xy is None:
|
foxes/data/__init__.py
CHANGED
|
@@ -2,5 +2,10 @@
|
|
|
2
2
|
Static data collection.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .parse import parse_Pct_file_name
|
|
6
|
-
from .
|
|
5
|
+
from .parse import parse_Pct_file_name as parse_Pct_file_name
|
|
6
|
+
from .parse import parse_Pct_two_files as parse_Pct_two_files
|
|
7
|
+
|
|
8
|
+
from .static_data import FARM as FARM
|
|
9
|
+
from .static_data import STATES as STATES
|
|
10
|
+
from .static_data import PCTCURVE as PCTCURVE
|
|
11
|
+
from .static_data import StaticData as StaticData
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
sector,wind_direction,sector_probability,weibull_a,weibull_k,turbulence_intensity
|
|
2
|
+
0,0.0,0.0359715203597152,9.176929,2.392578,0.1
|
|
3
|
+
1,30.0,0.0394868203948682,9.782334,2.447266,0.1
|
|
4
|
+
2,60.0,0.0516739505167395,9.531809,2.412109,0.1
|
|
5
|
+
3,90.0,0.07000154070001541,9.909545,2.591797,0.1
|
|
6
|
+
4,120.0,0.08364547083645471,10.04269,2.755859,0.1
|
|
7
|
+
5,150.0,0.064348500643485,9.593921,2.595703,0.1
|
|
8
|
+
6,180.0,0.0864319408643194,9.584007,2.583984,0.1
|
|
9
|
+
7,210.0,0.117705101177051,10.51499,2.548828,0.1
|
|
10
|
+
8,240.0,0.151575701515757,11.39895,2.470703,0.1
|
|
11
|
+
9,270.0,0.14737920147379202,11.68746,2.607422,0.1
|
|
12
|
+
10,300.0,0.10012050100120501,11.63732,2.626953,0.1
|
|
13
|
+
11,330.0,0.051659750516597505,10.08803,2.326172,0.1
|
|
Binary file
|
foxes/engines/__init__.py
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
from .pool import PoolEngine
|
|
2
|
-
from .multiprocess import MultiprocessEngine
|
|
3
|
-
from .numpy import NumpyEngine
|
|
4
|
-
from .single import SingleChunkEngine
|
|
5
|
-
from .
|
|
6
|
-
from .
|
|
7
|
-
from .
|
|
1
|
+
from .pool import PoolEngine as PoolEngine
|
|
2
|
+
from .multiprocess import MultiprocessEngine as MultiprocessEngine
|
|
3
|
+
from .numpy import NumpyEngine as NumpyEngine
|
|
4
|
+
from .single import SingleChunkEngine as SingleChunkEngine
|
|
5
|
+
from .mpi import MPIEngine as MPIEngine
|
|
6
|
+
from .ray import RayEngine as RayEngine
|
|
7
|
+
from .default import DefaultEngine as DefaultEngine
|
|
8
8
|
|
|
9
|
-
from .
|
|
10
|
-
|
|
11
|
-
XArrayEngine,
|
|
12
|
-
DaskEngine,
|
|
13
|
-
LocalClusterEngine,
|
|
14
|
-
SlurmClusterEngine,
|
|
15
|
-
)
|
|
9
|
+
from .futures import ThreadsEngine as ThreadsEngine
|
|
10
|
+
from .futures import ProcessEngine as ProcessEngine
|
|
16
11
|
|
|
17
|
-
from .
|
|
12
|
+
from .dask import DaskBaseEngine as DaskBaseEngine
|
|
13
|
+
from .dask import XArrayEngine as XArrayEngine
|
|
14
|
+
from .dask import DaskEngine as DaskEngine
|
|
15
|
+
from .dask import LocalClusterEngine as LocalClusterEngine
|
|
16
|
+
from .dask import SlurmClusterEngine as SlurmClusterEngine
|
foxes/engines/dask.py
CHANGED
|
@@ -222,19 +222,28 @@ def _run_as_ufunc(
|
|
|
222
222
|
if i == 0:
|
|
223
223
|
data.append(
|
|
224
224
|
MData(
|
|
225
|
-
data=hdata,
|
|
225
|
+
data=hdata,
|
|
226
|
+
dims=hdims,
|
|
227
|
+
# loop_dims=loop_dims,
|
|
228
|
+
states_i0=state_inds[0],
|
|
226
229
|
)
|
|
227
230
|
)
|
|
228
231
|
elif i == 1:
|
|
229
232
|
data.append(
|
|
230
233
|
FData(
|
|
231
|
-
data=hdata,
|
|
234
|
+
data=hdata,
|
|
235
|
+
dims=hdims,
|
|
236
|
+
# loop_dims=loop_dims,
|
|
237
|
+
states_i0=state_inds[0],
|
|
232
238
|
)
|
|
233
239
|
)
|
|
234
240
|
elif i == 2:
|
|
235
241
|
data.append(
|
|
236
242
|
TData(
|
|
237
|
-
data=hdata,
|
|
243
|
+
data=hdata,
|
|
244
|
+
dims=hdims,
|
|
245
|
+
# loop_dims=loop_dims,
|
|
246
|
+
states_i0=state_inds[0],
|
|
238
247
|
)
|
|
239
248
|
)
|
|
240
249
|
else:
|
|
@@ -246,13 +255,13 @@ def _run_as_ufunc(
|
|
|
246
255
|
|
|
247
256
|
# deduce output shape:
|
|
248
257
|
oshape = []
|
|
249
|
-
for li,
|
|
258
|
+
for li, ld in enumerate(out_coords):
|
|
250
259
|
for i, dims in enumerate(ldims):
|
|
251
|
-
if
|
|
252
|
-
oshape.append(ldata[i].shape[dims.index(
|
|
260
|
+
if ld in dims:
|
|
261
|
+
oshape.append(ldata[i].shape[dims.index(ld)])
|
|
253
262
|
break
|
|
254
263
|
if len(oshape) != li + 1:
|
|
255
|
-
raise ValueError(
|
|
264
|
+
raise ValueError("Failed to find loop dimension")
|
|
256
265
|
|
|
257
266
|
# add zero output data arrays:
|
|
258
267
|
odims = {v: tuple(out_coords) for v in out_vars}
|
|
@@ -267,14 +276,31 @@ def _run_as_ufunc(
|
|
|
267
276
|
}
|
|
268
277
|
|
|
269
278
|
if len(data) == 1:
|
|
270
|
-
data.append(
|
|
279
|
+
data.append(
|
|
280
|
+
FData(
|
|
281
|
+
odata,
|
|
282
|
+
odims,
|
|
283
|
+
# loop_dims,
|
|
284
|
+
states_i0=state_inds[0],
|
|
285
|
+
)
|
|
286
|
+
)
|
|
271
287
|
else:
|
|
272
288
|
odata.update(data[-1])
|
|
273
289
|
odims.update(data[-1].dims)
|
|
274
290
|
if len(data) == 2:
|
|
275
|
-
data[-1] = FData(
|
|
291
|
+
data[-1] = FData(
|
|
292
|
+
odata,
|
|
293
|
+
odims,
|
|
294
|
+
# loop_dims,
|
|
295
|
+
states_i0=state_inds[0],
|
|
296
|
+
)
|
|
276
297
|
else:
|
|
277
|
-
data[-1] = TData(
|
|
298
|
+
data[-1] = TData(
|
|
299
|
+
odata,
|
|
300
|
+
odims,
|
|
301
|
+
# loop_dims,
|
|
302
|
+
states_i0=state_inds[0],
|
|
303
|
+
)
|
|
278
304
|
del odims, odata
|
|
279
305
|
|
|
280
306
|
# link chunk state indices from mdata to fdata and tdata:
|
|
@@ -451,7 +477,6 @@ class XArrayEngine(DaskBaseEngine):
|
|
|
451
477
|
if d is not None
|
|
452
478
|
]
|
|
453
479
|
for ds in data:
|
|
454
|
-
|
|
455
480
|
hvarsl = [v for v, d in ds.items() if len(loopd.intersection(d.dims))]
|
|
456
481
|
ldata += [ds[v] for v in hvarsl]
|
|
457
482
|
ldims += [ds[v].dims for v in hvarsl]
|
|
@@ -734,7 +759,7 @@ def _run_on_cluster(
|
|
|
734
759
|
mdata = MData(
|
|
735
760
|
data={names[i]: data[i] for i in range(mdata_size)},
|
|
736
761
|
dims={names[i]: dims[i] for i in range(mdata_size)},
|
|
737
|
-
loop_dims=loop_dims[0],
|
|
762
|
+
# loop_dims=loop_dims[0],
|
|
738
763
|
states_i0=i0_states,
|
|
739
764
|
)
|
|
740
765
|
|
|
@@ -742,7 +767,7 @@ def _run_on_cluster(
|
|
|
742
767
|
fdata = FData(
|
|
743
768
|
data={names[i]: data[i].copy() for i in range(mdata_size, fdata_end)},
|
|
744
769
|
dims={names[i]: dims[i] for i in range(mdata_size, fdata_end)},
|
|
745
|
-
loop_dims=loop_dims[1],
|
|
770
|
+
# loop_dims=loop_dims[1],
|
|
746
771
|
states_i0=i0_states,
|
|
747
772
|
)
|
|
748
773
|
|
|
@@ -751,7 +776,7 @@ def _run_on_cluster(
|
|
|
751
776
|
tdata = TData(
|
|
752
777
|
data={names[i]: data[i].copy() for i in range(fdata_end, len(data))},
|
|
753
778
|
dims={names[i]: dims[i] for i in range(fdata_end, len(data))},
|
|
754
|
-
loop_dims=loop_dims[2],
|
|
779
|
+
# loop_dims=loop_dims[2],
|
|
755
780
|
states_i0=i0_states,
|
|
756
781
|
)
|
|
757
782
|
|
foxes/engines/numpy.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from tqdm import tqdm
|
|
2
2
|
from xarray import Dataset
|
|
3
|
-
from tqdm import tqdm
|
|
4
3
|
|
|
5
4
|
from foxes.core import Engine
|
|
6
5
|
import foxes.constants as FC
|
|
@@ -146,8 +145,6 @@ class NumpyEngine(Engine):
|
|
|
146
145
|
for chunki_points in range(n_chunks_targets):
|
|
147
146
|
i1_targets = i0_targets + chunk_sizes_targets[chunki_points]
|
|
148
147
|
|
|
149
|
-
i = chunki_states * n_chunks_targets + chunki_points
|
|
150
|
-
|
|
151
148
|
# get this chunk's data:
|
|
152
149
|
data = self.get_chunk_input_data(
|
|
153
150
|
algo=algo,
|
foxes/input/__init__.py
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
Functions for adding turbines to the wind farm.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .row import add_row
|
|
6
|
-
from .grid import add_grid
|
|
7
|
-
from .from_json import add_from_json
|
|
8
|
-
from .from_csv import add_from_csv
|
|
9
|
-
from .from_file import add_from_file
|
|
10
|
-
from .from_df import add_from_df
|
|
11
|
-
from .from_random import add_random
|
|
12
|
-
from .ring import add_ring
|
|
5
|
+
from .row import add_row as add_row
|
|
6
|
+
from .grid import add_grid as add_grid
|
|
7
|
+
from .from_json import add_from_json as add_from_json
|
|
8
|
+
from .from_csv import add_from_csv as add_from_csv
|
|
9
|
+
from .from_file import add_from_file as add_from_file
|
|
10
|
+
from .from_df import add_from_df as add_from_df
|
|
11
|
+
from .from_random import add_random as add_random
|
|
12
|
+
from .ring import add_ring as add_ring
|
|
@@ -86,7 +86,7 @@ def add_from_csv(
|
|
|
86
86
|
for i in data.index:
|
|
87
87
|
s = 1 if turbine_base_name_count_shift else 0
|
|
88
88
|
tname = (
|
|
89
|
-
f"{turbine_base_name}{i+s}" if col_name is None else data.loc[i, col_name]
|
|
89
|
+
f"{turbine_base_name}{i + s}" if col_name is None else data.loc[i, col_name]
|
|
90
90
|
)
|
|
91
91
|
txy = data.loc[i, [col_x, col_y]].values
|
|
92
92
|
|