foxes 1.1.1__py3-none-any.whl → 1.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of foxes might be problematic. Click here for more details.

Files changed (155) hide show
  1. docs/source/conf.py +3 -1
  2. examples/abl_states/run.py +5 -5
  3. examples/dyn_wakes/run.py +2 -2
  4. examples/induction/run.py +5 -5
  5. examples/random_timeseries/run.py +13 -13
  6. examples/scan_row/run.py +12 -7
  7. examples/sector_management/run.py +11 -7
  8. examples/single_state/run.py +5 -5
  9. examples/tab_file/run.py +1 -1
  10. examples/timelines/run.py +1 -1
  11. examples/timeseries/run.py +5 -5
  12. examples/timeseries_slurm/run.py +5 -5
  13. examples/wind_rose/run.py +1 -1
  14. examples/yawed_wake/run.py +5 -5
  15. foxes/__init__.py +13 -2
  16. foxes/algorithms/downwind/downwind.py +21 -6
  17. foxes/algorithms/downwind/models/init_farm_data.py +5 -2
  18. foxes/algorithms/downwind/models/point_wakes_calc.py +0 -1
  19. foxes/algorithms/iterative/iterative.py +1 -1
  20. foxes/algorithms/sequential/sequential.py +5 -4
  21. foxes/config/__init__.py +1 -0
  22. foxes/config/config.py +134 -0
  23. foxes/constants.py +15 -6
  24. foxes/core/algorithm.py +46 -30
  25. foxes/core/axial_induction_model.py +18 -0
  26. foxes/core/data.py +2 -1
  27. foxes/core/engine.py +43 -49
  28. foxes/core/farm_controller.py +22 -3
  29. foxes/core/farm_data_model.py +6 -2
  30. foxes/core/ground_model.py +19 -0
  31. foxes/core/model.py +2 -1
  32. foxes/core/partial_wakes_model.py +9 -21
  33. foxes/core/point_data_model.py +22 -2
  34. foxes/core/rotor_model.py +9 -21
  35. foxes/core/states.py +2 -17
  36. foxes/core/turbine_model.py +2 -18
  37. foxes/core/turbine_type.py +2 -18
  38. foxes/core/vertical_profile.py +8 -20
  39. foxes/core/wake_frame.py +9 -25
  40. foxes/core/wake_model.py +24 -20
  41. foxes/core/wake_superposition.py +19 -0
  42. foxes/data/__init__.py +1 -1
  43. foxes/data/static_data.py +0 -7
  44. foxes/engines/dask.py +4 -3
  45. foxes/engines/single.py +1 -1
  46. foxes/input/__init__.py +1 -1
  47. foxes/input/farm_layout/from_csv.py +3 -1
  48. foxes/input/farm_layout/from_file.py +10 -10
  49. foxes/input/farm_layout/from_json.py +4 -3
  50. foxes/input/farm_layout/grid.py +3 -3
  51. foxes/input/states/__init__.py +1 -1
  52. foxes/input/states/create/random_abl_states.py +5 -3
  53. foxes/input/states/field_data_nc.py +36 -15
  54. foxes/input/states/multi_height.py +26 -15
  55. foxes/input/states/one_point_flow.py +6 -5
  56. foxes/input/states/{scan_ws.py → scan.py} +42 -52
  57. foxes/input/states/single.py +15 -6
  58. foxes/input/states/slice_data_nc.py +18 -12
  59. foxes/input/states/states_table.py +17 -10
  60. foxes/input/yaml/__init__.py +3 -0
  61. foxes/input/yaml/dict.py +381 -0
  62. foxes/input/yaml/windio/__init__.py +4 -0
  63. foxes/input/{windio → yaml/windio}/get_states.py +7 -7
  64. foxes/input/{windio → yaml/windio}/read_attributes.py +61 -40
  65. foxes/input/{windio → yaml/windio}/read_farm.py +34 -43
  66. foxes/input/{windio → yaml/windio}/read_fields.py +11 -10
  67. foxes/input/yaml/windio/read_outputs.py +147 -0
  68. foxes/input/yaml/windio/windio.py +269 -0
  69. foxes/input/yaml/yaml.py +103 -0
  70. foxes/models/partial_wakes/axiwake.py +7 -6
  71. foxes/models/partial_wakes/centre.py +3 -2
  72. foxes/models/partial_wakes/segregated.py +5 -2
  73. foxes/models/point_models/set_uniform_data.py +5 -3
  74. foxes/models/rotor_models/centre.py +2 -2
  75. foxes/models/rotor_models/grid.py +5 -5
  76. foxes/models/rotor_models/levels.py +6 -6
  77. foxes/models/turbine_models/kTI_model.py +3 -1
  78. foxes/models/turbine_models/lookup_table.py +7 -4
  79. foxes/models/turbine_models/power_mask.py +14 -8
  80. foxes/models/turbine_models/sector_management.py +4 -2
  81. foxes/models/turbine_models/set_farm_vars.py +53 -23
  82. foxes/models/turbine_models/table_factors.py +8 -7
  83. foxes/models/turbine_models/yaw2yawm.py +0 -1
  84. foxes/models/turbine_models/yawm2yaw.py +0 -1
  85. foxes/models/turbine_types/CpCt_file.py +6 -3
  86. foxes/models/turbine_types/CpCt_from_two.py +6 -3
  87. foxes/models/turbine_types/PCt_file.py +7 -6
  88. foxes/models/turbine_types/PCt_from_two.py +11 -2
  89. foxes/models/turbine_types/TBL_file.py +3 -4
  90. foxes/models/turbine_types/wsrho2PCt_from_two.py +19 -11
  91. foxes/models/turbine_types/wsti2PCt_from_two.py +19 -11
  92. foxes/models/vertical_profiles/abl_log_neutral_ws.py +1 -1
  93. foxes/models/vertical_profiles/abl_log_stable_ws.py +1 -1
  94. foxes/models/vertical_profiles/abl_log_unstable_ws.py +1 -1
  95. foxes/models/vertical_profiles/abl_log_ws.py +1 -1
  96. foxes/models/wake_frames/dynamic_wakes.py +17 -9
  97. foxes/models/wake_frames/farm_order.py +4 -3
  98. foxes/models/wake_frames/rotor_wd.py +3 -1
  99. foxes/models/wake_frames/seq_dynamic_wakes.py +14 -7
  100. foxes/models/wake_frames/streamlines.py +9 -6
  101. foxes/models/wake_frames/timelines.py +21 -14
  102. foxes/models/wake_frames/yawed_wakes.py +3 -1
  103. foxes/models/wake_models/induction/vortex_sheet.py +0 -1
  104. foxes/models/wake_models/ti/crespo_hernandez.py +2 -1
  105. foxes/models/wake_models/wind/bastankhah14.py +3 -2
  106. foxes/models/wake_models/wind/bastankhah16.py +2 -1
  107. foxes/models/wake_models/wind/turbopark.py +9 -7
  108. foxes/models/wake_superpositions/ws_product.py +0 -1
  109. foxes/output/__init__.py +2 -1
  110. foxes/output/calc_points.py +7 -4
  111. foxes/output/farm_layout.py +30 -18
  112. foxes/output/farm_results_eval.py +61 -38
  113. foxes/output/grids.py +8 -7
  114. foxes/output/output.py +9 -20
  115. foxes/output/plt.py +19 -0
  116. foxes/output/results_writer.py +10 -11
  117. foxes/output/rose_plot.py +448 -224
  118. foxes/output/rotor_point_plots.py +7 -3
  119. foxes/output/slice_data.py +1 -1
  120. foxes/output/state_turbine_map.py +5 -1
  121. foxes/output/state_turbine_table.py +7 -3
  122. foxes/output/turbine_type_curves.py +7 -2
  123. foxes/utils/__init__.py +1 -2
  124. foxes/utils/dict.py +107 -3
  125. foxes/utils/geopandas_utils.py +3 -2
  126. foxes/utils/subclasses.py +69 -0
  127. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/METADATA +18 -18
  128. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/RECORD +145 -145
  129. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/WHEEL +1 -1
  130. foxes-1.2.1.dist-info/entry_points.txt +3 -0
  131. tests/0_consistency/iterative/test_iterative.py +65 -67
  132. tests/0_consistency/partial_wakes/test_partial_wakes.py +58 -61
  133. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +56 -53
  134. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +41 -41
  135. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +34 -34
  136. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +57 -52
  137. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +58 -54
  138. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +80 -76
  139. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +80 -76
  140. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +58 -51
  141. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +101 -103
  142. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +67 -64
  143. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +58 -54
  144. examples/windio/run.py +0 -29
  145. foxes/data/states/windio_timeseries_5000.nc +0 -0
  146. foxes/data/windio/DTU_10MW_turbine.yaml +0 -10
  147. foxes/data/windio/__init__.py +0 -0
  148. foxes/data/windio/windio_5turbines_timeseries.yaml +0 -79
  149. foxes/input/windio/__init__.py +0 -11
  150. foxes/input/windio/read_outputs.py +0 -172
  151. foxes/input/windio/runner.py +0 -183
  152. foxes/input/windio/windio.py +0 -193
  153. foxes/utils/windrose_plot.py +0 -152
  154. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/LICENSE +0 -0
  155. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,381 @@
