foxes 0.7.1__py3-none-any.whl → 0.7.3__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 (66) hide show
  1. foxes/VERSION +1 -1
  2. foxes/algorithms/downwind/downwind.py +60 -46
  3. foxes/algorithms/downwind/models/farm_wakes_calc.py +17 -6
  4. foxes/algorithms/downwind/models/point_wakes_calc.py +13 -45
  5. foxes/algorithms/iterative/iterative.py +1 -1
  6. foxes/algorithms/iterative/models/farm_wakes_calc.py +18 -4
  7. foxes/constants.py +5 -0
  8. foxes/core/__init__.py +2 -1
  9. foxes/core/ground_model.py +254 -0
  10. foxes/core/model.py +3 -2
  11. foxes/core/partial_wakes_model.py +19 -3
  12. foxes/core/states.py +33 -0
  13. foxes/core/wake_model.py +138 -2
  14. foxes/data/__init__.py +1 -1
  15. foxes/data/states/WRF-Timeseries-3000.nc +0 -0
  16. foxes/data/states/windio_timeseries_5000.nc +0 -0
  17. foxes/data/static_data.py +7 -0
  18. foxes/data/windio/DTU_10MW_turbine.yaml +10 -0
  19. foxes/data/windio/__init__.py +0 -0
  20. foxes/data/windio/windio_5turbines_timeseries.yaml +63 -0
  21. foxes/input/states/__init__.py +1 -0
  22. foxes/input/states/multi_height.py +225 -6
  23. foxes/input/windio/__init__.py +6 -1
  24. foxes/input/windio/get_states.py +115 -0
  25. foxes/input/windio/read_attributes.py +321 -0
  26. foxes/input/windio/read_farm.py +163 -0
  27. foxes/input/windio/read_fields.py +164 -0
  28. foxes/input/windio/runner.py +105 -0
  29. foxes/input/windio/windio.py +136 -254
  30. foxes/models/__init__.py +2 -1
  31. foxes/models/ground_models/__init__.py +2 -0
  32. foxes/models/ground_models/no_ground.py +12 -0
  33. foxes/models/ground_models/wake_mirror.py +161 -0
  34. foxes/models/model_book.py +114 -164
  35. foxes/models/partial_wakes/axiwake.py +27 -4
  36. foxes/models/partial_wakes/top_hat.py +26 -4
  37. foxes/models/turbine_types/PCt_file.py +1 -0
  38. foxes/models/turbine_types/PCt_from_two.py +92 -0
  39. foxes/models/wake_frames/yawed_wakes.py +41 -38
  40. foxes/models/wake_models/__init__.py +0 -1
  41. foxes/models/wake_models/induction/__init__.py +1 -0
  42. foxes/models/wake_models/induction/rankine_half_body.py +1 -1
  43. foxes/models/wake_models/induction/vortex_sheet.py +227 -0
  44. foxes/models/wake_models/ti/crespo_hernandez.py +26 -24
  45. foxes/models/wake_models/ti/iec_ti.py +33 -26
  46. foxes/models/wake_models/wind/bastankhah14.py +11 -32
  47. foxes/models/wake_models/wind/bastankhah16.py +30 -34
  48. foxes/models/wake_models/wind/jensen.py +13 -29
  49. foxes/models/wake_models/wind/turbopark.py +31 -61
  50. foxes/models/wake_superpositions/ws_max.py +1 -0
  51. foxes/models/wake_superpositions/ws_pow.py +1 -0
  52. foxes/models/wake_superpositions/ws_quadratic.py +1 -0
  53. foxes/output/grids.py +6 -6
  54. foxes/output/output.py +6 -6
  55. foxes/utils/__init__.py +1 -1
  56. foxes/utils/factory.py +284 -76
  57. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/METADATA +8 -6
  58. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/RECORD +65 -51
  59. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/WHEEL +1 -1
  60. foxes/models/wake_models/wake_mirror.py +0 -196
  61. /foxes/models/{axial_induction_models → axial_induction}/__init__.py +0 -0
  62. /foxes/models/{axial_induction_models → axial_induction}/betz.py +0 -0
  63. /foxes/models/{axial_induction_models → axial_induction}/madsen.py +0 -0
  64. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/LICENSE +0 -0
  65. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/top_level.txt +0 -0
  66. {foxes-0.7.1.dist-info → foxes-0.7.3.dist-info}/zip-safe +0 -0
