foxes 1.3__py3-none-any.whl → 1.5__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/field_data_nc/run.py +1 -1
- 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 +29 -6
- 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 +19 -9
- foxes/__init__.py +21 -17
- foxes/algorithms/__init__.py +6 -6
- foxes/algorithms/downwind/__init__.py +2 -2
- foxes/algorithms/downwind/downwind.py +49 -17
- 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 +58 -29
- foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
- foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
- 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 +5 -6
- foxes/core/data.py +94 -22
- foxes/core/data_calc_model.py +4 -2
- foxes/core/engine.py +42 -53
- foxes/core/farm_controller.py +2 -2
- foxes/core/farm_data_model.py +16 -13
- foxes/core/ground_model.py +4 -13
- foxes/core/model.py +24 -6
- foxes/core/partial_wakes_model.py +147 -10
- foxes/core/point_data_model.py +21 -17
- foxes/core/rotor_model.py +4 -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/point_cloud_100.nc +0 -0
- foxes/data/states/weibull_cloud_4.nc +0 -0
- foxes/data/states/weibull_grid.nc +0 -0
- 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 +42 -20
- foxes/engines/default.py +2 -2
- foxes/engines/numpy.py +11 -13
- foxes/engines/pool.py +20 -11
- foxes/engines/single.py +8 -6
- foxes/input/__init__.py +3 -3
- foxes/input/farm_layout/__init__.py +9 -8
- foxes/input/farm_layout/from_arrays.py +68 -0
- foxes/input/farm_layout/from_csv.py +1 -1
- foxes/input/farm_layout/ring.py +0 -1
- foxes/input/states/__init__.py +28 -12
- foxes/input/states/create/__init__.py +3 -2
- foxes/input/states/dataset_states.py +710 -0
- foxes/input/states/field_data.py +531 -0
- foxes/input/states/multi_height.py +11 -6
- foxes/input/states/one_point_flow.py +1 -4
- foxes/input/states/point_cloud_data.py +618 -0
- foxes/input/states/scan.py +2 -0
- foxes/input/states/single.py +3 -1
- foxes/input/states/states_table.py +23 -30
- foxes/input/states/weibull_sectors.py +330 -0
- foxes/input/states/wrg_states.py +8 -6
- foxes/input/yaml/__init__.py +9 -3
- foxes/input/yaml/dict.py +42 -41
- foxes/input/yaml/windio/__init__.py +10 -5
- foxes/input/yaml/windio/read_attributes.py +42 -29
- foxes/input/yaml/windio/read_farm.py +17 -15
- foxes/input/yaml/windio/read_fields.py +4 -2
- foxes/input/yaml/windio/read_outputs.py +25 -15
- foxes/input/yaml/windio/read_site.py +172 -11
- foxes/input/yaml/windio/windio.py +23 -11
- foxes/input/yaml/yaml.py +1 -0
- 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 +190 -63
- 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 +4 -3
- foxes/models/rotor_models/centre.py +1 -1
- foxes/models/rotor_models/direct_infusion.py +241 -0
- foxes/models/turbine_models/__init__.py +11 -11
- foxes/models/turbine_models/calculator.py +16 -3
- foxes/models/turbine_models/kTI_model.py +1 -0
- foxes/models/turbine_models/lookup_table.py +2 -0
- foxes/models/turbine_models/power_mask.py +1 -0
- foxes/models/turbine_models/rotor_centre_calc.py +2 -0
- foxes/models/turbine_models/sector_management.py +1 -0
- foxes/models/turbine_models/set_farm_vars.py +3 -9
- foxes/models/turbine_models/table_factors.py +2 -0
- foxes/models/turbine_models/thrust2ct.py +1 -0
- foxes/models/turbine_models/yaw2yawm.py +2 -0
- foxes/models/turbine_models/yawm2yaw.py +2 -0
- foxes/models/turbine_types/PCt_file.py +2 -6
- foxes/models/turbine_types/PCt_from_two.py +1 -2
- foxes/models/turbine_types/__init__.py +10 -9
- foxes/models/turbine_types/calculator_type.py +123 -0
- foxes/models/turbine_types/null_type.py +1 -0
- foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -0
- foxes/models/turbine_types/wsti2PCt_from_two.py +3 -1
- 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 +4 -2
- foxes/output/farm_results_eval.py +19 -16
- foxes/output/flow_plots_2d/__init__.py +2 -2
- foxes/output/flow_plots_2d/flow_plots.py +18 -0
- foxes/output/flow_plots_2d/get_fig.py +5 -2
- foxes/output/output.py +6 -1
- foxes/output/results_writer.py +1 -1
- foxes/output/rose_plot.py +13 -3
- foxes/output/rotor_point_plots.py +3 -0
- 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/state_turbine_map.py +3 -0
- foxes/output/turbine_type_curves.py +10 -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 +49 -37
- foxes/utils/exec_python.py +5 -5
- foxes/utils/factory.py +3 -5
- 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.5.dist-info}/METADATA +34 -63
- foxes-1.5.dist-info/RECORD +328 -0
- {foxes-1.3.dist-info → foxes-1.5.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/input/states/field_data_nc.py +0 -847
- 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.5.dist-info}/entry_points.txt +0 -0
- {foxes-1.3.dist-info → foxes-1.5.dist-info/licenses}/LICENSE +0 -0
- {foxes-1.3.dist-info → foxes-1.5.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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
@@ -199,7 +199,6 @@ def _run_as_ufunc(
|
|
|
199
199
|
out_coords,
|
|
200
200
|
calc_pars,
|
|
201
201
|
init_vars,
|
|
202
|
-
ensure_variables,
|
|
203
202
|
calculate,
|
|
204
203
|
):
|
|
205
204
|
"""
|
|
@@ -222,19 +221,28 @@ def _run_as_ufunc(
|
|
|
222
221
|
if i == 0:
|
|
223
222
|
data.append(
|
|
224
223
|
MData(
|
|
225
|
-
data=hdata,
|
|
224
|
+
data=hdata,
|
|
225
|
+
dims=hdims,
|
|
226
|
+
# loop_dims=loop_dims,
|
|
227
|
+
states_i0=state_inds[0],
|
|
226
228
|
)
|
|
227
229
|
)
|
|
228
230
|
elif i == 1:
|
|
229
231
|
data.append(
|
|
230
232
|
FData(
|
|
231
|
-
data=hdata,
|
|
233
|
+
data=hdata,
|
|
234
|
+
dims=hdims,
|
|
235
|
+
# loop_dims=loop_dims,
|
|
236
|
+
states_i0=state_inds[0],
|
|
232
237
|
)
|
|
233
238
|
)
|
|
234
239
|
elif i == 2:
|
|
235
240
|
data.append(
|
|
236
241
|
TData(
|
|
237
|
-
data=hdata,
|
|
242
|
+
data=hdata,
|
|
243
|
+
dims=hdims,
|
|
244
|
+
# loop_dims=loop_dims,
|
|
245
|
+
states_i0=state_inds[0],
|
|
238
246
|
)
|
|
239
247
|
)
|
|
240
248
|
else:
|
|
@@ -246,13 +254,13 @@ def _run_as_ufunc(
|
|
|
246
254
|
|
|
247
255
|
# deduce output shape:
|
|
248
256
|
oshape = []
|
|
249
|
-
for li,
|
|
257
|
+
for li, ld in enumerate(out_coords):
|
|
250
258
|
for i, dims in enumerate(ldims):
|
|
251
|
-
if
|
|
252
|
-
oshape.append(ldata[i].shape[dims.index(
|
|
259
|
+
if ld in dims:
|
|
260
|
+
oshape.append(ldata[i].shape[dims.index(ld)])
|
|
253
261
|
break
|
|
254
262
|
if len(oshape) != li + 1:
|
|
255
|
-
raise ValueError(
|
|
263
|
+
raise ValueError("Failed to find loop dimension")
|
|
256
264
|
|
|
257
265
|
# add zero output data arrays:
|
|
258
266
|
odims = {v: tuple(out_coords) for v in out_vars}
|
|
@@ -267,14 +275,31 @@ def _run_as_ufunc(
|
|
|
267
275
|
}
|
|
268
276
|
|
|
269
277
|
if len(data) == 1:
|
|
270
|
-
data.append(
|
|
278
|
+
data.append(
|
|
279
|
+
FData(
|
|
280
|
+
odata,
|
|
281
|
+
odims,
|
|
282
|
+
# loop_dims,
|
|
283
|
+
states_i0=state_inds[0],
|
|
284
|
+
)
|
|
285
|
+
)
|
|
271
286
|
else:
|
|
272
287
|
odata.update(data[-1])
|
|
273
288
|
odims.update(data[-1].dims)
|
|
274
289
|
if len(data) == 2:
|
|
275
|
-
data[-1] = FData(
|
|
290
|
+
data[-1] = FData(
|
|
291
|
+
odata,
|
|
292
|
+
odims,
|
|
293
|
+
# loop_dims,
|
|
294
|
+
states_i0=state_inds[0],
|
|
295
|
+
)
|
|
276
296
|
else:
|
|
277
|
-
data[-1] = TData(
|
|
297
|
+
data[-1] = TData(
|
|
298
|
+
odata,
|
|
299
|
+
odims,
|
|
300
|
+
# loop_dims,
|
|
301
|
+
states_i0=state_inds[0],
|
|
302
|
+
)
|
|
278
303
|
del odims, odata
|
|
279
304
|
|
|
280
305
|
# link chunk state indices from mdata to fdata and tdata:
|
|
@@ -288,7 +313,6 @@ def _run_as_ufunc(
|
|
|
288
313
|
data[1].dims[FV.WEIGHT] = data[0].dims[FV.WEIGHT]
|
|
289
314
|
|
|
290
315
|
# run model calculation:
|
|
291
|
-
ensure_variables(algo, *data)
|
|
292
316
|
results = calculate(algo, *data, **calc_pars)
|
|
293
317
|
|
|
294
318
|
# replace missing results by first input data with matching shape:
|
|
@@ -359,7 +383,7 @@ class XArrayEngine(DaskBaseEngine):
|
|
|
359
383
|
self,
|
|
360
384
|
algo,
|
|
361
385
|
model,
|
|
362
|
-
model_data
|
|
386
|
+
model_data,
|
|
363
387
|
farm_data=None,
|
|
364
388
|
point_data=None,
|
|
365
389
|
out_vars=[],
|
|
@@ -382,9 +406,9 @@ class XArrayEngine(DaskBaseEngine):
|
|
|
382
406
|
should be run
|
|
383
407
|
model_data: xarray.Dataset
|
|
384
408
|
The initial model data
|
|
385
|
-
farm_data: xarray.Dataset
|
|
409
|
+
farm_data: xarray.Dataset, optional
|
|
386
410
|
The initial farm data
|
|
387
|
-
point_data: xarray.Dataset
|
|
411
|
+
point_data: xarray.Dataset, optional
|
|
388
412
|
The initial point data
|
|
389
413
|
out_vars: list of str, optional
|
|
390
414
|
Names of the output variables
|
|
@@ -451,7 +475,6 @@ class XArrayEngine(DaskBaseEngine):
|
|
|
451
475
|
if d is not None
|
|
452
476
|
]
|
|
453
477
|
for ds in data:
|
|
454
|
-
|
|
455
478
|
hvarsl = [v for v, d in ds.items() if len(loopd.intersection(d.dims))]
|
|
456
479
|
ldata += [ds[v] for v in hvarsl]
|
|
457
480
|
ldims += [ds[v].dims for v in hvarsl]
|
|
@@ -512,7 +535,6 @@ class XArrayEngine(DaskBaseEngine):
|
|
|
512
535
|
out_coords=out_coords,
|
|
513
536
|
calc_pars=calc_pars,
|
|
514
537
|
init_vars=ivars,
|
|
515
|
-
ensure_variables=model.ensure_variables,
|
|
516
538
|
calculate=model.calculate,
|
|
517
539
|
)
|
|
518
540
|
|
|
@@ -734,7 +756,7 @@ def _run_on_cluster(
|
|
|
734
756
|
mdata = MData(
|
|
735
757
|
data={names[i]: data[i] for i in range(mdata_size)},
|
|
736
758
|
dims={names[i]: dims[i] for i in range(mdata_size)},
|
|
737
|
-
loop_dims=loop_dims[0],
|
|
759
|
+
# loop_dims=loop_dims[0],
|
|
738
760
|
states_i0=i0_states,
|
|
739
761
|
)
|
|
740
762
|
|
|
@@ -742,7 +764,7 @@ def _run_on_cluster(
|
|
|
742
764
|
fdata = FData(
|
|
743
765
|
data={names[i]: data[i].copy() for i in range(mdata_size, fdata_end)},
|
|
744
766
|
dims={names[i]: dims[i] for i in range(mdata_size, fdata_end)},
|
|
745
|
-
loop_dims=loop_dims[1],
|
|
767
|
+
# loop_dims=loop_dims[1],
|
|
746
768
|
states_i0=i0_states,
|
|
747
769
|
)
|
|
748
770
|
|
|
@@ -751,7 +773,7 @@ def _run_on_cluster(
|
|
|
751
773
|
tdata = TData(
|
|
752
774
|
data={names[i]: data[i].copy() for i in range(fdata_end, len(data))},
|
|
753
775
|
dims={names[i]: dims[i] for i in range(fdata_end, len(data))},
|
|
754
|
-
loop_dims=loop_dims[2],
|
|
776
|
+
# loop_dims=loop_dims[2],
|
|
755
777
|
states_i0=i0_states,
|
|
756
778
|
)
|
|
757
779
|
|
foxes/engines/default.py
CHANGED
|
@@ -60,7 +60,7 @@ class DefaultEngine(Engine):
|
|
|
60
60
|
self,
|
|
61
61
|
algo,
|
|
62
62
|
model,
|
|
63
|
-
model_data
|
|
63
|
+
model_data,
|
|
64
64
|
farm_data=None,
|
|
65
65
|
point_data=None,
|
|
66
66
|
**kwargs,
|
|
@@ -75,7 +75,7 @@ class DefaultEngine(Engine):
|
|
|
75
75
|
model: foxes.core.DataCalcModel
|
|
76
76
|
The model that whose calculate function
|
|
77
77
|
should be run
|
|
78
|
-
model_data: xarray.Dataset
|
|
78
|
+
model_data: xarray.Dataset
|
|
79
79
|
The initial model data
|
|
80
80
|
farm_data: xarray.Dataset, optional
|
|
81
81
|
The initial farm data
|