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.

Files changed (175) hide show
  1. docs/source/conf.py +353 -0
  2. examples/abl_states/run.py +160 -0
  3. examples/compare_rotors_pwakes/run.py +217 -0
  4. examples/compare_wakes/run.py +241 -0
  5. examples/dyn_wakes/run.py +311 -0
  6. examples/field_data_nc/run.py +121 -0
  7. examples/induction_RHB/run.py +201 -0
  8. examples/multi_height/run.py +113 -0
  9. examples/power_mask/run.py +249 -0
  10. examples/random_timeseries/run.py +210 -0
  11. examples/scan_row/run.py +193 -0
  12. examples/sector_management/run.py +162 -0
  13. examples/sequential/run.py +209 -0
  14. examples/single_state/run.py +201 -0
  15. examples/states_lookup_table/run.py +137 -0
  16. examples/streamline_wakes/run.py +138 -0
  17. examples/tab_file/run.py +142 -0
  18. examples/timelines/run.py +267 -0
  19. examples/timeseries/run.py +183 -0
  20. examples/timeseries_slurm/run.py +185 -0
  21. examples/wind_rose/run.py +141 -0
  22. examples/windio/run.py +29 -0
  23. examples/yawed_wake/run.py +196 -0
  24. foxes/__init__.py +4 -8
  25. foxes/algorithms/__init__.py +1 -1
  26. foxes/algorithms/downwind/downwind.py +232 -101
  27. foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -6
  28. foxes/algorithms/downwind/models/init_farm_data.py +1 -1
  29. foxes/algorithms/downwind/models/point_wakes_calc.py +5 -6
  30. foxes/algorithms/downwind/models/reorder_farm_output.py +0 -1
  31. foxes/algorithms/downwind/models/set_amb_point_results.py +4 -2
  32. foxes/algorithms/iterative/iterative.py +73 -33
  33. foxes/algorithms/iterative/models/farm_wakes_calc.py +11 -6
  34. foxes/algorithms/sequential/models/plugin.py +1 -1
  35. foxes/algorithms/sequential/sequential.py +126 -255
  36. foxes/constants.py +17 -2
  37. foxes/core/__init__.py +1 -0
  38. foxes/core/algorithm.py +631 -146
  39. foxes/core/data.py +252 -20
  40. foxes/core/data_calc_model.py +13 -289
  41. foxes/core/engine.py +630 -0
  42. foxes/core/farm_controller.py +37 -9
  43. foxes/core/farm_data_model.py +15 -0
  44. foxes/core/model.py +133 -80
  45. foxes/core/point_data_model.py +15 -0
  46. foxes/core/rotor_model.py +27 -21
  47. foxes/core/states.py +16 -0
  48. foxes/core/turbine_type.py +28 -0
  49. foxes/core/wake_frame.py +22 -4
  50. foxes/core/wake_model.py +2 -3
  51. foxes/data/windio/windio_5turbines_timeseries.yaml +23 -1
  52. foxes/engines/__init__.py +16 -0
  53. foxes/engines/dask.py +975 -0
  54. foxes/engines/default.py +75 -0
  55. foxes/engines/futures.py +72 -0
  56. foxes/engines/mpi.py +38 -0
  57. foxes/engines/multiprocess.py +74 -0
  58. foxes/engines/numpy.py +185 -0
  59. foxes/engines/pool.py +263 -0
  60. foxes/engines/single.py +139 -0
  61. foxes/input/farm_layout/__init__.py +1 -0
  62. foxes/input/farm_layout/from_csv.py +4 -0
  63. foxes/input/farm_layout/from_json.py +1 -1
  64. foxes/input/farm_layout/grid.py +2 -2
  65. foxes/input/farm_layout/ring.py +65 -0
  66. foxes/input/farm_layout/row.py +2 -2
  67. foxes/input/states/__init__.py +6 -0
  68. foxes/input/states/create/random_abl_states.py +1 -1
  69. foxes/input/states/field_data_nc.py +157 -32
  70. foxes/input/states/multi_height.py +127 -13
  71. foxes/input/states/one_point_flow.py +577 -0
  72. foxes/input/states/scan_ws.py +73 -2
  73. foxes/input/states/states_table.py +204 -35
  74. foxes/input/windio/__init__.py +1 -1
  75. foxes/input/windio/get_states.py +44 -23
  76. foxes/input/windio/read_attributes.py +41 -16
  77. foxes/input/windio/read_farm.py +116 -102
  78. foxes/input/windio/read_fields.py +13 -6
  79. foxes/input/windio/read_outputs.py +63 -22
  80. foxes/input/windio/runner.py +31 -17
  81. foxes/input/windio/windio.py +36 -22
  82. foxes/models/ground_models/wake_mirror.py +8 -4
  83. foxes/models/model_book.py +29 -18
  84. foxes/models/partial_wakes/rotor_points.py +3 -3
  85. foxes/models/rotor_models/centre.py +4 -0
  86. foxes/models/rotor_models/grid.py +22 -23
  87. foxes/models/rotor_models/levels.py +4 -5
  88. foxes/models/turbine_models/calculator.py +0 -2
  89. foxes/models/turbine_models/lookup_table.py +27 -2
  90. foxes/models/turbine_models/rotor_centre_calc.py +4 -3
  91. foxes/models/turbine_models/set_farm_vars.py +103 -34
  92. foxes/models/turbine_types/PCt_file.py +24 -0
  93. foxes/models/turbine_types/PCt_from_two.py +24 -0
  94. foxes/models/turbine_types/__init__.py +1 -0
  95. foxes/models/turbine_types/lookup.py +316 -0
  96. foxes/models/turbine_types/null_type.py +50 -0
  97. foxes/models/turbine_types/wsrho2PCt_from_two.py +24 -0
  98. foxes/models/turbine_types/wsti2PCt_from_two.py +24 -0
  99. foxes/models/vertical_profiles/data_profile.py +1 -1
  100. foxes/models/wake_frames/__init__.py +1 -0
  101. foxes/models/wake_frames/dynamic_wakes.py +424 -0
  102. foxes/models/wake_frames/farm_order.py +23 -3
  103. foxes/models/wake_frames/rotor_wd.py +4 -2
  104. foxes/models/wake_frames/seq_dynamic_wakes.py +56 -63
  105. foxes/models/wake_frames/streamlines.py +19 -20
  106. foxes/models/wake_frames/timelines.py +328 -127
  107. foxes/models/wake_frames/yawed_wakes.py +4 -1
  108. foxes/models/wake_models/dist_sliced.py +1 -3
  109. foxes/models/wake_models/induction/rankine_half_body.py +4 -4
  110. foxes/models/wake_models/induction/rathmann.py +2 -2
  111. foxes/models/wake_models/induction/self_similar.py +2 -2
  112. foxes/models/wake_models/induction/vortex_sheet.py +2 -2
  113. foxes/models/wake_models/ti/iec_ti.py +34 -17
  114. foxes/models/wake_models/top_hat.py +1 -1
  115. foxes/models/wake_models/wind/bastankhah14.py +2 -2
  116. foxes/models/wake_models/wind/bastankhah16.py +8 -7
  117. foxes/models/wake_models/wind/jensen.py +1 -1
  118. foxes/models/wake_models/wind/turbopark.py +2 -2
  119. foxes/output/__init__.py +4 -1
  120. foxes/output/farm_layout.py +2 -2
  121. foxes/output/flow_plots_2d/__init__.py +0 -1
  122. foxes/output/flow_plots_2d/flow_plots.py +70 -30
  123. foxes/output/grids.py +91 -21
  124. foxes/output/seq_plugins/__init__.py +2 -0
  125. foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +62 -20
  126. foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
  127. foxes/output/slice_data.py +131 -111
  128. foxes/output/state_turbine_map.py +18 -13
  129. foxes/output/state_turbine_table.py +19 -19
  130. foxes/utils/__init__.py +1 -1
  131. foxes/utils/dev_utils.py +42 -0
  132. foxes/utils/dict.py +1 -1
  133. foxes/utils/factory.py +147 -52
  134. foxes/utils/pandas_helpers.py +4 -3
  135. foxes/utils/wind_dir.py +0 -2
  136. foxes/utils/xarray_utils.py +25 -13
  137. foxes/variables.py +37 -0
  138. {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/METADATA +72 -34
  139. foxes-1.0.dist-info/RECORD +307 -0
  140. {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/WHEEL +1 -1
  141. foxes-1.0.dist-info/top_level.txt +4 -0
  142. tests/0_consistency/iterative/test_iterative.py +92 -0
  143. tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
  144. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
  145. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
  146. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
  147. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
  148. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
  149. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
  150. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
  151. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
  152. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
  153. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
  154. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
  155. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
  156. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
  157. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
  158. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
  159. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
  160. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
  161. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
  162. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
  163. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
  164. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
  165. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
  166. tests/3_examples/test_examples.py +34 -0
  167. foxes/VERSION +0 -1
  168. foxes/output/flow_plots_2d.py +0 -0
  169. foxes/utils/plotly_helpers.py +0 -19
  170. foxes/utils/runners/__init__.py +0 -1
  171. foxes/utils/runners/runners.py +0 -280
  172. foxes-0.8.1.dist-info/RECORD +0 -248
  173. foxes-0.8.1.dist-info/top_level.txt +0 -1
  174. foxes-0.8.1.dist-info/zip-safe +0 -1
  175. {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.data_source = algo.dbook.get_file_path(
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._inds = data.index.to_numpy()
238
+ self.__inds = data.index.to_numpy()
222
239
 
223
240
  col_w = self.var2col.get(FV.WEIGHT, FV.WEIGHT)
224
- self._weights = np.zeros((self._N, algo.n_turbines), dtype=FC.DTYPE)
241
+ self.__weights = np.zeros((self._N, algo.n_turbines), dtype=FC.DTYPE)
225
242
  if col_w in data:
226
- self._weights[:] = data[col_w].to_numpy()[:, None]
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._weights[:] = 1.0 / self._N
249
+ self.__weights[:] = 1.0 / self._N
233
250
  if isorg:
234
251
  data = data.copy()
235
- data[col_w] = self._weights[:, 0]
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
- return self._inds
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
- return self._weights
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._weights = None
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._tab_source = None
416
- self._tab_data = data_source
511
+ self.__tab_source = None
512
+ self.__tab_data = data_source
417
513
  elif isinstance(data_source, (str, Path)):
418
- self._tab_source = data_source
419
- self._tab_data = None
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._tab_data is None:
452
- if not Path(self._tab_source).is_file():
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._tab_source}' from context '{STATES}'"
551
+ f"States '{self.name}': Reading static data '{self.__tab_source}' from context '{STATES}'"
456
552
  )
457
- self._tab_source = algo.dbook.get_file_path(
458
- STATES, self._tab_source, check_raw=False
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._tab_source}")
557
+ print(f"Path: {self.__tab_source}")
462
558
  elif verbosity:
463
- print(f"States '{self.name}': Reading file {self._tab_source}")
464
- self._tab_data = read_tab_file(self._tab_source, self._normalize)
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._tab_data.attrs["factor_ws"]
467
- b = self._tab_data.attrs["shift_wd"]
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._tab_data["wd"].to_numpy()
569
+ wd0 = self.__tab_data["wd"].to_numpy()
474
570
  ws0 = a * np.append(
475
- np.array([0], dtype=FC.DTYPE), self._tab_data["ws"].to_numpy()
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._tab_data.sizes["ws"]
480
- n_wd = self._tab_data.sizes["wd"]
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._tab_data["wd_freq"].to_numpy() / 100
487
- weights = self._tab_data["ws_freq"].to_numpy() * wd_freq[None, :] / 1000
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.data_source = pd.DataFrame(
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.data_source.index.name = FC.STATE
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")
@@ -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 read_turbine_type, read_layout
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
@@ -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 and verbosity > 0:
17
- print(f"Ignoring '{FV.Z0}', since no reference_height found. No ABL profile activated.")
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(f"Ignoring '{FV.H}', since no '{FV.Z0}' data found. No ABL profile activated.")
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(f" Selecting ABL profile '{profiles[FV.WS]}', {FV.H} = {fields[FV.H]} m")
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
- def _get_SingleStateStates(coords, fields, dims, states_dict,
33
- ovars, fixval, profiles, verbosity):
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
- def _get_Timeseries(coords, fields, dims, states_dict,
70
- ovars, fixval, profiles, verbosity):
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
- def _get_MultiHeightNCTimeseries(coords, fields, dims, states_dict,
104
- ovars, fixval, profiles, verbosity):
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(f"Ignoring profile '{profiles[FV.WS]}' for states class 'MultiHeightNCTimeseries'")
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
- if dims[v] == (FV.H, FC.TIME):
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 _get_SingleStateStates(
174
- coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
175
- ) or _get_Timeseries(
176
- coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
177
- ) or _get_MultiHeightNCTimeseries(
178
- coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
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(wind_deficit, superposition, induction, algo_dict, verbosity):
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 wind_deficit_model")
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 != "None":
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 != "None":
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
- raise KeyError(
186
- f"Expecting background_averaging 'center' or 'grid', got '{background_averaging}'"
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
- wind_deficit = Dict(wio_ana["wind_deficit_model"], name="wind_deficit_model")
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, superposition, induction, algo_dict, ka, kb, amb_ti, verbosity
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