1
+ import matplotlib.pyplot as plt
2
+ import pandas as pd
3
+ from inspect import signature
4
+
5
+ import foxes.input.farm_layout as farm_layout
6
+ from foxes.core import States, Engine, WindFarm, Algorithm
7
+ from foxes.models import ModelBook
8
+ from foxes.output import Output
9
+ from foxes.utils import Dict, new_cls
10
+ from foxes.config import config
11
+ import foxes.constants as FC
12
+
13
+
14
+ def read_dict(
15
+ idict,
16
+ farm=None,
17
+ states=None,
18
+ mbook=None,
19
+ algo=None,
20
+ engine_pars=None,
21
+ iterative=None,
22
+ verbosity=None,
23
+ work_dir=".",
24
+ out_dir=".",
25
+ **algo_pars,
26
+ ):
27
+ """
28
+ Read dictionary input into foxes objects
29
+
30
+ Parameters
31
+ ----------
32
+ idict: foxes.utils.Dict
33
+ The input parameter dictionary
34
+ farm: foxes.core.WindFarm, optional
35
+ The wind farm, overrules settings from idict
36
+ states: foxes.core.States, optional
37
+ The ambient states, overrules settings from idict
38
+ mbook: foxes.models.ModelBook, optional
39
+ The model book, overrules settings from idict
40
+ algo: foxes.core.Algorithm, optional
41
+ The algorithm, overrules settings from idict
42
+ engine_pars: dict, optional
43
+ Parameters for engine creation, overrules
44
+ settings from idict
45
+ iterative: bool, optional
46
+ Force iterative calculations, overrules
47
+ settings from idict
48
+ verbosity: int, optional
49
+ Force a verbosity level, 0 = silent, overrules
50
+ settings from idict
51
+ work_dir: str or pathlib.Path
52
+ Path to the working directory
53
+ out_dir: str or pathlib.Path
54
+ The default output directory
55
+ algo_pars: dict, optional
56
+ Additional parameters for the algorithm, overrules
57
+ settings from idict
58
+
59
+ Returns
60
+ -------
61
+ algo: foxes.core.Algorithm
62
+ The algorithm
63
+ engine: foxes.core.Engine
64
+ The engine, or None if not set
65
+
66
+ :group: input.yaml
67
+
68
+ """
69
+
70
+ def _print(*args, level=1, **kwargs):
71
+ if verbosity is None or verbosity >= level:
72
+ print(*args, **kwargs)
73
+
74
+ # set working directory:
75
+ config[FC.WORK_DIR] = work_dir
76
+ config[FC.OUT_DIR] = out_dir
77
+ _print("Working directory:", config.work_dir)
78
+ _print("Output directory :", config.out_dir)
79
+
80
+ # create states:
81
+ if states is None:
82
+ _print("Creating states")
83
+ states = States.new(**idict["states"])
84
+
85
+ # create model book:
86
+ if mbook is None:
87
+ mbook = ModelBook()
88
+ if "model_book" in idict:
89
+ _print("Creating model book")
90
+ mdict = idict.get_item("model_book")
91
+ for s, mlst in mdict.items():
92
+ t = mbook.sources.get_item(s)
93
+ c = mbook.base_classes.get_item(s)
94
+ ms = [Dict(m, name=f"{mdict.name}.s{i}") for i, m in enumerate(mlst)]
95
+ for m in ms:
96
+ mname = m.pop_item("name")
97
+ _print(f" Adding {s}.{mname}")
98
+ t[mname] = c.new(**m)
99
+
100
+ # create farm:
101
+ if farm is None:
102
+ _print("Creating wind farm")
103
+ fdict = idict.get_item("wind_farm")
104
+ lyts = [
105
+ Dict(l, name=f"{fdict.name}.layout{i}")
106
+ for i, l in enumerate(fdict.pop_item("layouts"))
107
+ ]
108
+ farm = WindFarm(**fdict)
109
+ for lyt in lyts:
110
+ add_fun = getattr(farm_layout, lyt.pop_item("function"))
111
+ if verbosity is not None:
112
+ lyt["verbosity"] = verbosity - 1
113
+ add_fun(farm, **lyt)
114
+
115
+ # create engine:
116
+ engine = None
117
+ if engine_pars is not None:
118
+ engine = Engine.new(**engine_pars)
119
+ _print(f"Initializing engine: {engine}")
120
+ engine.initialize()
121
+ elif "engine" in idict:
122
+ if verbosity is not None:
123
+ idict["verbosity"] = verbosity - 1
124
+ engine = Engine.new(**idict["engine"])
125
+ engine.initialize()
126
+ _print(f"Initializing engine: {engine}")
127
+
128
+ # create algorithm:
129
+ if algo is None:
130
+ _print("Creating algorithm")
131
+ adict = idict.get_item("algorithm")
132
+ if iterative is not None and iterative:
133
+ adict["algo_type"] = "Iterative"
134
+ adict.update(dict(farm=farm, states=states, mbook=mbook))
135
+ if verbosity is not None:
136
+ adict["verbosity"] = verbosity - 1
137
+ if algo_pars is not None:
138
+ adict.update({v: d for v, d in algo_pars.items() if d is not None})
139
+ algo = Algorithm.new(**adict)
140
+
141
+ return algo, engine
142
+
143
+
144
+ def run_outputs(
145
+ idict,
146
+ algo=None,
147
+ farm_results=None,
148
+ point_results=None,
149
+ verbosity=None,
150
+ ):
151
+ """
152
+ Run outputs from dict.
153
+
154
+ Parameters
155
+ ----------
156
+ idict: foxes.utils.Dict
157
+ The input parameter dictionary
158
+ algo: foxes.core.Algorithm, optional
159
+ The algorithm
160
+ farm_results: xarray.Dataset, optional
161
+ The farm results
162
+ point_results: xarray.Dataset, optional
163
+ The point results
164
+ verbosity: int, optional
165
+ Force a verbosity level, 0 = silent, overrules
166
+ settings from idict
167
+
168
+ Returns
169
+ -------
170
+ outputs: list of tuple
171
+ For each output enty, a tuple (dict, results),
172
+ where results is a tuple that represents one
173
+ entry per function call
174
+
175
+ :group: input.yaml
176
+
177
+ """
178
+
179
+ def _print(*args, level=1, **kwargs):
180
+ if verbosity is None or verbosity >= level:
181
+ print(*args, **kwargs)
182
+
183
+ out = []
184
+ if "outputs" in idict:
185
+ _print("Running outputs")
186
+ odicts = [
187
+ Dict(odict, name=f"{idict.name}.output{i}")
188
+ for i, odict in enumerate(idict["outputs"])
189
+ ]
190
+
191
+ rlabels = Dict(name="result_labels")
192
+
193
+ def _get_object(rlabels, d):
194
+ d = d.replace("]", "")
195
+ i0 = d.find("[")
196
+ if i0 > 0:
197
+ inds = tuple([int(x) for x in d[i0 + 1 :].split(",")])
198
+ return rlabels[d[:i0]][inds]
199
+ else:
200
+ return rlabels[d]
201
+
202
+ for i, d in enumerate(odicts):
203
+
204
+ if "output_type" in d:
205
+ ocls = d.pop_item("output_type")
206
+ _print(f" Output {i}: {ocls}")
207
+ d0 = dict(output_type=ocls)
208
+ d0.update(d)
209
+ flist = [
210
+ Dict(f, name=f"{d.name}.function{i}")
211
+ for i, f in enumerate(d.pop_item("functions"))
212
+ ]
213
+ cls = new_cls(Output, ocls)
214
+ prs = list(signature(cls.__init__).parameters.keys())
215
+ if "algo" in prs:
216
+ assert (
217
+ algo is not None
218
+ ), f"Output {i} of type '{ocls}' requires algo"
219
+ d["algo"] = algo
220
+ if "farm" in prs:
221
+ d["farm"] = algo.farm
222
+ if "farm_results" in prs:
223
+ if farm_results is None:
224
+ print(f"No farm results; skipping output {ocls}")
225
+ for fdict in flist:
226
+ out += (d0, None)
227
+ continue
228
+ d["farm_results"] = farm_results
229
+ if "point_results" in prs:
230
+ d["point_results"] = point_results
231
+ o = cls(**d)
232
+
233
+ elif "object" in d:
234
+ ocls = d.pop("object")
235
+ o = _get_object(rlabels, ocls)
236
+ d0 = dict(object=ocls)
237
+ d0.update(d)
238
+ flist = [
239
+ Dict(f, name=f"{d.name}.function{i}")
240
+ for i, f in enumerate(d.pop_item("functions"))
241
+ ]
242
+
243
+ else:
244
+ raise KeyError(
245
+ f"Output {i} of type '{ocls}': Please specify either 'output_type' or 'object'"
246
+ )
247
+
248
+ fres = []
249
+ for fdict in flist:
250
+ fname = fdict.pop_item("function")
251
+ _print(f" - {fname}")
252
+ plt_show = fdict.pop("plt_show", False)
253
+ plt_close = fdict.pop("plt_close", False)
254
+ rlbs = fdict.pop("result_labels", None)
255
+
256
+ # grab function:
257
+ assert hasattr(
258
+ o, fname
259
+ ), f"Output {i} of type '{ocls}': Function '{fname}' not found"
260
+ f = getattr(o, fname)
261
+
262
+ # add required input data objects:
263
+ prs = list(signature(f).parameters.keys())
264
+ if "algo" in prs:
265
+ fdict["algo"] = algo
266
+ if "farm" in prs:
267
+ fdict["farm"] = algo.farm
268
+
269
+ # replace result labels by objects:
270
+ for k, d in fdict.items():
271
+ if isinstance(d, str) and d[0] == "$":
272
+ fdict[k] = _get_object(rlabels, d)
273
+
274
+ # run function:
275
+ args = fdict.pop("args", tuple())
276
+ results = f(*args, **fdict)
277
+
278
+ # pyplot shortcuts:
279
+ if plt_show:
280
+ plt.show()
281
+ if plt_close:
282
+ results = None
283
+ plt.close()
284
+
285
+ # store results under result labels:
286
+ if rlbs is not None:
287
+
288
+ def _set_label(rlabels, k, r):
289
+ if k not in ["", "none", "None", "_", "__"]:
290
+ assert (
291
+ k[0] == "$"
292
+ ), f"Output {i} of type '{ocls}', function '{fname}': result labels must start with '$', got '{k}'"
293
+ assert (
294
+ "[" not in k and "]" not in k and "," not in k
295
+ ), f"Output {i} of type '{ocls}', function '{fname}': result labels cannot contain '[' or ']' or comma, got '{k}'"
296
+ _print(f" result label {k}: {type(r).__name__}")
297
+ rlabels[k] = r
298
+
299
+ if isinstance(rlbs, (list, tuple)):
300
+ for i, k in enumerate(rlbs):
301
+ _set_label(rlabels, k, results[i])
302
+ else:
303
+ _set_label(rlabels, rlbs, results)
304
+
305
+ fres.append(results)
306
+ out.append((d0, fres))
307
+
308
+ return out
309
+
310
+
311
+ def run_dict(idict, *args, verbosity=None, **kwargs):
312
+ """
313
+ Runs foxes from dictionary input
314
+
315
+ Parameters
316
+ ----------
317
+ idict: foxes.utils.Dict
318
+ The input parameter dictionary
319
+ args: tuple, optional
320
+ Additional parameters for read_dict
321
+ verbosity: int, optional
322
+ Force a verbosity level, 0 = silent, overrules
323
+ settings from idict
324
+ kwargs: dict, optional
325
+ Additional parameters for read_dict
326
+
327
+ Returns
328
+ -------
329
+ farm_results: xarray.Dataset, optional
330
+ The farm results
331
+ point_results: xarray.Dataset, optional
332
+ The point results
333
+ outputs: list of tuple
334
+ For each output enty, a tuple (dict, results),
335
+ where results is a tuple that represents one
336
+ entry per function call
337
+
338
+ :group: input.yaml
339
+
340
+ """
341
+
342
+ def _print(*args, level=1, **kwargs):
343
+ if verbosity is None or verbosity >= level:
344
+ print(*args, **kwargs)
345
+
346
+ # read components:
347
+ algo, engine = read_dict(idict, *args, verbosity=verbosity, **kwargs)
348
+
349
+ # run farm calculation:
350
+ rdict = idict.get_item("calc_farm", Dict(name=idict.name + ".calc_farm"))
351
+ if rdict.pop_item("run", True):
352
+ _print("Running calc_farm")
353
+ farm_results = algo.calc_farm(**rdict)
354
+ else:
355
+ farm_results = None
356
+ out = (farm_results,)
357
+
358
+ # run points calculation:
359
+ point_results = None
360
+ if "calc_points" in idict:
361
+ rdict = idict.get_item("calc_points")
362
+ if rdict.pop_item("run"):
363
+ _print("Running calc_points")
364
+ points = rdict.pop_item("points")
365
+ if isinstance(points, str):
366
+ _print("Reading file", points)
367
+ points = pd.read_csv(points).to_numpy()
368
+ point_results = algo.calc_points(farm_results, points=points, **rdict)
369
+ else:
370
+ point_results = None
371
+ out += (point_results,)
372
+
373
+ # run outputs:
374
+ out += (run_outputs(idict, algo, farm_results, point_results, verbosity),)
375
+
376
+ # shutdown engine, if created above:
377
+ if engine is not None:
378
+ _print(f"Finalizing engine: {engine}")
379
+ engine.finalize()
380
+
381
+ return out
@@ -0,0 +1,4 @@
1
+ from .windio import foxes_windio, read_windio
2
+ from .read_fields import read_wind_resource_field
3
+ from .read_farm import read_layout, read_turbine_types
4
+ from .read_attributes import read_attributes
@@ -4,13 +4,13 @@ from xarray import Dataset
4
4
  from numbers import Number
