foxes 0.8.1__py3-none-any.whl → 1.0__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 +353 -0
- examples/abl_states/run.py +160 -0
- examples/compare_rotors_pwakes/run.py +217 -0
- examples/compare_wakes/run.py +241 -0
- examples/dyn_wakes/run.py +311 -0
- examples/field_data_nc/run.py +121 -0
- examples/induction_RHB/run.py +201 -0
- examples/multi_height/run.py +113 -0
- examples/power_mask/run.py +249 -0
- examples/random_timeseries/run.py +210 -0
- examples/scan_row/run.py +193 -0
- examples/sector_management/run.py +162 -0
- examples/sequential/run.py +209 -0
- examples/single_state/run.py +201 -0
- examples/states_lookup_table/run.py +137 -0
- examples/streamline_wakes/run.py +138 -0
- examples/tab_file/run.py +142 -0
- examples/timelines/run.py +267 -0
- examples/timeseries/run.py +183 -0
- examples/timeseries_slurm/run.py +185 -0
- examples/wind_rose/run.py +141 -0
- examples/windio/run.py +29 -0
- examples/yawed_wake/run.py +196 -0
- foxes/__init__.py +4 -8
- foxes/algorithms/__init__.py +1 -1
- foxes/algorithms/downwind/downwind.py +232 -101
- foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -6
- foxes/algorithms/downwind/models/init_farm_data.py +1 -1
- foxes/algorithms/downwind/models/point_wakes_calc.py +5 -6
- foxes/algorithms/downwind/models/reorder_farm_output.py +0 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +4 -2
- foxes/algorithms/iterative/iterative.py +73 -33
- foxes/algorithms/iterative/models/farm_wakes_calc.py +11 -6
- foxes/algorithms/sequential/models/plugin.py +1 -1
- foxes/algorithms/sequential/sequential.py +126 -255
- foxes/constants.py +17 -2
- foxes/core/__init__.py +1 -0
- foxes/core/algorithm.py +631 -146
- foxes/core/data.py +252 -20
- foxes/core/data_calc_model.py +13 -289
- foxes/core/engine.py +630 -0
- foxes/core/farm_controller.py +37 -9
- foxes/core/farm_data_model.py +15 -0
- foxes/core/model.py +133 -80
- foxes/core/point_data_model.py +15 -0
- foxes/core/rotor_model.py +27 -21
- foxes/core/states.py +16 -0
- foxes/core/turbine_type.py +28 -0
- foxes/core/wake_frame.py +22 -4
- foxes/core/wake_model.py +2 -3
- foxes/data/windio/windio_5turbines_timeseries.yaml +23 -1
- foxes/engines/__init__.py +16 -0
- foxes/engines/dask.py +975 -0
- foxes/engines/default.py +75 -0
- foxes/engines/futures.py +72 -0
- foxes/engines/mpi.py +38 -0
- foxes/engines/multiprocess.py +74 -0
- foxes/engines/numpy.py +185 -0
- foxes/engines/pool.py +263 -0
- foxes/engines/single.py +139 -0
- foxes/input/farm_layout/__init__.py +1 -0
- foxes/input/farm_layout/from_csv.py +4 -0
- foxes/input/farm_layout/from_json.py +1 -1
- foxes/input/farm_layout/grid.py +2 -2
- foxes/input/farm_layout/ring.py +65 -0
- foxes/input/farm_layout/row.py +2 -2
- foxes/input/states/__init__.py +6 -0
- foxes/input/states/create/random_abl_states.py +1 -1
- foxes/input/states/field_data_nc.py +157 -32
- foxes/input/states/multi_height.py +127 -13
- foxes/input/states/one_point_flow.py +577 -0
- foxes/input/states/scan_ws.py +73 -2
- foxes/input/states/states_table.py +204 -35
- foxes/input/windio/__init__.py +1 -1
- foxes/input/windio/get_states.py +44 -23
- foxes/input/windio/read_attributes.py +41 -16
- foxes/input/windio/read_farm.py +116 -102
- foxes/input/windio/read_fields.py +13 -6
- foxes/input/windio/read_outputs.py +63 -22
- foxes/input/windio/runner.py +31 -17
- foxes/input/windio/windio.py +36 -22
- foxes/models/ground_models/wake_mirror.py +8 -4
- foxes/models/model_book.py +29 -18
- foxes/models/partial_wakes/rotor_points.py +3 -3
- foxes/models/rotor_models/centre.py +4 -0
- foxes/models/rotor_models/grid.py +22 -23
- foxes/models/rotor_models/levels.py +4 -5
- foxes/models/turbine_models/calculator.py +0 -2
- foxes/models/turbine_models/lookup_table.py +27 -2
- foxes/models/turbine_models/rotor_centre_calc.py +4 -3
- foxes/models/turbine_models/set_farm_vars.py +103 -34
- foxes/models/turbine_types/PCt_file.py +24 -0
- foxes/models/turbine_types/PCt_from_two.py +24 -0
- foxes/models/turbine_types/__init__.py +1 -0
- foxes/models/turbine_types/lookup.py +316 -0
- foxes/models/turbine_types/null_type.py +50 -0
- foxes/models/turbine_types/wsrho2PCt_from_two.py +24 -0
- foxes/models/turbine_types/wsti2PCt_from_two.py +24 -0
- foxes/models/vertical_profiles/data_profile.py +1 -1
- foxes/models/wake_frames/__init__.py +1 -0
- foxes/models/wake_frames/dynamic_wakes.py +424 -0
- foxes/models/wake_frames/farm_order.py +23 -3
- foxes/models/wake_frames/rotor_wd.py +4 -2
- foxes/models/wake_frames/seq_dynamic_wakes.py +56 -63
- foxes/models/wake_frames/streamlines.py +19 -20
- foxes/models/wake_frames/timelines.py +328 -127
- foxes/models/wake_frames/yawed_wakes.py +4 -1
- foxes/models/wake_models/dist_sliced.py +1 -3
- foxes/models/wake_models/induction/rankine_half_body.py +4 -4
- foxes/models/wake_models/induction/rathmann.py +2 -2
- foxes/models/wake_models/induction/self_similar.py +2 -2
- foxes/models/wake_models/induction/vortex_sheet.py +2 -2
- foxes/models/wake_models/ti/iec_ti.py +34 -17
- foxes/models/wake_models/top_hat.py +1 -1
- foxes/models/wake_models/wind/bastankhah14.py +2 -2
- foxes/models/wake_models/wind/bastankhah16.py +8 -7
- foxes/models/wake_models/wind/jensen.py +1 -1
- foxes/models/wake_models/wind/turbopark.py +2 -2
- foxes/output/__init__.py +4 -1
- foxes/output/farm_layout.py +2 -2
- foxes/output/flow_plots_2d/__init__.py +0 -1
- foxes/output/flow_plots_2d/flow_plots.py +70 -30
- foxes/output/grids.py +91 -21
- foxes/output/seq_plugins/__init__.py +2 -0
- foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +62 -20
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
- foxes/output/slice_data.py +131 -111
- foxes/output/state_turbine_map.py +18 -13
- foxes/output/state_turbine_table.py +19 -19
- foxes/utils/__init__.py +1 -1
- foxes/utils/dev_utils.py +42 -0
- foxes/utils/dict.py +1 -1
- foxes/utils/factory.py +147 -52
- foxes/utils/pandas_helpers.py +4 -3
- foxes/utils/wind_dir.py +0 -2
- foxes/utils/xarray_utils.py +25 -13
- foxes/variables.py +37 -0
- {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/METADATA +72 -34
- foxes-1.0.dist-info/RECORD +307 -0
- {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/WHEEL +1 -1
- foxes-1.0.dist-info/top_level.txt +4 -0
- tests/0_consistency/iterative/test_iterative.py +92 -0
- tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
- tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
- tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
- tests/3_examples/test_examples.py +34 -0
- foxes/VERSION +0 -1
- foxes/output/flow_plots_2d.py +0 -0
- foxes/utils/plotly_helpers.py +0 -19
- foxes/utils/runners/__init__.py +0 -1
- foxes/utils/runners/runners.py +0 -280
- foxes-0.8.1.dist-info/RECORD +0 -248
- foxes-0.8.1.dist-info/top_level.txt +0 -1
- foxes-0.8.1.dist-info/zip-safe +0 -1
- {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/LICENSE +0 -0
|
@@ -81,7 +81,6 @@ class StatesTable(States):
|
|
|
81
81
|
"""
|
|
82
82
|
super().__init__()
|
|
83
83
|
|
|
84
|
-
self.data_source = data_source
|
|
85
84
|
self.ovars = output_vars
|
|
86
85
|
self.rpars = pd_read_pars
|
|
87
86
|
self.var2col = var2col
|
|
@@ -95,11 +94,30 @@ class StatesTable(States):
|
|
|
95
94
|
f"States '{self.name}': Cannot handle both 'states_sel' and 'states_loc', please pick one"
|
|
96
95
|
)
|
|
97
96
|
|
|
98
|
-
self._weights = None
|
|
99
97
|
self._N = None
|
|
100
98
|
self._tvars = None
|
|
101
99
|
self._profiles = None
|
|
102
100
|
|
|
101
|
+
self._data_source = data_source
|
|
102
|
+
self.__weights = None
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def data_source(self):
|
|
106
|
+
"""
|
|
107
|
+
The data source
|
|
108
|
+
|
|
109
|
+
Returns
|
|
110
|
+
-------
|
|
111
|
+
s: object
|
|
112
|
+
The data source
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
if self.running:
|
|
116
|
+
raise ValueError(
|
|
117
|
+
f"States '{self.name}': Cannot acces data_source while running"
|
|
118
|
+
)
|
|
119
|
+
return self._data_source
|
|
120
|
+
|
|
103
121
|
def reset(self, algo=None, states_sel=None, states_loc=None, verbosity=0):
|
|
104
122
|
"""
|
|
105
123
|
Reset the states, optionally select states
|
|
@@ -164,7 +182,6 @@ class StatesTable(States):
|
|
|
164
182
|
Names of all sub models
|
|
165
183
|
|
|
166
184
|
"""
|
|
167
|
-
|
|
168
185
|
return list(self._profiles.values())
|
|
169
186
|
|
|
170
187
|
def load_data(self, algo, verbosity=0):
|
|
@@ -202,7 +219,7 @@ class StatesTable(States):
|
|
|
202
219
|
print(
|
|
203
220
|
f"States '{self.name}': Reading static data '{self.data_source}' from context '{STATES}'"
|
|
204
221
|
)
|
|
205
|
-
self.
|
|
222
|
+
self._data_source = algo.dbook.get_file_path(
|
|
206
223
|
STATES, self.data_source, check_raw=False
|
|
207
224
|
)
|
|
208
225
|
if verbosity:
|
|
@@ -218,21 +235,21 @@ class StatesTable(States):
|
|
|
218
235
|
elif self.states_loc is not None:
|
|
219
236
|
data = data.loc[self.states_loc]
|
|
220
237
|
self._N = len(data.index)
|
|
221
|
-
self.
|
|
238
|
+
self.__inds = data.index.to_numpy()
|
|
222
239
|
|
|
223
240
|
col_w = self.var2col.get(FV.WEIGHT, FV.WEIGHT)
|
|
224
|
-
self.
|
|
241
|
+
self.__weights = np.zeros((self._N, algo.n_turbines), dtype=FC.DTYPE)
|
|
225
242
|
if col_w in data:
|
|
226
|
-
self.
|
|
243
|
+
self.__weights[:] = data[col_w].to_numpy()[:, None]
|
|
227
244
|
elif FV.WEIGHT in self.var2col:
|
|
228
245
|
raise KeyError(
|
|
229
246
|
f"Weight variable '{col_w}' defined in var2col, but not found in states table columns {data.columns}"
|
|
230
247
|
)
|
|
231
248
|
else:
|
|
232
|
-
self.
|
|
249
|
+
self.__weights[:] = 1.0 / self._N
|
|
233
250
|
if isorg:
|
|
234
251
|
data = data.copy()
|
|
235
|
-
data[col_w] = self.
|
|
252
|
+
data[col_w] = self.__weights[:, 0]
|
|
236
253
|
|
|
237
254
|
tcols = []
|
|
238
255
|
for v in self._tvars:
|
|
@@ -273,7 +290,9 @@ class StatesTable(States):
|
|
|
273
290
|
The index labels of states, or None for default integers
|
|
274
291
|
|
|
275
292
|
"""
|
|
276
|
-
|
|
293
|
+
if self.running:
|
|
294
|
+
raise ValueError(f"States '{self.name}': Cannot acces index while running")
|
|
295
|
+
return self.__inds
|
|
277
296
|
|
|
278
297
|
def output_point_vars(self, algo):
|
|
279
298
|
"""
|
|
@@ -307,10 +326,87 @@ class StatesTable(States):
|
|
|
307
326
|
The weights, shape: (n_states, n_turbines)
|
|
308
327
|
|
|
309
328
|
"""
|
|
310
|
-
|
|
329
|
+
if self.running:
|
|
330
|
+
raise ValueError(
|
|
331
|
+
f"States '{self.name}': Cannot acces weights while running"
|
|
332
|
+
)
|
|
333
|
+
return self.__weights
|
|
334
|
+
|
|
335
|
+
def set_running(
|
|
336
|
+
self,
|
|
337
|
+
algo,
|
|
338
|
+
data_stash,
|
|
339
|
+
sel=None,
|
|
340
|
+
isel=None,
|
|
341
|
+
verbosity=0,
|
|
342
|
+
):
|
|
343
|
+
"""
|
|
344
|
+
Sets this model status to running, and moves
|
|
345
|
+
all large data to stash.
|
|
346
|
+
|
|
347
|
+
The stashed data will be returned by the
|
|
348
|
+
unset_running() function after running calculations.
|
|
349
|
+
|
|
350
|
+
Parameters
|
|
351
|
+
----------
|
|
352
|
+
algo: foxes.core.Algorithm
|
|
353
|
+
The calculation algorithm
|
|
354
|
+
data_stash: dict
|
|
355
|
+
Large data stash, this function adds data here.
|
|
356
|
+
Key: model name. Value: dict, large model data
|
|
357
|
+
sel: dict, optional
|
|
358
|
+
The subset selection dictionary
|
|
359
|
+
isel: dict, optional
|
|
360
|
+
The index subset selection dictionary
|
|
361
|
+
verbosity: int
|
|
362
|
+
The verbosity level, 0 = silent
|
|
363
|
+
|
|
364
|
+
"""
|
|
365
|
+
super().set_running(algo, data_stash, sel, isel, verbosity)
|
|
366
|
+
|
|
367
|
+
data_stash[self.name] = dict(
|
|
368
|
+
data_source=self._data_source,
|
|
369
|
+
weights=self.__weights,
|
|
370
|
+
inds=self.__inds,
|
|
371
|
+
)
|
|
372
|
+
del self._data_source, self.__weights, self.__inds
|
|
373
|
+
|
|
374
|
+
def unset_running(
|
|
375
|
+
self,
|
|
376
|
+
algo,
|
|
377
|
+
data_stash,
|
|
378
|
+
sel=None,
|
|
379
|
+
isel=None,
|
|
380
|
+
verbosity=0,
|
|
381
|
+
):
|
|
382
|
+
"""
|
|
383
|
+
Sets this model status to not running, recovering large data
|
|
384
|
+
from stash
|
|
385
|
+
|
|
386
|
+
Parameters
|
|
387
|
+
----------
|
|
388
|
+
algo: foxes.core.Algorithm
|
|
389
|
+
The calculation algorithm
|
|
390
|
+
data_stash: dict
|
|
391
|
+
Large data stash, this function adds data here.
|
|
392
|
+
Key: model name. Value: dict, large model data
|
|
393
|
+
sel: dict, optional
|
|
394
|
+
The subset selection dictionary
|
|
395
|
+
isel: dict, optional
|
|
396
|
+
The index subset selection dictionary
|
|
397
|
+
verbosity: int
|
|
398
|
+
The verbosity level, 0 = silent
|
|
399
|
+
|
|
400
|
+
"""
|
|
401
|
+
super().unset_running(algo, data_stash, sel, isel, verbosity)
|
|
402
|
+
|
|
403
|
+
data = data_stash[self.name]
|
|
404
|
+
self._data_source = data.pop("data_source")
|
|
405
|
+
self.__weights = data.pop("weights")
|
|
406
|
+
self.__inds = data.pop("inds")
|
|
311
407
|
|
|
312
408
|
def calculate(self, algo, mdata, fdata, tdata):
|
|
313
|
-
"""
|
|
409
|
+
"""
|
|
314
410
|
The main model calculation.
|
|
315
411
|
|
|
316
412
|
This function is executed on a single chunk of data,
|
|
@@ -368,7 +464,7 @@ class StatesTable(States):
|
|
|
368
464
|
The verbosity level
|
|
369
465
|
|
|
370
466
|
"""
|
|
371
|
-
self.
|
|
467
|
+
self.__weights = None
|
|
372
468
|
self._N = None
|
|
373
469
|
self._tvars = None
|
|
374
470
|
|
|
@@ -412,11 +508,11 @@ class TabStates(StatesTable):
|
|
|
412
508
|
"""
|
|
413
509
|
self._normalize = normalize
|
|
414
510
|
if isinstance(data_source, Dataset):
|
|
415
|
-
self.
|
|
416
|
-
self.
|
|
511
|
+
self.__tab_source = None
|
|
512
|
+
self.__tab_data = data_source
|
|
417
513
|
elif isinstance(data_source, (str, Path)):
|
|
418
|
-
self.
|
|
419
|
-
self.
|
|
514
|
+
self.__tab_source = data_source
|
|
515
|
+
self.__tab_data = None
|
|
420
516
|
else:
|
|
421
517
|
raise TypeError(
|
|
422
518
|
f"Expecting str, Path or xarray.Dataset as data_source, got {type(data_source)}"
|
|
@@ -448,47 +544,47 @@ class TabStates(StatesTable):
|
|
|
448
544
|
|
|
449
545
|
"""
|
|
450
546
|
if self.data_source is None:
|
|
451
|
-
if self.
|
|
452
|
-
if not Path(self.
|
|
547
|
+
if self.__tab_data is None:
|
|
548
|
+
if not Path(self.__tab_source).is_file():
|
|
453
549
|
if verbosity:
|
|
454
550
|
print(
|
|
455
|
-
f"States '{self.name}': Reading static data '{self.
|
|
551
|
+
f"States '{self.name}': Reading static data '{self.__tab_source}' from context '{STATES}'"
|
|
456
552
|
)
|
|
457
|
-
self.
|
|
458
|
-
STATES, self.
|
|
553
|
+
self.__tab_source = algo.dbook.get_file_path(
|
|
554
|
+
STATES, self.__tab_source, check_raw=False
|
|
459
555
|
)
|
|
460
556
|
if verbosity:
|
|
461
|
-
print(f"Path: {self.
|
|
557
|
+
print(f"Path: {self.__tab_source}")
|
|
462
558
|
elif verbosity:
|
|
463
|
-
print(f"States '{self.name}': Reading file {self.
|
|
464
|
-
self.
|
|
559
|
+
print(f"States '{self.name}': Reading file {self.__tab_source}")
|
|
560
|
+
self.__tab_data = read_tab_file(self.__tab_source, self._normalize)
|
|
465
561
|
|
|
466
|
-
a = self.
|
|
467
|
-
b = self.
|
|
562
|
+
a = self.__tab_data.attrs["factor_ws"]
|
|
563
|
+
b = self.__tab_data.attrs["shift_wd"]
|
|
468
564
|
if b != 0.0:
|
|
469
565
|
raise ValueError(
|
|
470
566
|
f"{self.name}: shift_wd = {b} is not supported, expecting zero"
|
|
471
567
|
)
|
|
472
568
|
|
|
473
|
-
wd0 = self.
|
|
569
|
+
wd0 = self.__tab_data["wd"].to_numpy()
|
|
474
570
|
ws0 = a * np.append(
|
|
475
|
-
np.array([0], dtype=FC.DTYPE), self.
|
|
571
|
+
np.array([0], dtype=FC.DTYPE), self.__tab_data["ws"].to_numpy()
|
|
476
572
|
)
|
|
477
573
|
ws0 = 0.5 * (ws0[:-1] + ws0[1:])
|
|
478
574
|
|
|
479
|
-
n_ws = self.
|
|
480
|
-
n_wd = self.
|
|
575
|
+
n_ws = self.__tab_data.sizes["ws"]
|
|
576
|
+
n_wd = self.__tab_data.sizes["wd"]
|
|
481
577
|
ws = np.zeros((n_ws, n_wd), dtype=FC.DTYPE)
|
|
482
578
|
wd = np.zeros((n_ws, n_wd), dtype=FC.DTYPE)
|
|
483
579
|
ws[:] = ws0[:, None]
|
|
484
580
|
wd[:] = wd0[None, :]
|
|
485
581
|
|
|
486
|
-
wd_freq = self.
|
|
487
|
-
weights = self.
|
|
582
|
+
wd_freq = self.__tab_data["wd_freq"].to_numpy() / 100
|
|
583
|
+
weights = self.__tab_data["ws_freq"].to_numpy() * wd_freq[None, :] / 1000
|
|
488
584
|
|
|
489
585
|
sel = weights > 0
|
|
490
586
|
|
|
491
|
-
self.
|
|
587
|
+
self._data_source = pd.DataFrame(
|
|
492
588
|
index=np.arange(np.sum(sel)),
|
|
493
589
|
data={
|
|
494
590
|
FV.WS: ws[sel],
|
|
@@ -496,6 +592,79 @@ class TabStates(StatesTable):
|
|
|
496
592
|
FV.WEIGHT: weights[sel],
|
|
497
593
|
},
|
|
498
594
|
)
|
|
499
|
-
self.
|
|
595
|
+
self._data_source.index.name = FC.STATE
|
|
500
596
|
|
|
501
597
|
return super().load_data(algo, verbosity)
|
|
598
|
+
|
|
599
|
+
def set_running(
|
|
600
|
+
self,
|
|
601
|
+
algo,
|
|
602
|
+
data_stash,
|
|
603
|
+
sel=None,
|
|
604
|
+
isel=None,
|
|
605
|
+
verbosity=0,
|
|
606
|
+
):
|
|
607
|
+
"""
|
|
608
|
+
Sets this model status to running, and moves
|
|
609
|
+
all large data to stash.
|
|
610
|
+
|
|
611
|
+
The stashed data will be returned by the
|
|
612
|
+
unset_running() function after running calculations.
|
|
613
|
+
|
|
614
|
+
Parameters
|
|
615
|
+
----------
|
|
616
|
+
algo: foxes.core.Algorithm
|
|
617
|
+
The calculation algorithm
|
|
618
|
+
data_stash: dict
|
|
619
|
+
Large data stash, this function adds data here.
|
|
620
|
+
Key: model name. Value: dict, large model data
|
|
621
|
+
sel: dict, optional
|
|
622
|
+
The subset selection dictionary
|
|
623
|
+
isel: dict, optional
|
|
624
|
+
The index subset selection dictionary
|
|
625
|
+
verbosity: int
|
|
626
|
+
The verbosity level, 0 = silent
|
|
627
|
+
|
|
628
|
+
"""
|
|
629
|
+
super().set_running(algo, data_stash, sel, isel, verbosity)
|
|
630
|
+
|
|
631
|
+
data_stash[self.name].update(
|
|
632
|
+
dict(
|
|
633
|
+
tab_source=self.__tab_source,
|
|
634
|
+
tab_data=self.__tab_data,
|
|
635
|
+
)
|
|
636
|
+
)
|
|
637
|
+
del self.__tab_source, self.__tab_data
|
|
638
|
+
|
|
639
|
+
def unset_running(
|
|
640
|
+
self,
|
|
641
|
+
algo,
|
|
642
|
+
data_stash,
|
|
643
|
+
sel=None,
|
|
644
|
+
isel=None,
|
|
645
|
+
verbosity=0,
|
|
646
|
+
):
|
|
647
|
+
"""
|
|
648
|
+
Sets this model status to not running, recovering large data
|
|
649
|
+
from stash
|
|
650
|
+
|
|
651
|
+
Parameters
|
|
652
|
+
----------
|
|
653
|
+
algo: foxes.core.Algorithm
|
|
654
|
+
The calculation algorithm
|
|
655
|
+
data_stash: dict
|
|
656
|
+
Large data stash, this function adds data here.
|
|
657
|
+
Key: model name. Value: dict, large model data
|
|
658
|
+
sel: dict, optional
|
|
659
|
+
The subset selection dictionary
|
|
660
|
+
isel: dict, optional
|
|
661
|
+
The index subset selection dictionary
|
|
662
|
+
verbosity: int
|
|
663
|
+
The verbosity level, 0 = silent
|
|
664
|
+
|
|
665
|
+
"""
|
|
666
|
+
super().unset_running(algo, data_stash, sel, isel, verbosity)
|
|
667
|
+
|
|
668
|
+
data = data_stash[self.name]
|
|
669
|
+
self.__tab_source = data.pop("tab_source")
|
|
670
|
+
self.__tab_data = data.pop("tab_data")
|
foxes/input/windio/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ Functions for usingin windIO yaml files as input.
|
|
|
5
5
|
from .windio import read_windio
|
|
6
6
|
from .read_fields import wio2foxes, foxes2wio
|
|
7
7
|
from .get_states import get_states
|
|
8
|
-
from .read_farm import
|
|
8
|
+
from .read_farm import read_turbine_types, read_layout
|
|
9
9
|
from .read_attributes import read_attributes
|
|
10
10
|
from .read_outputs import read_outputs
|
|
11
11
|
from .runner import WindioRunner
|
foxes/input/windio/get_states.py
CHANGED
|
@@ -7,14 +7,18 @@ from foxes.core import States
|
|
|
7
7
|
import foxes.constants as FC
|
|
8
8
|
import foxes.variables as FV
|
|
9
9
|
|
|
10
|
+
|
|
10
11
|
def _get_profiles(coords, fields, dims, ovars, fixval, verbosity):
|
|
11
12
|
"""Read ABL profiles information
|
|
12
13
|
:group: input.windio
|
|
13
14
|
"""
|
|
14
15
|
profiles = {}
|
|
15
16
|
if FV.Z0 in fields:
|
|
16
|
-
if FV.H not in fields
|
|
17
|
-
|
|
17
|
+
if FV.H not in fields:
|
|
18
|
+
if verbosity > 0:
|
|
19
|
+
print(
|
|
20
|
+
f"Ignoring '{FV.Z0}', since no reference_height found. No ABL profile activated."
|
|
21
|
+
)
|
|
18
22
|
elif FV.MOL in fields:
|
|
19
23
|
ovars.append(FV.MOL)
|
|
20
24
|
fixval[FV.H] = fields[FV.H]
|
|
@@ -23,14 +27,20 @@ def _get_profiles(coords, fields, dims, ovars, fixval, verbosity):
|
|
|
23
27
|
fixval[FV.H] = fields[FV.H]
|
|
24
28
|
profiles = {FV.WS: "ABLLogNeutralWsProfile"}
|
|
25
29
|
elif FV.H in fields and verbosity > 0:
|
|
26
|
-
print(
|
|
30
|
+
print(
|
|
31
|
+
f"Ignoring '{FV.H}', since no '{FV.Z0}' data found. No ABL profile activated."
|
|
32
|
+
)
|
|
27
33
|
if len(profiles) and verbosity > 2:
|
|
28
|
-
print(
|
|
29
|
-
|
|
34
|
+
print(
|
|
35
|
+
f" Selecting ABL profile '{profiles[FV.WS]}', {FV.H} = {fields[FV.H]} m"
|
|
36
|
+
)
|
|
37
|
+
|
|
30
38
|
return profiles
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _get_SingleStateStates(
|
|
42
|
+
coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
|
|
43
|
+
):
|
|
34
44
|
"""Try to generate single state parameters
|
|
35
45
|
:group: input.windio
|
|
36
46
|
"""
|
|
@@ -66,8 +76,10 @@ def _get_SingleStateStates(coords, fields, dims, states_dict,
|
|
|
66
76
|
)
|
|
67
77
|
return True
|
|
68
78
|
|
|
69
|
-
|
|
70
|
-
|
|
79
|
+
|
|
80
|
+
def _get_Timeseries(
|
|
81
|
+
coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
|
|
82
|
+
):
|
|
71
83
|
"""Try to generate time series parameters
|
|
72
84
|
:group: input.windio
|
|
73
85
|
"""
|
|
@@ -100,24 +112,28 @@ def _get_Timeseries(coords, fields, dims, states_dict,
|
|
|
100
112
|
return True
|
|
101
113
|
return False
|
|
102
114
|
|
|
103
|
-
|
|
104
|
-
|
|
115
|
+
|
|
116
|
+
def _get_MultiHeightNCTimeseries(
|
|
117
|
+
coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
|
|
118
|
+
):
|
|
105
119
|
"""Try to generate time series parameters
|
|
106
120
|
:group: input.windio
|
|
107
121
|
"""
|
|
108
122
|
if len(coords) == 2 and FC.TIME in coords and FV.H in coords:
|
|
109
123
|
if verbosity > 2:
|
|
110
124
|
print(" selecting class 'MultiHeightNCTimeseries'")
|
|
111
|
-
|
|
125
|
+
|
|
112
126
|
if len(profiles) and verbosity > 0:
|
|
113
|
-
print(
|
|
127
|
+
print(
|
|
128
|
+
f"Ignoring profile '{profiles[FV.WS]}' for states class 'MultiHeightNCTimeseries'"
|
|
129
|
+
)
|
|
114
130
|
|
|
115
131
|
data = {}
|
|
116
132
|
fix = {}
|
|
117
133
|
for v, d in fields.items():
|
|
118
134
|
if dims[v] == (FC.TIME, FV.H):
|
|
119
135
|
data[v] = ((FC.TIME, FV.H), d)
|
|
120
|
-
|
|
136
|
+
elif dims[v] == (FV.H, FC.TIME):
|
|
121
137
|
data[v] = ((FC.TIME, FV.H), np.swapaxes(d, 0, 1))
|
|
122
138
|
elif len(dims[v]) == 0:
|
|
123
139
|
fix[v] = d
|
|
@@ -139,6 +155,7 @@ def _get_MultiHeightNCTimeseries(coords, fields, dims, states_dict,
|
|
|
139
155
|
return True
|
|
140
156
|
return False
|
|
141
157
|
|
|
158
|
+
|
|
142
159
|
def get_states(coords, fields, dims, verbosity=1):
|
|
143
160
|
"""
|
|
144
161
|
Reads states parameters from windio input
|
|
@@ -164,18 +181,22 @@ def get_states(coords, fields, dims, verbosity=1):
|
|
|
164
181
|
"""
|
|
165
182
|
if verbosity > 2:
|
|
166
183
|
print(" Preparing states")
|
|
167
|
-
|
|
184
|
+
|
|
168
185
|
ovars = [FV.WS, FV.WD, FV.TI, FV.RHO]
|
|
169
|
-
fixval = {FV.TI: 0.05, FV.RHO: 1.225}
|
|
186
|
+
fixval = {FV.TI: 0.05, FV.RHO: 1.225}
|
|
170
187
|
profiles = _get_profiles(coords, fields, dims, ovars, fixval, verbosity)
|
|
171
188
|
|
|
172
189
|
states_dict = {}
|
|
173
|
-
if
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
190
|
+
if (
|
|
191
|
+
_get_SingleStateStates(
|
|
192
|
+
coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
|
|
193
|
+
)
|
|
194
|
+
or _get_Timeseries(
|
|
195
|
+
coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
|
|
196
|
+
)
|
|
197
|
+
or _get_MultiHeightNCTimeseries(
|
|
198
|
+
coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
|
|
199
|
+
)
|
|
179
200
|
):
|
|
180
201
|
return States.new(**states_dict)
|
|
181
202
|
else:
|
|
@@ -5,7 +5,9 @@ import foxes.variables as FV
|
|
|
5
5
|
from .read_outputs import read_outputs
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def _read_wind_deficit(
|
|
8
|
+
def _read_wind_deficit(
|
|
9
|
+
wake_model_key, wind_deficit, superposition, induction, algo_dict, verbosity
|
|
10
|
+
):
|
|
9
11
|
"""Reads the wind deficit wake model"""
|
|
10
12
|
|
|
11
13
|
wind_def_map = Dict(
|
|
@@ -32,11 +34,11 @@ def _read_wind_deficit(wind_deficit, superposition, induction, algo_dict, verbos
|
|
|
32
34
|
},
|
|
33
35
|
name="ws_sup_dict",
|
|
34
36
|
)
|
|
35
|
-
|
|
37
|
+
|
|
36
38
|
wname = wind_deficit.pop("name")
|
|
37
39
|
eff_ws = wind_deficit.pop("use_effective_ws", True)
|
|
38
40
|
if verbosity > 2:
|
|
39
|
-
print(" Reading
|
|
41
|
+
print(" Reading", wake_model_key)
|
|
40
42
|
print(" Name :", wname)
|
|
41
43
|
print(" Eff ws :", eff_ws)
|
|
42
44
|
print(" Contents:", [k for k in wind_deficit.keys()])
|
|
@@ -73,6 +75,7 @@ def _read_wind_deficit(wind_deficit, superposition, induction, algo_dict, verbos
|
|
|
73
75
|
|
|
74
76
|
return ka, kb, amb_ti
|
|
75
77
|
|
|
78
|
+
|
|
76
79
|
def _read_turbulence(
|
|
77
80
|
turbulence_model, superposition, induction, algo_dict, ka, kb, amb_ti, verbosity
|
|
78
81
|
):
|
|
@@ -99,7 +102,7 @@ def _read_turbulence(
|
|
|
99
102
|
print(" Reading turbulence_model")
|
|
100
103
|
print(" Name:", wname)
|
|
101
104
|
print(" Contents:", [k for k in turbulence_model.keys()])
|
|
102
|
-
if wname
|
|
105
|
+
if wname not in ["None", "none"]:
|
|
103
106
|
tiwake_dict = dict(wmodel_type=twake_def_map[wname], induction=induction)
|
|
104
107
|
if wname == "IEC-TI-2019":
|
|
105
108
|
tiwake_dict["opening_angle"] = None
|
|
@@ -129,6 +132,7 @@ def _read_turbulence(
|
|
|
129
132
|
print(" ", algo_dict["mbook"].wake_models[wname])
|
|
130
133
|
algo_dict["wake_models"].append(wname)
|
|
131
134
|
|
|
135
|
+
|
|
132
136
|
def _read_blockage(blockage_model, induction, algo_dict, verbosity):
|
|
133
137
|
"""Reads the blockage model"""
|
|
134
138
|
indc_def_map = Dict(
|
|
@@ -146,7 +150,7 @@ def _read_blockage(blockage_model, induction, algo_dict, verbosity):
|
|
|
146
150
|
print(" Reading blockage_model")
|
|
147
151
|
print(" Name:", wname)
|
|
148
152
|
print(" Contents:", [k for k in blockage_model.keys()])
|
|
149
|
-
if wname
|
|
153
|
+
if wname not in ["None", "none"]:
|
|
150
154
|
indc_dict = Dict(wmodel_type=indc_def_map[wname], induction=induction)
|
|
151
155
|
algo_dict["mbook"].wake_models[wname] = WakeModel.new(**indc_dict)
|
|
152
156
|
if verbosity > 2:
|
|
@@ -155,6 +159,7 @@ def _read_blockage(blockage_model, induction, algo_dict, verbosity):
|
|
|
155
159
|
algo_dict["wake_models"].append(wname)
|
|
156
160
|
algo_dict["algo_type"] = "Iterative"
|
|
157
161
|
|
|
162
|
+
|
|
158
163
|
def _read_rotor_averaging(rotor_averaging, algo_dict, verbosity):
|
|
159
164
|
"""Reads the rotor averaging"""
|
|
160
165
|
if verbosity > 2:
|
|
@@ -177,16 +182,20 @@ def _read_rotor_averaging(rotor_averaging, algo_dict, verbosity):
|
|
|
177
182
|
print(" wake_averaging :", wake_averaging)
|
|
178
183
|
print(" ws exponent power :", wse_P)
|
|
179
184
|
print(" ws exponent ct :", wse_ct)
|
|
185
|
+
|
|
180
186
|
if background_averaging in ["center", "centre"]:
|
|
181
187
|
algo_dict["rotor_model"] = "centre"
|
|
188
|
+
elif background_averaging in ["none", "None", None]:
|
|
189
|
+
algo_dict["rotor_model"] = None
|
|
182
190
|
elif background_averaging == "grid":
|
|
183
191
|
algo_dict["rotor_model"] = f"grid{nx*ny}"
|
|
184
192
|
else:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
)
|
|
193
|
+
algo_dict["rotor_model"] = background_averaging
|
|
194
|
+
|
|
188
195
|
if wake_averaging in ["centre", "center"]:
|
|
189
196
|
algo_dict["partial_wakes"] = "centre"
|
|
197
|
+
elif wake_averaging in ["none", "None", "auto", None]:
|
|
198
|
+
algo_dict["partial_wakes"] = None
|
|
190
199
|
elif wake_averaging == "grid":
|
|
191
200
|
if background_averaging == "grid":
|
|
192
201
|
algo_dict["partial_wakes"] = "rotor_points"
|
|
@@ -197,10 +206,12 @@ def _read_rotor_averaging(rotor_averaging, algo_dict, verbosity):
|
|
|
197
206
|
algo_dict["partial_wakes"] = grid
|
|
198
207
|
else:
|
|
199
208
|
algo_dict["partial_wakes"] = wake_averaging
|
|
209
|
+
|
|
200
210
|
if verbosity > 2:
|
|
201
211
|
print(" --> rotor_model :", algo_dict["rotor_model"])
|
|
202
212
|
print(" --> partial_wakes :", algo_dict["partial_wakes"])
|
|
203
213
|
|
|
214
|
+
|
|
204
215
|
def _read_deflection(deflection, induction, algo_dict, verbosity):
|
|
205
216
|
"""Reads deflection model"""
|
|
206
217
|
defl_def_map = Dict(
|
|
@@ -228,6 +239,7 @@ def _read_deflection(deflection, induction, algo_dict, verbosity):
|
|
|
228
239
|
print(" ", algo_dict["mbook"].wake_frames[wname])
|
|
229
240
|
algo_dict["wake_frame"] = wname
|
|
230
241
|
|
|
242
|
+
|
|
231
243
|
def _read_analysis(wio_ana, algo_dict, verbosity):
|
|
232
244
|
"""Reads the windio analyses"""
|
|
233
245
|
if verbosity > 2:
|
|
@@ -253,16 +265,26 @@ def _read_analysis(wio_ana, algo_dict, verbosity):
|
|
|
253
265
|
print(" axial induction model:", induction)
|
|
254
266
|
|
|
255
267
|
# wind deficit model:
|
|
256
|
-
|
|
268
|
+
wake_model_key = (
|
|
269
|
+
"wind_deficit_model" if "wind_deficit_model" in wio_ana else "wake_model"
|
|
270
|
+
)
|
|
271
|
+
wind_deficit = Dict(wio_ana[wake_model_key], name=wake_model_key)
|
|
257
272
|
ka, kb, amb_ti = _read_wind_deficit(
|
|
258
|
-
wind_deficit, superposition, induction, algo_dict, verbosity
|
|
273
|
+
wake_model_key, wind_deficit, superposition, induction, algo_dict, verbosity
|
|
259
274
|
)
|
|
260
275
|
|
|
261
276
|
# turbulence model:
|
|
262
277
|
if "turbulence_model" in wio_ana:
|
|
263
278
|
turbulence_model = Dict(wio_ana["turbulence_model"], name="turbulence_model")
|
|
264
279
|
_read_turbulence(
|
|
265
|
-
turbulence_model,
|
|
280
|
+
turbulence_model,
|
|
281
|
+
superposition,
|
|
282
|
+
induction,
|
|
283
|
+
algo_dict,
|
|
284
|
+
ka,
|
|
285
|
+
kb,
|
|
286
|
+
amb_ti,
|
|
287
|
+
verbosity,
|
|
266
288
|
)
|
|
267
289
|
elif verbosity > 0:
|
|
268
290
|
print("turbulence_model not found, not using a TI wake model")
|
|
@@ -273,21 +295,22 @@ def _read_analysis(wio_ana, algo_dict, verbosity):
|
|
|
273
295
|
_read_blockage(blockage_model, induction, algo_dict, verbosity)
|
|
274
296
|
elif verbosity > 0:
|
|
275
297
|
print("blockage_model not found, not using a turbine induction model")
|
|
276
|
-
|
|
298
|
+
|
|
277
299
|
# rotor_averaging:
|
|
278
300
|
if "rotor_averaging" in wio_ana:
|
|
279
301
|
rotor_averaging = Dict(wio_ana["rotor_averaging"], name="rotor_averaging")
|
|
280
302
|
_read_rotor_averaging(rotor_averaging, algo_dict, verbosity)
|
|
281
303
|
elif verbosity > 0:
|
|
282
304
|
print("rotor_averaging not found, using default settings")
|
|
283
|
-
|
|
305
|
+
|
|
284
306
|
# deflection:
|
|
285
307
|
if "deflection_model" in wio_ana:
|
|
286
308
|
deflection = Dict(wio_ana["deflection_model"], name="deflection_model")
|
|
287
309
|
_read_deflection(deflection, induction, algo_dict, verbosity)
|
|
288
310
|
elif verbosity > 0:
|
|
289
311
|
print("deflection_model not found, using default settings")
|
|
290
|
-
|
|
312
|
+
|
|
313
|
+
|
|
291
314
|
def read_attributes(wio, algo_dict, verbosity):
|
|
292
315
|
"""
|
|
293
316
|
Reads the attributes part of windio
|
|
@@ -305,6 +328,8 @@ def read_attributes(wio, algo_dict, verbosity):
|
|
|
305
328
|
-------
|
|
306
329
|
out_dicts: list of dict
|
|
307
330
|
The output dictionaries
|
|
331
|
+
odir: pathlib.Path
|
|
332
|
+
Path to the output folder
|
|
308
333
|
|
|
309
334
|
:group: input.windio
|
|
310
335
|
|
|
@@ -333,6 +358,6 @@ def read_attributes(wio, algo_dict, verbosity):
|
|
|
333
358
|
out_dicts = []
|
|
334
359
|
if "outputs" in wio_attrs:
|
|
335
360
|
outputs = Dict(wio_attrs["outputs"], name="outputs")
|
|
336
|
-
out_dicts = read_outputs(outputs, algo_dict, verbosity)
|
|
361
|
+
out_dicts, odir = read_outputs(outputs, algo_dict, verbosity)
|
|
337
362
|
|
|
338
|
-
return out_dicts
|
|
363
|
+
return out_dicts, odir
|