@@ -1,7 +1,7 @@
1
1
  from math import sqrt
2
2
  import foxes.models as fm
3
3
  import foxes.variables as FV
4
- from foxes.utils import Dict, FDict
4
+ from foxes.utils import FDict
5
5
 
6
6
  from foxes.core import (
7
7
  PointDataModel,
@@ -16,6 +16,7 @@ from foxes.core import (
16
16
  WakeModel,
17
17
  AxialInductionModel,
18
18
  TurbineInductionModel,
19
+ GroundModel,
19
20
  )
20
21
 
21
22
 
@@ -25,42 +26,45 @@ class ModelBook:
25
26
 
26
27
  Attributes
27
28
  ----------
28
- point_models: foxes.utils.Dict
29
+ point_models: foxes.utils.FDict
29
30
  The point models. Keys: model name str,
30
31
  values: foxes.core.PointDataModel
31
- rotor_models: foxes.utils.Dict
32
+ rotor_models: foxes.utils.FDict
32
33
  The rotor models. Keys: model name str,
33
34
  values: foxes.core.RotorModel
34
- turbine_types: foxes.utils.Dict
35
+ turbine_types: foxes.utils.FDict
35
36
  The turbine type models. Keys: model name str,
36
37
  values: foxes.core.TurbineType
37
- turbine_models: foxes.utils.Dict
38
+ turbine_models: foxes.utils.FDict
38
39
  The turbine models. Keys: model name str,
39
40
  values: foxes.core.TurbineModel
40
- farm_models: foxes.utils.Dict
41
+ farm_models: foxes.utils.FDict
41
42
  The farm models. Keys: model name str,
42
43
  values: foxes.core.FarmModel
43
- farm_controllers: foxes.utils.Dict
44
+ farm_controllers: foxes.utils.FDict
44
45
  The farm controllers. Keys: model name str,
45
46
  values: foxes.core.FarmController
46
- partial_wakes: foxes.utils.Dict
47
+ partial_wakes: foxes.utils.FDict
47
48
  The partial wakes. Keys: model name str,
48
49
  values: foxes.core.PartialWakeModel
49
- wake_frames: foxes.utils.Dict
50
+ wake_frames: foxes.utils.FDict
50
51
  The wake frames. Keys: model name str,
51
52
  values: foxes.core.WakeFrame
52
- wake_superpositions: foxes.utils.Dict
53
+ wake_superpositions: foxes.utils.FDict
53
54
  The wake superposition models. Keys: model name str,
54
55
  values: foxes.core.WakeSuperposition
55
- wake_models: foxes.utils.Dict
56
+ wake_models: foxes.utils.FDict
56
57
  The wake models. Keys: model name str,
57
58
  values: foxes.core.WakeModel
58
- induction_models: foxes.utils.Dict
59
+ induction_models: foxes.utils.FDict
59
60
  The induction models. Keys: model name str,
60
61
  values: foxes.core.AxialInductionModel
61
- sources: foxes.utils.Dict
62
+ ground_models: foxes.utils.FDict
63
+ The ground models. Keys: model name str,
64
+ values: foxes.core.GroundModel
65
+ sources: foxes.utils.FDict
62
66
  All sources dict
63
- base_classes: foxes.utils.Dict
67
+ base_classes: foxes.utils.FDict
64
68
  The base classes for all model types
65
69
 
66
70
  :group: models
@@ -77,7 +81,7 @@ class ModelBook:
77
81
  Path to power/ct curve file, for creation
78
82
  of default turbine type model
79
83
  """
80
- self.point_models = Dict(name="point_models")
84
+ self.point_models = FDict(name="point_models")
81
85
  self.point_models["tke2ti"] = fm.point_models.TKE2TI()
82
86
 
83
87
  self.rotor_models = FDict(name="rotor_models")
@@ -88,8 +92,11 @@ class ModelBook:
88
92
  n2 = float(n2)
89
93
  n = int(sqrt(n2))
90
94
  if n**2 != n2:
91
- raise Exception(f"GridRotor factory: Value {n2} is not the square of an integer")
95
+ raise Exception(
96
+ f"GridRotor factory: Value {n2} is not the square of an integer"
97
+ )
92
98
  return n
99
+
93
100
  self.rotor_models.add_factory(
94
101
  fm.rotor_models.GridRotor,
95
102
  "grid<n2>",
@@ -100,7 +107,7 @@ class ModelBook:
100
107
  )
101
108
  self.rotor_models.add_factory(
102
109
  fm.rotor_models.GridRotor,
103
- "raw_grid<n2>",
110
+ "grid<n2>_raw",
104
111
  kwargs=dict(calc_vars=rvars, reduce=False),
105
112
  var2arg={"n2": "n"},
106
113
  n2=_n2n,
@@ -115,13 +122,13 @@ class ModelBook:
115
122
  )
116
123
  self.rotor_models.add_factory(
117
124
  fm.rotor_models.LevelRotor,
118
- "raw_level<n>",
125
+ "level<n>_raw",
119
126
  kwargs=dict(calc_vars=rvars, reduce=False),
120
127
  n=lambda x: int(x),
121
128
  hints={"n": "(Number of vertical levels)"},
122
129
  )
123
130
 
124
- self.turbine_types = Dict(name="turbine_types")
131
+ self.turbine_types = FDict(name="turbine_types")
125
132
  self.turbine_types["null_type"] = fm.turbine_types.NullType()
126
133
  self.turbine_types["NREL5MW"] = fm.turbine_types.PCtFile(
127
134
  "NREL-5MW-D126-H90.csv", rho=1.225
@@ -165,8 +172,10 @@ class ModelBook:
165
172
  "kTI_<kTI>_<kb>",
166
173
  kTI=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
167
174
  kb=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
168
- hints={"kTI": "(Value, e.g. 004 for 0.04)",
169
- "kb": "(Value, e.g. 004 for 0.04)"},
175
+ hints={
176
+ "kTI": "(Value, e.g. 004 for 0.04)",
177
+ "kb": "(Value, e.g. 004 for 0.04)",
178
+ },
170
179
  )
171
180
  self.turbine_models.add_factory(
172
181
  fm.turbine_models.kTI,
@@ -174,8 +183,10 @@ class ModelBook:
174
183
  kwargs=dict(ti_var=FV.AMB_TI),
175
184
  kTI=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
176
185
  kb=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
177
- hints={"kTI": "(Value, e.g. 004 for 0.04)",
178
- "kb": "(Value, e.g. 004 for 0.04)"},
186
+ hints={
187
+ "kTI": "(Value, e.g. 004 for 0.04)",
188
+ "kb": "(Value, e.g. 004 for 0.04)",
189
+ },
179
190
  )
180
191
 
181
192
  self.turbine_models["hubh_data"] = fm.turbine_models.RotorCentreCalc(
@@ -187,7 +198,7 @@ class ModelBook:
187
198
  }
188
199
  )
189
200
 
190
- self.farm_models = Dict(
201
+ self.farm_models = FDict(
191
202
  name="farm_models",
192
203
  **{
193
204
  f"farm_{mname}": fm.farm_models.Turbine2FarmModel(m)
@@ -195,7 +206,7 @@ class ModelBook:
195
206
  },
196
207
  )
197
208
 
198
- self.farm_controllers = Dict(
209
+ self.farm_controllers = FDict(
199
210
  name="farm_controllers",
200
211
  basic_ctrl=fm.farm_controllers.BasicFarmController(),
201
212
  )
@@ -224,13 +235,10 @@ class ModelBook:
224
235
  name="wake_frames",
225
236
  rotor_wd=fm.wake_frames.RotorWD(var_wd=FV.WD),
226
237
  rotor_wd_farmo=fm.wake_frames.FarmOrder(),
227
- yawed=fm.wake_frames.YawedWakes(),
228
238
  )
229
- self.wake_frames.add_factory(
239
+ self.wake_frames.add_k_factory(
230
240
  fm.wake_frames.YawedWakes,
231
- "yawed_k<k>",
232
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
233
- hints={"k": "(Value, e.g. 004 for 0.04)"},
241
+ "yawed_[wake_k]",
234
242
  )
235
243
  self.wake_frames.add_factory(
236
244
  fm.wake_frames.Streamlines2D,
@@ -246,11 +254,13 @@ class ModelBook:
246
254
  )
247
255
 
248
256
  self.wake_frames["timelines"] = fm.wake_frames.Timelines()
257
+
249
258
  def _todt(x):
250
259
  if x[-1] == "s":
251
- return float(x[:-1])/60
260
+ return float(x[:-1]) / 60
252
261
  elif x[-3:] == "min":
253
262
  return float(x[:-3])
263
+
254
264
  self.wake_frames.add_factory(
255
265
  fm.wake_frames.Timelines,
256
266
  "timelines_<dt>",
@@ -266,7 +276,7 @@ class ModelBook:
266
276
  hints={"dt": "(Time step, e.g '10s', '1min' etc.)"},
267
277
  )
268
278
 
269
- self.wake_superpositions = Dict(
279
+ self.wake_superpositions = FDict(
270
280
  name="wake_superpositions",
271
281
  ws_linear=fm.wake_superpositions.WSLinear(scale_amb=False),
272
282
  ws_linear_lim=fm.wake_superpositions.WSLinear(
@@ -309,192 +319,119 @@ class ModelBook:
309
319
  ti_max=fm.wake_superpositions.TIMax(superp_to_amb="quadratic"),
310
320
  )
311
321
 
312
- self.axial_induction = Dict(name="induction_models")
313
- self.axial_induction["Betz"] = fm.axial_induction_models.BetzAxialInduction()
314
- self.axial_induction["Madsen"] = (
315
- fm.axial_induction_models.MadsenAxialInduction()
316
- )
322
+ self.axial_induction = FDict(name="induction_models")
323
+ self.axial_induction["Betz"] = fm.axial_induction.BetzAxialInduction()
324
+ self.axial_induction["Madsen"] = fm.axial_induction.MadsenAxialInduction()
317
325
 
318
326
  self.wake_models = FDict(name="wake_models")
319
327
 
320
- self.wake_models.add_factory(
328
+ self.wake_models.add_k_factory(
321
329
  fm.wake_models.wind.JensenWake,
322
- "Jensen_<superposition>",
330
+ "Jensen_<superposition>_[wake_k]",
331
+ kwargs=dict(induction="Betz"),
323
332
  superposition=lambda s: f"ws_{s}",
324
333
  hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
325
334
  )
326
- self.wake_models.add_factory(
327
- fm.wake_models.wind.JensenWake,
328
- "Jensen_<superposition>_k<k>",
329
- superposition=lambda s: f"ws_{s}",
330
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
331
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
332
- "k": "(Value, e.g. 004 for 0.04)"},
333
- )
334
335
 
335
- self.wake_models.add_factory(
336
+ self.wake_models.add_k_factory(
336
337
  fm.wake_models.wind.Bastankhah2014,
337
- "Bastankhah2014_<superposition>",
338
- kwargs=dict(sbeta_factor=0.2),
338
+ "Bastankhah2014_<superposition>_[wake_k]",
339
+ kwargs=dict(sbeta_factor=0.2, induction="Madsen"),
339
340
  superposition=lambda s: f"ws_{s}",
340
341
  hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
341
342
  )
342
- self.wake_models.add_factory(
343
+ self.wake_models.add_k_factory(
343
344
  fm.wake_models.wind.Bastankhah2014,
344
- "Bastankhah2014_<superposition>_k<k>",
345
- kwargs=dict(sbeta_factor=0.2),
346
- superposition=lambda s: f"ws_{s}",
347
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
348
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
349
- "k": "(Value, e.g. 004 for 0.04)"},
350
- )
351
- self.wake_models.add_factory(
352
- fm.wake_models.wind.Bastankhah2014,
353
- "Bastankhah2014B_<superposition>",
345
+ "Bastankhah2014B_<superposition>_[wake_k]",
354
346
  kwargs=dict(sbeta_factor=0.2, induction="Betz"),
355
347
  superposition=lambda s: f"ws_{s}",
356
348
  hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
357
349
  )
358
- self.wake_models.add_factory(
350
+ self.wake_models.add_k_factory(
359
351
  fm.wake_models.wind.Bastankhah2014,
360
- "Bastankhah2014B_<superposition>_k<k>",
361
- kwargs=dict(sbeta_factor=0.2, induction="Betz"),
362
- superposition=lambda s: f"ws_{s}",
363
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
364
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
365
- "k": "(Value, e.g. 004 for 0.04)"},
366
- )
367
- self.wake_models.add_factory(
368
- fm.wake_models.wind.Bastankhah2014,
369
- "Bastankhah025_<superposition>",
370
- kwargs=dict(sbeta_factor=0.25),
352
+ "Bastankhah025_<superposition>_[wake_k]",
353
+ kwargs=dict(sbeta_factor=0.25, induction="Madsen"),
371
354
  superposition=lambda s: f"ws_{s}",
372
355
  hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
373
356
  )
374
- self.wake_models.add_factory(
357
+ self.wake_models.add_k_factory(
375
358
  fm.wake_models.wind.Bastankhah2014,
376
- "Bastankhah025_<superposition>_k<k>",
377
- kwargs=dict(sbeta_factor=0.25),
378
- superposition=lambda s: f"ws_{s}",
379
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
380
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
381
- "k": "(Value, e.g. 004 for 0.04)"},
382
- )
383
- self.wake_models.add_factory(
384
- fm.wake_models.wind.Bastankhah2014,
385
- "Bastankhah025B_<superposition>",
359
+ "Bastankhah025B_<superposition>_[wake_k]",
386
360
  kwargs=dict(sbeta_factor=0.25, induction="Betz"),
387
361
  superposition=lambda s: f"ws_{s}",
388
362
  hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
389
363
  )
390
- self.wake_models.add_factory(
391
- fm.wake_models.wind.Bastankhah2014,
392
- "Bastankhah025B_<superposition>_k<k>",
393
- kwargs=dict(sbeta_factor=0.25, induction="Betz"),
394
- superposition=lambda s: f"ws_{s}",
395
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
396
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
397
- "k": "(Value, e.g. 004 for 0.04)"},
398
- )
399
364
 
400
- self.wake_models.add_factory(
365
+ self.wake_models.add_k_factory(
401
366
  fm.wake_models.wind.Bastankhah2016,
402
- "Bastankhah2016_<superposition>",
367
+ "Bastankhah2016_<superposition>_[wake_k]",
368
+ kwargs=dict(induction="Madsen"),
403
369
  superposition=lambda s: f"ws_{s}",
404
370
  hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
405
371
  )
406
- self.wake_models.add_factory(
372
+ self.wake_models.add_k_factory(
407
373
  fm.wake_models.wind.Bastankhah2016,
408
- "Bastankhah2016_<superposition>_k<k>",
409
- superposition=lambda s: f"ws_{s}",
410
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
411
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
412
- "k": "(Value, e.g. 004 for 0.04)"},
413
- )
414
- self.wake_models.add_factory(
415
- fm.wake_models.wind.Bastankhah2016,
416
- "Bastankhah2016B_<superposition>",
374
+ "Bastankhah2016B_<superposition>_[wake_k]",
417
375
  kwargs=dict(induction="Betz"),
418
376
  superposition=lambda s: f"ws_{s}",
419
377
  hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
420
378
  )
421
- self.wake_models.add_factory(
422
- fm.wake_models.wind.Bastankhah2016,
423
- "Bastankhah2016B_<superposition>_k<k>",
424
- kwargs=dict(induction="Betz"),
425
- superposition=lambda s: f"ws_{s}",
426
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
427
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
428
- "k": "(Value, e.g. 004 for 0.04)"},
429
- )
430
379
 
431
- self.wake_models.add_factory(
380
+ self.wake_models.add_k_factory(
432
381
  fm.wake_models.wind.TurbOParkWake,
433
- "TurbOPark_<superposition>",
382
+ "TurbOPark_<superposition>_[wake_k]",
383
+ kwargs=dict(induction="Madsen"),
434
384
  superposition=lambda s: f"ws_{s}",
435
385
  hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
436
386
  )
437
- self.wake_models.add_factory(
387
+ self.wake_models.add_k_factory(
438
388
  fm.wake_models.wind.TurbOParkWake,
439
- "TurbOPark_<superposition>_k<k>",
440
- superposition=lambda s: f"ws_{s}",
441
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
442
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
443
- "k": "(Value, e.g. 004 for 0.04)"},
444
- )
445
- self.wake_models.add_factory(
446
- fm.wake_models.wind.TurbOParkWake,
447
- "TurbOParkB_<superposition>",
389
+ "TurbOParkB_<superposition>_[wake_k]",
448
390
  kwargs=dict(induction="Betz"),
449
391
  superposition=lambda s: f"ws_{s}",
450
392
  hints={"superposition": "(Superposition, e.g. linear for ws_linear)"},
451
393
  )
452
- self.wake_models.add_factory(
453
- fm.wake_models.wind.TurbOParkWake,
454
- "TurbOParkB_<superposition>_k<k>",
455
- kwargs=dict(induction="Betz"),
456
- superposition=lambda s: f"ws_{s}",
457
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
458
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
459
- "k": "(Value, e.g. 004 for 0.04)"},
460
- )
461
394
 
462
- self.wake_models.add_factory(
395
+ self.wake_models.add_k_factory(
463
396
  fm.wake_models.wind.TurbOParkWakeIX,
464
- "TurbOParkIX_<superposition>_dx<dx>",
397
+ "TurbOParkIX_<superposition>_[wake_k]_dx<dx>",
465
398
  superposition=lambda s: f"ws_{s}",
466
399
  dx=lambda x: float(x),
467
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
468
- "dx": "(Integration step in m)"},
400
+ hints={
401
+ "superposition": "(Superposition, e.g. linear for ws_linear)",
402
+ "dx": "(Integration step in m)",
403
+ },
469
404
  )
470
405
 
471
- self.wake_models.add_factory(
472
- fm.wake_models.wind.TurbOParkWakeIX,
473
- "TurbOParkIX_<superposition>_k<k>_dx<dx>",
474
- superposition=lambda s: f"ws_{s}",
475
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
476
- dx=lambda x: float(x),
477
- hints={"superposition": "(Superposition, e.g. linear for ws_linear)",
478
- "k": "(Value, e.g. 004 for 0.04)",
479
- "dx": "(Integration step in m)"},
406
+ self.wake_models.add_k_factory(
407
+ fm.wake_models.ti.CrespoHernandezTIWake,
408
+ "CrespoHernandez_<superposition>_[wake_k]",
409
+ kwargs=dict(use_ambti=False),
410
+ superposition=lambda s: f"ti_{s}",
411
+ hints={"superposition": "(Superposition, e.g. linear for ti_linear)"},
480
412
  )
481
413
 
482
414
  self.wake_models.add_factory(
483
- fm.wake_models.ti.CrespoHernandezTIWake,
484
- "CrespoHernandez_<superposition>",
485
- kwargs=dict(use_ambti=False),
415
+ fm.wake_models.ti.IECTIWake,
416
+ "IECTI2005_<superposition>",
417
+ kwargs=dict(iec_type="2005"),
486
418
  superposition=lambda s: f"ti_{s}",
487
419
  hints={"superposition": "(Superposition, e.g. linear for ti_linear)"},
488
420
  )
489
421
 
490
422
  self.wake_models.add_factory(
491
- fm.wake_models.ti.CrespoHernandezTIWake,
492
- "CrespoHernandez_<superposition>_k<k>",
493
- kwargs=dict(use_ambti=False),
423
+ fm.wake_models.ti.IECTIWake,
424
+ "IECTI2019_<superposition>",
425
+ kwargs=dict(iec_type="2019"),
494
426
  superposition=lambda s: f"ti_{s}",
495
- k=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
496
- hints={"superposition": "(Superposition, e.g. linear for ti_linear)",
497
- "k": "(Value, e.g. 004 for 0.04)"},
427
+ hints={"superposition": "(Superposition, e.g. linear for ti_linear)"},
428
+ )
429
+ self.wake_models.add_k_factory(
430
+ fm.wake_models.ti.IECTIWake,
431
+ "IECTI2019k_<superposition>_[wake_k]",
432
+ kwargs=dict(iec_type="2019", opening_angle=None),
433
+ superposition=lambda s: f"ti_{s}",
434
+ hints={"superposition": "(Superposition, e.g. linear for ti_linear)"},
498
435
  )
499
436
 
500
437
  self.wake_models.add_factory(
@@ -504,11 +441,10 @@ class ModelBook:
504
441
  superposition=lambda s: f"ti_{s}",
505
442
  hints={"superposition": "(Superposition, e.g. linear for ti_linear)"},
506
443
  )
507
-
508
- self.wake_models.add_factory(
444
+ self.wake_models.add_k_factory(
509
445
  fm.wake_models.ti.IECTIWake,
510
- "IECTI2019_<superposition>",
511
- kwargs=dict(iec_type="2019"),
446
+ "IECTI2005k_<superposition>_[wake_k]",
447
+ kwargs=dict(iec_type="2005", opening_angle=None),
512
448
  superposition=lambda s: f"ti_{s}",
513
449
  hints={"superposition": "(Superposition, e.g. linear for ti_linear)"},
514
450
  )
@@ -519,8 +455,20 @@ class ModelBook:
519
455
  self.wake_models[f"SelfSimilar2020"] = (
520
456
  fm.wake_models.induction.SelfSimilar2020()
521
457
  )
458
+ self.wake_models[f"VortexSheet"] = fm.wake_models.induction.VortexSheet()
459
+
460
+ self.ground_models = FDict(name="ground_models")
461
+ self.ground_models["no_ground"] = fm.ground_models.NoGround()
462
+ self.ground_models["ground_mirror"] = fm.ground_models.GroundMirror()
463
+ self.ground_models.add_factory(
464
+ fm.ground_models.WakeMirror,
465
+ "blh_mirror_h<height>",
466
+ var2arg={"height": "heights"},
467
+ height=lambda h: [0.0, float(h)],
468
+ hints={"height": "(Boundary layer wake reflection height)"},
469
+ )
522
470
 
523
- self.sources = Dict(
471
+ self.sources = FDict(
524
472
  name="sources",
525
473
  point_models=self.point_models,
526
474
  rotor_models=self.rotor_models,
@@ -533,8 +481,9 @@ class ModelBook:
533
481
  wake_superpositions=self.wake_superpositions,
534
482
  wake_models=self.wake_models,
535
483
  axial_induction=self.axial_induction,
484
+ ground_models=self.ground_models,
536
485
  )
537
- self.base_classes = Dict(
486
+ self.base_classes = FDict(
538
487
  name="base_classes",
539
488
  point_models=PointDataModel,
540
489
  rotor_models=RotorModel,
@@ -547,6 +496,7 @@ class ModelBook:
547
496
  wake_superpositions=WakeSuperposition,
548
497
  wake_models=WakeModel,
549
498
  axial_induction=AxialInductionModel,
499
+ ground_models=GroundModel,
550
500
  )
551
501
 
552
502
  for s in self.sources.values():
@@ -663,7 +613,7 @@ class ModelBook:
663
613
 
664
614
  """
665
615
  for ms in self.sources.values():
666
- if isinstance(ms, Dict):
616
+ if isinstance(ms, FDict):
667
617
  for m in ms.values():
668
618
  if m.initialized:
669
619
  m.finalize(algo, verbosity)
@@ -44,6 +44,31 @@ class PartialAxiwake(PartialCentre):
44
44
  def __repr__(self):
45
45
  return f"{type(self).__name__}(n={self.n})"
46
46
 
47
+ def check_wmodel(self, wmodel, error=True):
48
+ """
49
+ Checks the wake model type
50
+
51
+ Parameters
52
+ ----------
53
+ wmodel: foxes.core.WakeModel
54
+ The wake model to be tested
55
+ error: bool
56
+ Flag for raising TypeError
57
+
58
+ Returns
59
+ -------
60
+ chk: bool
61
+ True if wake model is compatible
62
+
63
+ """
64
+ if not isinstance(wmodel, AxisymmetricWakeModel):
65
+ if error:
66
+ raise TypeError(
67
+ f"Partial wakes '{self.name}': Cannot be applied to wake model '{wmodel.name}', since not an AxisymmetricWakeModel"
68
+ )
69
+ return False
70
+ return True
71
+
47
72
  def contribute(
48
73
  self,
49
74
  algo,
@@ -79,10 +104,8 @@ class PartialAxiwake(PartialCentre):
79
104
  The wake model
80
105
 
81
106
  """
82
- if not isinstance(wmodel, AxisymmetricWakeModel):
83
- raise TypeError(
84
- f"Partial wakes '{self.name}': Cannot be applied to wake model '{wmodel.name}', since not an AxisymmetricWakeModel"
85
- )
107
+ # check:
108
+ self.check_wmodel(wmodel, error=True)
86
109
 
87
110
  # prepare:
88
111
  n_states = mdata.n_states
@@ -24,6 +24,31 @@ class PartialTopHat(PartialCentre):
24
24
 
25
25
  """
26
26
 
27
+ def check_wmodel(self, wmodel, error=True):
28
+ """
29
+ Checks the wake model type
30
+
31
+ Parameters
32
+ ----------
33
+ wmodel: foxes.core.WakeModel
34
+ The wake model to be tested
35
+ error: bool
36
+ Flag for raising TypeError
37
+
38
+ Returns
39
+ -------
40
+ chk: bool
41
+ True if wake model is compatible
42
+
43
+ """
44
+ if not isinstance(wmodel, TopHatWakeModel):
45
+ if error:
46
+ raise TypeError(
47
+ f"Partial wakes '{self.name}': Cannot be applied to wake model '{wmodel.name}', since not a TopHatWakeModel"
48
+ )
49
+ return False
50
+ return True
51
+
27
52
  def __init__(self, rotor_model=None):
28
53
  """
29
54
  Constructor.
@@ -105,10 +130,7 @@ class PartialTopHat(PartialCentre):
105
130
  The wake model
106
131
 
107
132
  """
108
- if not isinstance(wmodel, TopHatWakeModel):
109
- raise TypeError(
110
- f"Partial wakes '{self.name}': Cannot be applied to wake model '{wmodel.name}', since not a TopHatWakeModel"
111
- )
133
+ self.check_wmodel(wmodel, error=True)
112
134
 
113
135
  wcoos = algo.wake_frame.get_wake_coos(algo, mdata, fdata, tdata, downwind_index)
114
136
  x = wcoos[:, :, 0, 0]
@@ -103,6 +103,7 @@ class PCtFile(TurbineType):
103
103
 
104
104
  def __repr__(self):
105
105
  a = f"D={self.D}, H={self.H}, P_nominal={self.P_nominal}, P_unit={self.P_unit}, rho={self.rho}"
106
+ a += f", var_ws_ct={self.WSCT}, var_ws_P={self.WSP}"
106
107
  return f"{type(self).__name__}({a})"
107
108
 
108
109
  def output_farm_vars(self, algo):