5
5
 
6
6
  from foxes.core import States
7
- import foxes.constants as FC
8
7
  import foxes.variables as FV
8
+ import foxes.constants as FC
9
9
 
10
10
 
11
11
  def _get_profiles(coords, fields, dims, ovars, fixval, verbosity):
12
12
  """Read ABL profiles information
13
- :group: input.windio
13
+ :group: input.yaml.windio
14
14
  """
15
15
  profiles = {}
16
16
  if FV.Z0 in fields:
@@ -42,7 +42,7 @@ def _get_SingleStateStates(
42
42
  coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
43
43
  ):
44
44
  """Try to generate single state parameters
45
- :group: input.windio
45
+ :group: input.yaml.windio
46
46
  """
47
47
  for c in coords:
48
48
  if not isinstance(c, Number):
@@ -81,7 +81,7 @@ def _get_Timeseries(
81
81
  coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
82
82
  ):
83
83
  """Try to generate time series parameters
84
- :group: input.windio
84
+ :group: input.yaml.windio
85
85
  """
86
86
  if len(coords) == 1 and FC.TIME in coords:
87
87
  if verbosity > 2:
@@ -117,7 +117,7 @@ def _get_MultiHeightNCTimeseries(
117
117
  coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
118
118
  ):
119
119
  """Try to generate time series parameters
120
- :group: input.windio
120
+ :group: input.yaml.windio
121
121
  """
122
122
  if len(coords) == 2 and FC.TIME in coords and FV.H in coords:
123
123
  if verbosity > 2:
@@ -176,11 +176,11 @@ def get_states(coords, fields, dims, verbosity=1):
176
176
  states: foxes.core.States
177
177
  The states object
178
178
 
179
- :group: input.windio
179
+ :group: input.yaml.windio
180
180
 
181
181
  """
182
182
  if verbosity > 2:
183
- print(" Preparing states")
183
+ print(" Creating states")
184
184
 
185
185
  ovars = [FV.WS, FV.WD, FV.TI, FV.RHO]
186
186
  fixval = {FV.TI: 0.05, FV.RHO: 1.225}
@@ -6,7 +6,13 @@ from .read_outputs import read_outputs
6
6
 
7
7
 
8
8
  def _read_wind_deficit(
9
- wake_model_key, wind_deficit, superposition, induction, algo_dict, verbosity
9
+ wake_model_key,
10
+ wind_deficit,
11
+ superposition,
12
+ induction,
13
+ algo_dict,
14
+ mbook,
15
+ verbosity,
10
16
  ):
11
17
  """Reads the wind deficit wake model"""
12
18
 
@@ -69,17 +75,25 @@ def _read_wind_deficit(
69
75
  supd = ws_sup_dict if eff_ws else ws_sup_amb_dict
70
76
  wind_def_dict["superposition"] = supd[superposition["ws_superposition"]]
71
77
 
72
- algo_dict["mbook"].wake_models[wname] = WakeModel.new(**wind_def_dict)
78
+ mbook.wake_models[wname] = WakeModel.new(**wind_def_dict)
73
79
  if verbosity > 2:
74
80
  print(f" Created wake model '{wname}':")
75
- print(" ", algo_dict["mbook"].wake_models[wname])
81
+ print(" ", mbook.wake_models[wname])
76
82
  algo_dict["wake_models"].append(wname)
77
83
 
78
84
  return ka, kb, amb_ti
79
85
 
80
86
 
81
87
  def _read_turbulence(
82
- turbulence_model, superposition, induction, algo_dict, ka, kb, amb_ti, verbosity
88
+ turbulence_model,
89
+ superposition,
90
+ induction,
91
+ algo_dict,
92
+ mbook,
93
+ ka,
94
+ kb,
95
+ amb_ti,
96
+ verbosity,
83
97
  ):
84
98
  """Reads the ti wake model"""
85
99
 
@@ -128,14 +142,14 @@ def _read_turbulence(
128
142
  tiwake_dict["ti_var"] = ti_var
129
143
  tiwake_dict["superposition"] = ti_sup_dict[superposition["ti_superposition"]]
130
144
 
131
- algo_dict["mbook"].wake_models[wname] = WakeModel.new(**tiwake_dict)
145
+ mbook.wake_models[wname] = WakeModel.new(**tiwake_dict)
132
146
  if verbosity > 2:
133
147
  print(f" Created wake model '{wname}':")
134
- print(" ", algo_dict["mbook"].wake_models[wname])
148
+ print(" ", mbook.wake_models[wname])
135
149
  algo_dict["wake_models"].append(wname)
136
150
 
137
151
 
138
- def _read_blockage(blockage_model, induction, algo_dict, verbosity):
152
+ def _read_blockage(blockage_model, induction, algo_dict, mbook, verbosity):
139
153
  """Reads the blockage model"""
140
154
  indc_def_map = Dict(
141
155
  {
@@ -154,10 +168,10 @@ def _read_blockage(blockage_model, induction, algo_dict, verbosity):
154
168
  print(" Contents:", [k for k in blockage_model.keys()])
155
169
  if wname not in ["None", "none"]:
156
170
  indc_dict = Dict(wmodel_type=indc_def_map[wname], induction=induction)
157
- algo_dict["mbook"].wake_models[wname] = WakeModel.new(**indc_dict)
171
+ mbook.wake_models[wname] = WakeModel.new(**indc_dict)
158
172
  if verbosity > 2:
159
173
  print(f" Created wake model '{wname}':")
160
- print(" ", algo_dict["mbook"].wake_models[wname])
174
+ print(" ", mbook.wake_models[wname])
161
175
  algo_dict["wake_models"].append(wname)
162
176
  algo_dict["algo_type"] = "Iterative"
163
177
 
@@ -214,7 +228,7 @@ def _read_rotor_averaging(rotor_averaging, algo_dict, verbosity):
214
228
  print(" --> partial_wakes :", algo_dict["partial_wakes"])
215
229
 
216
230
 
217
- def _read_deflection(deflection, induction, algo_dict, verbosity):
231
+ def _read_deflection(deflection, induction, algo_dict, mbook, verbosity):
218
232
  """Reads deflection model"""
219
233
  defl_def_map = Dict(
220
234
  {
@@ -231,25 +245,25 @@ def _read_deflection(deflection, induction, algo_dict, verbosity):
231
245
  print(" Contents:", [k for k in deflection.keys()])
232
246
  indc_dict = Dict(wframe_type=defl_def_map[wname])
233
247
  try:
234
- algo_dict["mbook"].wake_frames[wname] = WakeFrame.new(
235
- **indc_dict, induction=induction
236
- )
248
+ mbook.wake_frames[wname] = WakeFrame.new(**indc_dict, induction=induction)
237
249
  except TypeError:
238
- algo_dict["mbook"].wake_frames[wname] = WakeFrame.new(**indc_dict)
250
+ mbook.wake_frames[wname] = WakeFrame.new(**indc_dict)
239
251
  if verbosity > 2:
240
252
  print(f" Created wake frame '{wname}':")
241
- print(" ", algo_dict["mbook"].wake_frames[wname])
253
+ print(" ", mbook.wake_frames[wname])
242
254
  algo_dict["wake_frame"] = wname
243
255
 
244
256
 
245
- def _read_analysis(wio_ana, algo_dict, verbosity):
257
+ def _read_analysis(wio_ana, idict, mbook, verbosity):
246
258
  """Reads the windio analyses"""
247
259
  if verbosity > 2:
248
260
  print(" Reading analysis")
249
261
  print(" Contents:", [k for k in wio_ana.keys()])
250
262
 
251
263
  # superposition:
252
- superposition = Dict(wio_ana["superposition_model"], name="superposition_model")
264
+ superposition = Dict(
265
+ wio_ana["superposition_model"], name=wio_ana.name + ".superposition_model"
266
+ )
253
267
  if verbosity > 2:
254
268
  print(" Reading superposition_model")
255
269
  print(" Contents:", [k for k in superposition.keys()])
@@ -270,9 +284,18 @@ def _read_analysis(wio_ana, algo_dict, verbosity):
270
284
  wake_model_key = (
271
285
  "wind_deficit_model" if "wind_deficit_model" in wio_ana else "wake_model"
272
286
  )
273
- wind_deficit = Dict(wio_ana[wake_model_key], name=wake_model_key)
287
+ algo_dict = idict["algorithm"]
288
+ wind_deficit = Dict(
289
+ wio_ana[wake_model_key], name=wio_ana.name + "." + wake_model_key
290
+ )
274
291
  ka, kb, amb_ti = _read_wind_deficit(
275
- wake_model_key, wind_deficit, superposition, induction, algo_dict, verbosity
292
+ wake_model_key,
293
+ wind_deficit,
294
+ superposition,
295
+ induction,
296
+ algo_dict,
297
+ mbook,
298
+ verbosity,
276
299
  )
277
300
 
278
301
  # turbulence model:
@@ -283,6 +306,7 @@ def _read_analysis(wio_ana, algo_dict, verbosity):
283
306
  superposition,
284
307
  induction,
285
308
  algo_dict,
309
+ mbook,
286
310
  ka,
287
311
  kb,
288
312
  amb_ti,
@@ -294,7 +318,7 @@ def _read_analysis(wio_ana, algo_dict, verbosity):
294
318
  # blockage model:
295
319
  if "blockage_model" in wio_ana:
296
320
  blockage_model = Dict(wio_ana["blockage_model"], name="blockage_model")
297
- _read_blockage(blockage_model, induction, algo_dict, verbosity)
321
+ _read_blockage(blockage_model, induction, algo_dict, mbook, verbosity)
298
322
  elif verbosity > 0:
299
323
  print("blockage_model not found, not using a turbine induction model")
300
324
 
@@ -308,37 +332,35 @@ def _read_analysis(wio_ana, algo_dict, verbosity):
308
332
  # deflection:
309
333
  if "deflection_model" in wio_ana:
310
334
  deflection = Dict(wio_ana["deflection_model"], name="deflection_model")
311
- _read_deflection(deflection, induction, algo_dict, verbosity)
335
+ _read_deflection(deflection, induction, algo_dict, mbook, verbosity)
312
336
  elif verbosity > 0:
313
337
  print("deflection_model not found, using default settings")
314
338
 
315
339
 
316
- def read_attributes(wio, algo_dict, verbosity=1, **output_pars):
340
+ def read_attributes(wio, idict, mbook, verbosity=1):
317
341
  """
318
342
  Reads the attributes part of windio
319
343
 
320
344
  Parameters
321
345
  ----------
322
- wio: dict
346
+ wio: foxes.utils.Dict
323
347
  The windio data
324
- algo_dict: dict
325
- The algorithm dictionary
348
+ idict: foxes.utils.Dict
349
+ The foxes input data dictionary
350
+ mbook: foxes.models.ModelBook
351
+ The model book
326
352
  verbosity: int
327
353
  The verbosity level, 0=silent
328
- **output_pars: dict, optional
329
- Additional parameters for output reading
330
354
 
331
355
  Returns
332
356
  -------
333
- out_dicts: list of dict
334
- The output dictionaries
335
357
  odir: pathlib.Path
336
- Path to the output folder
358
+ The output directory
337
359
 
338
- :group: input.windio
360
+ :group: input.yaml.windio
339
361
 
340
362
  """
341
- wio_attrs = Dict(wio["attributes"], name="attributes")
363
+ wio_attrs = Dict(wio["attributes"], name=wio.name + ".attributes")
342
364
  if verbosity > 1:
343
365
  print("Reading attributes")
344
366
  print(" Contents:", [k for k in wio_attrs.keys()])
@@ -355,15 +377,14 @@ def read_attributes(wio, algo_dict, verbosity=1, **output_pars):
355
377
  print(f"Running flow model 'foxes', overruling original choice '{fmname}'")
356
378
 
357
379
  # read analysis:
358
- wio_ana = Dict(wio_attrs["analysis"], name="analyses")
359
- _read_analysis(wio_ana, algo_dict, verbosity)
380
+ wio_ana = Dict(wio_attrs["analysis"], name=wio_attrs.name + ".analysis")
381
+ _read_analysis(wio_ana, idict, mbook, verbosity)
360
382
 
361
383
  # outputs:
362
- out_dicts = []
384
+ odict = idict["outputs"]
385
+ odir = "."
363
386
  if "outputs" in wio_attrs:
364
- outputs = Dict(wio_attrs["outputs"], name="outputs")
365
- out_dicts, odir = read_outputs(
366
- outputs, algo_dict, verbosity=verbosity, **output_pars
367
- )
387
+ outputs = Dict(wio_attrs["outputs"], name=wio_attrs.name + ".outputs")
388
+ odir = read_outputs(outputs, odict, verbosity=verbosity)
368
389
 
369
- return out_dicts, odir
390
+ return odir