foxes 0.5.0.2__py3-none-any.whl → 0.5.2__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 +41 -46
  3. foxes/algorithms/downwind/models/point_wakes_calc.py +4 -9
  4. foxes/algorithms/downwind/models/set_amb_point_results.py +5 -22
  5. foxes/core/algorithm.py +1 -1
  6. foxes/core/data_calc_model.py +26 -2
  7. foxes/core/partial_wakes_model.py +1 -1
  8. foxes/core/rotor_model.py +36 -2
  9. foxes/core/turbine_model.py +36 -0
  10. foxes/core/turbine_type.py +35 -1
  11. foxes/core/wake_frame.py +39 -3
  12. foxes/core/wake_model.py +36 -0
  13. foxes/models/model_book.py +129 -89
  14. foxes/models/turbine_models/rotor_centre_calc.py +1 -2
  15. foxes/models/turbine_types/CpCt_file.py +13 -3
  16. foxes/models/turbine_types/CpCt_from_two.py +14 -4
  17. foxes/models/vertical_profiles/abl_log_neutral_ws.py +32 -5
  18. foxes/models/vertical_profiles/abl_log_stable_ws.py +32 -4
  19. foxes/models/vertical_profiles/abl_log_unstable_ws.py +32 -4
  20. foxes/models/vertical_profiles/abl_log_ws.py +50 -18
  21. foxes/models/wake_frames/yawed_wakes.py +15 -9
  22. foxes/models/wake_models/induction/__init__.py +1 -1
  23. foxes/models/wake_models/induction/rankine_half_body.py +33 -7
  24. foxes/models/wake_models/ti/crespo_hernandez.py +6 -1
  25. foxes/models/wake_models/ti/iec_ti.py +5 -3
  26. foxes/models/wake_models/wind/__init__.py +2 -2
  27. foxes/models/wake_models/wind/{bastankhah.py → bastankhah14.py} +11 -14
  28. foxes/models/wake_models/wind/{porte_agel.py → bastankhah16.py} +24 -16
  29. foxes/models/wake_models/wind/turbopark.py +11 -22
  30. foxes/models/wake_superpositions/__init__.py +9 -5
  31. foxes/models/wake_superpositions/ti_linear.py +134 -0
  32. foxes/models/wake_superpositions/ti_max.py +134 -0
  33. foxes/models/wake_superpositions/{ti_superp.py → ti_pow.py} +15 -57
  34. foxes/models/wake_superpositions/ti_quadratic.py +134 -0
  35. foxes/models/wake_superpositions/ws_linear.py +170 -0
  36. foxes/models/wake_superpositions/ws_max.py +173 -0
  37. foxes/models/wake_superpositions/ws_pow.py +175 -0
  38. foxes/models/wake_superpositions/{product.py → ws_product.py} +43 -22
  39. foxes/models/wake_superpositions/ws_quadratic.py +170 -0
  40. foxes/output/__init__.py +4 -0
  41. foxes/output/calc_points.py +143 -0
  42. foxes/output/flow_plots_2d/__init__.py +1 -0
  43. foxes/output/flow_plots_2d/common.py +104 -1
  44. foxes/output/flow_plots_2d/flow_plots.py +237 -569
  45. foxes/output/flow_plots_2d/get_fig.py +183 -0
  46. foxes/output/flow_plots_2d/seq_flow_ani_plugin.py +0 -1
  47. foxes/output/grids.py +705 -0
  48. foxes/output/output.py +58 -11
  49. foxes/output/results_writer.py +101 -17
  50. foxes/output/round.py +10 -0
  51. foxes/output/slice_data.py +900 -0
  52. foxes/utils/__init__.py +5 -3
  53. foxes/utils/exec_python.py +56 -0
  54. foxes/utils/geopandas_utils.py +294 -0
  55. foxes/utils/pandas_utils.py +175 -0
  56. foxes/utils/plotly_utils.py +19 -0
  57. foxes/utils/xarray_utils.py +38 -0
  58. {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/METADATA +1 -1
  59. {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/RECORD +63 -49
  60. foxes/models/wake_superpositions/linear.py +0 -242
  61. foxes/models/wake_superpositions/max.py +0 -258
  62. foxes/models/wake_superpositions/quadratic.py +0 -252
  63. {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/LICENSE +0 -0
  64. {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/WHEEL +0 -0
  65. {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/top_level.txt +0 -0
  66. {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/zip-safe +0 -0
@@ -1,15 +1,20 @@
1
1
  import foxes.models as fm
2
2
  import foxes.variables as FV
3
3
  from foxes.utils import Dict
4
+
4
5
  from foxes.core import (
5
- TurbineModel,
6
- RotorModel,
7
- FarmModel,
8
6
  PointDataModel,
7
+ FarmDataModel,
9
8
  FarmController,
9
+ RotorModel,
10
+ TurbineType,
11
+ TurbineModel,
12
+ PartialWakesModel,
13
+ WakeFrame,
14
+ WakeSuperposition,
15
+ WakeModel
10
16
  )
11
17
 
12
-
13
18
  class ModelBook:
14
19
  """
15
20
  Container for all kinds of models.
@@ -28,9 +33,6 @@ class ModelBook:
28
33
  turbine_models: foxes.utils.Dict
29
34
  The turbine models. Keys: model name str,
30
35
  values: foxes.core.TurbineModel
31
- turbine_orders: foxes.utils.Dict
32
- The turbine orders. Keys: model name str,
33
- values: foxes.core.TurbineOrder
34
36
  farm_models: foxes.utils.Dict
35
37
  The farm models. Keys: model name str,
36
38
  values: foxes.core.FarmModel
@@ -51,6 +53,8 @@ class ModelBook:
51
53
  values: foxes.core.WakeModel
52
54
  sources: foxes.utils.Dict
53
55
  All sources dict
56
+ base_classes: foxes.utils.Dict
57
+ The base classes for all model types
54
58
 
55
59
  :group: foxes
56
60
 
@@ -193,47 +197,27 @@ class ModelBook:
193
197
 
194
198
  self.wake_superpositions = Dict(
195
199
  name="wake_superpositions",
196
- linear=fm.wake_superpositions.LinearSuperposition(
197
- scalings=f"source_turbine_{FV.REWS}"
198
- ),
199
- linear_lim=fm.wake_superpositions.LinearSuperposition(
200
- scalings=f"source_turbine_{FV.REWS}",
201
- lim_low={FV.WS: 1e-4},
202
- ),
203
- linear_amb=fm.wake_superpositions.LinearSuperposition(
204
- scalings=f"source_turbine_{FV.AMB_REWS}"
205
- ),
206
- quadratic=fm.wake_superpositions.QuadraticSuperposition(
207
- scalings=f"source_turbine_{FV.REWS}"
208
- ),
209
- quadratic_amb=fm.wake_superpositions.QuadraticSuperposition(
210
- scalings=f"source_turbine_{FV.AMB_REWS}"
211
- ),
212
- max=fm.wake_superpositions.MaxSuperposition(
213
- scalings=f"source_turbine_{FV.REWS}"
214
- ),
215
- max_amb=fm.wake_superpositions.MaxSuperposition(
216
- scalings=f"source_turbine_{FV.AMB_REWS}"
217
- ),
218
- product=fm.wake_superpositions.ProductSuperposition(),
219
- product_lim=fm.wake_superpositions.ProductSuperposition(
220
- lim_low={FV.WS: 1e-4},
221
- ),
222
- ti_linear=fm.wake_superpositions.TISuperposition(
223
- ti_superp="linear", superp_to_amb="quadratic"
224
- ),
225
- ti_quadratic=fm.wake_superpositions.TISuperposition(
226
- ti_superp="quadratic", superp_to_amb="quadratic"
227
- ),
228
- ti_cubic=fm.wake_superpositions.TISuperposition(
229
- ti_superp="power_3", superp_to_amb="quadratic"
230
- ),
231
- ti_quartic=fm.wake_superpositions.TISuperposition(
232
- ti_superp="power_4", superp_to_amb="quadratic"
233
- ),
234
- ti_max=fm.wake_superpositions.TISuperposition(
235
- ti_superp="max", superp_to_amb="quadratic"
236
- ),
200
+ ws_linear=fm.wake_superpositions.WSLinear(scale_amb=False),
201
+ ws_linear_lim=fm.wake_superpositions.WSLinear(scale_amb=False, lim_low=1e-4),
202
+ ws_linear_amb=fm.wake_superpositions.WSLinear(scale_amb=True),
203
+ ws_linear_amb_lim=fm.wake_superpositions.WSLinear(scale_amb=True, lim_low=1e-4),
204
+ ws_quadratic=fm.wake_superpositions.WSQuadratic(scale_amb=False),
205
+ ws_quadratic_lim=fm.wake_superpositions.WSQuadratic(scale_amb=False, lim_low=1e-4),
206
+ ws_quadratic_amb=fm.wake_superpositions.WSQuadratic(scale_amb=True),
207
+ ws_quadratic_amb_lim=fm.wake_superpositions.WSQuadratic(scale_amb=True, lim_low=1e-4),
208
+ ws_cubic=fm.wake_superpositions.WSPow(pow=3, scale_amb=False),
209
+ ws_cubic_amb=fm.wake_superpositions.WSPow(pow=3, scale_amb=True),
210
+ ws_quartic=fm.wake_superpositions.WSPow(pow=4, scale_amb=False),
211
+ ws_quartic_amb=fm.wake_superpositions.WSPow(pow=4, scale_amb=True),
212
+ ws_max=fm.wake_superpositions.WSMax(scale_amb=False),
213
+ ws_max_amb=fm.wake_superpositions.WSMax(scale_amb=True),
214
+ ws_product=fm.wake_superpositions.WSProduct(),
215
+ ws_product_lim=fm.wake_superpositions.WSProduct(lim_low=1e-4),
216
+ ti_linear=fm.wake_superpositions.TILinear(superp_to_amb="quadratic"),
217
+ ti_quadratic=fm.wake_superpositions.TIQuadratic(superp_to_amb="quadratic"),
218
+ ti_cubic=fm.wake_superpositions.TIPow(pow=3, superp_to_amb="quadratic"),
219
+ ti_quartic=fm.wake_superpositions.TIPow(pow=4, superp_to_amb="quadratic"),
220
+ ti_max=fm.wake_superpositions.TIMax(superp_to_amb="quadratic"),
237
221
  )
238
222
 
239
223
  self.wake_models = Dict(name="wake_models")
@@ -241,69 +225,80 @@ class ModelBook:
241
225
  "linear",
242
226
  "linear_lim",
243
227
  "linear_amb",
228
+ "linear_amb_lim",
244
229
  "quadratic",
230
+ "wquadratic_lim",
245
231
  "quadratic_amb",
246
- "max",
232
+ "quadratic_amb_lim",
233
+ "cubic",
234
+ "cubic_amb",
235
+ "quartic",
236
+ "quartic_amb",
237
+ "wmax",
247
238
  "max_amb",
248
239
  "product",
249
240
  "product_lim",
250
241
  ]
251
242
  for s in slist:
252
243
  self.wake_models[f"Jensen_{s}"] = fm.wake_models.wind.JensenWake(
253
- superposition=s
244
+ superposition=f"ws_{s}"
254
245
  )
255
246
  self.wake_models[f"Jensen_{s}_k002"] = fm.wake_models.wind.JensenWake(
256
- k=0.02, superposition=s
247
+ k=0.02, superposition=f"ws_{s}"
257
248
  )
258
249
  self.wake_models[f"Jensen_{s}_k004"] = fm.wake_models.wind.JensenWake(
259
- k=0.04, superposition=s
250
+ k=0.04, superposition=f"ws_{s}"
260
251
  )
261
252
  self.wake_models[f"Jensen_{s}_k007"] = fm.wake_models.wind.JensenWake(
262
- k=0.07, superposition=s
253
+ k=0.07, superposition=f"ws_{s}"
263
254
  )
264
255
  self.wake_models[f"Jensen_{s}_k0075"] = fm.wake_models.wind.JensenWake(
265
- k=0.075, superposition=s
256
+ k=0.075, superposition=f"ws_{s}"
266
257
  )
267
258
 
268
- self.wake_models[f"Bastankhah_{s}"] = fm.wake_models.wind.BastankhahWake(
269
- superposition=s
259
+ self.wake_models[f"Bastankhah2014_{s}"] = fm.wake_models.wind.Bastankhah2014(
260
+ superposition=f"ws_{s}", sbeta_factor=0.2
270
261
  )
271
262
  self.wake_models[
272
- f"Bastankhah_{s}_k002"
273
- ] = fm.wake_models.wind.BastankhahWake(k=0.02, superposition=s)
263
+ f"Bastankhah2014_{s}_k002"
264
+ ] = fm.wake_models.wind.Bastankhah2014(
265
+ k=0.02, sbeta_factor=0.2, superposition=f"ws_{s}"
266
+ )
274
267
  self.wake_models[
275
- f"Bastankhah_{s}_k004"
276
- ] = fm.wake_models.wind.BastankhahWake(k=0.04, superposition=s)
268
+ f"Bastankhah2014_{s}_k004"
269
+ ] = fm.wake_models.wind.Bastankhah2014(
270
+ k=0.04, sbeta_factor=0.2, superposition=f"ws_{s}"
271
+ )
277
272
 
278
- self.wake_models[f"Bastankhah0_{s}"] = fm.wake_models.wind.BastankhahWake(
279
- superposition=s, sbeta_factor=0.2
273
+ self.wake_models[f"Bastankhah025_{s}"] = fm.wake_models.wind.Bastankhah2014(
274
+ superposition=f"ws_{s}", sbeta_factor=0.25
280
275
  )
281
276
  self.wake_models[
282
- f"Bastankhah0_{s}_k002"
283
- ] = fm.wake_models.wind.BastankhahWake(
284
- k=0.02, superposition=s, sbeta_factor=0.2
277
+ f"Bastankhah025_{s}_k002"
278
+ ] = fm.wake_models.wind.Bastankhah2014(
279
+ k=0.02, superposition=f"ws_{s}", sbeta_factor=0.25
285
280
  )
286
281
  self.wake_models[
287
- f"Bastankhah0_{s}_k004"
288
- ] = fm.wake_models.wind.BastankhahWake(
289
- k=0.04, superposition=s, sbeta_factor=0.2
282
+ f"Bastankhah025_{s}_k004"
283
+ ] = fm.wake_models.wind.Bastankhah2014(
284
+ k=0.04, superposition=f"ws_{s}", sbeta_factor=0.25
290
285
  )
291
286
 
292
- self.wake_models[f"PorteAgel_{s}"] = fm.wake_models.wind.PorteAgelWake(
293
- superposition=s
287
+ self.wake_models[f"Bastankhah2016_{s}"] = fm.wake_models.wind.Bastankhah2016(
288
+ superposition=f"ws_{s}"
294
289
  )
295
- self.wake_models[f"PorteAgel_{s}_k002"] = fm.wake_models.wind.PorteAgelWake(
296
- superposition=s, k=0.02
290
+ self.wake_models[f"Bastankhah2016_{s}_k002"] = fm.wake_models.wind.Bastankhah2016(
291
+ superposition=f"ws_{s}", k=0.02
297
292
  )
298
- self.wake_models[f"PorteAgel_{s}_k004"] = fm.wake_models.wind.PorteAgelWake(
299
- superposition=s, k=0.04
293
+ self.wake_models[f"Bastankhah2016_{s}_k004"] = fm.wake_models.wind.Bastankhah2016(
294
+ superposition=f"ws_{s}", k=0.04
300
295
  )
301
296
 
302
297
  self.wake_models[f"TurbOPark_{s}_A002"] = fm.wake_models.wind.TurbOParkWake(
303
- A=0.02, superposition=s
298
+ A=0.02, superposition=f"ws_{s}"
304
299
  )
305
300
  self.wake_models[f"TurbOPark_{s}_A004"] = fm.wake_models.wind.TurbOParkWake(
306
- A=0.04, superposition=s
301
+ A=0.04, superposition=f"ws_{s}"
307
302
  )
308
303
 
309
304
  As = [0.02, 0.04]
@@ -314,29 +309,29 @@ class ModelBook:
314
309
  d = str(dx).replace(".", "") if dx < 1 else int(dx)
315
310
  self.wake_models[
316
311
  f"TurbOParkIX_{s}_A{a}_dx{d}"
317
- ] = fm.wake_models.wind.TurbOParkWakeIX(A=A, superposition=s, dx=dx)
312
+ ] = fm.wake_models.wind.TurbOParkWakeIX(A=A, superposition=f"ws_{s}", dx=dx)
318
313
 
319
- slist = ["ti_linear", "ti_quadratic", "ti_cubic", "ti_quartic", "ti_max"]
314
+ slist = ["linear", "quadratic", "cubic", "quartic", "max"]
320
315
  for s in slist:
321
316
  self.wake_models[
322
- f"CrespoHernandez_{s[3:]}"
323
- ] = fm.wake_models.ti.CrespoHernandezTIWake(superposition=s)
317
+ f"CrespoHernandez_{s}"
318
+ ] = fm.wake_models.ti.CrespoHernandezTIWake(superposition=f"ti_{s}")
324
319
  self.wake_models[
325
- f"CrespoHernandez_ambti_{s[3:]}"
326
- ] = fm.wake_models.ti.CrespoHernandezTIWake(superposition=s, use_ambti=True)
320
+ f"CrespoHernandez_ambti_{s}"
321
+ ] = fm.wake_models.ti.CrespoHernandezTIWake(superposition=f"ti_{s}", use_ambti=True)
327
322
  self.wake_models[
328
- f"CrespoHernandez_{s[3:]}_k002"
329
- ] = fm.wake_models.ti.CrespoHernandezTIWake(k=0.02, superposition=s)
323
+ f"CrespoHernandez_{s}_k002"
324
+ ] = fm.wake_models.ti.CrespoHernandezTIWake(k=0.02, superposition=f"ti_{s}")
330
325
 
331
- self.wake_models[f"IECTI2005_{s[3:]}"] = fm.wake_models.ti.IECTIWake(
332
- superposition=s, iec_type="2005"
326
+ self.wake_models[f"IECTI2005_{s}"] = fm.wake_models.ti.IECTIWake(
327
+ superposition=f"ti_{s}", iec_type="2005"
333
328
  )
334
329
 
335
- self.wake_models[f"IECTI2019_{s[3:]}"] = fm.wake_models.ti.IECTIWake(
336
- superposition=s, iec_type="2019"
330
+ self.wake_models[f"IECTI2019_{s}"] = fm.wake_models.ti.IECTIWake(
331
+ superposition=f"ti_{s}", iec_type="2019"
337
332
  )
338
333
 
339
- self.wake_models[f"RHB"] = fm.wake_models.induction.RHB()
334
+ self.wake_models[f"RHB"] = fm.wake_models.induction.RankineHalfBody()
340
335
 
341
336
  self.sources = Dict(
342
337
  name="sources",
@@ -351,6 +346,19 @@ class ModelBook:
351
346
  wake_superpositions=self.wake_superpositions,
352
347
  wake_models=self.wake_models,
353
348
  )
349
+ self.base_classes = Dict(
350
+ name="base_classes",
351
+ point_models=PointDataModel,
352
+ rotor_models=RotorModel,
353
+ turbine_types=TurbineType,
354
+ turbine_models=TurbineModel,
355
+ farm_models=FarmDataModel,
356
+ farm_controllers=FarmController,
357
+ partial_wakes=PartialWakesModel,
358
+ wake_frames=WakeFrame,
359
+ wake_superpositions=WakeSuperposition,
360
+ wake_models=WakeModel,
361
+ )
354
362
 
355
363
  for s in self.sources.values():
356
364
  for k, m in s.items():
@@ -383,6 +391,38 @@ class ModelBook:
383
391
  else:
384
392
  print("(none)")
385
393
  print()
394
+
395
+ def get(self, model_type, name, class_name=None, *args, **kwargs):
396
+ """
397
+ Gets a model object.
398
+
399
+ If not found, dynamically creates it (given the class name)
400
+
401
+ Parameters
402
+ ----------
403
+ model_type: str
404
+ The model type
405
+ name: str
406
+ The model name
407
+ class_name: str, optinal
408
+ Name of the model class
409
+ args: tuple, optional
410
+ Arguments for the model class
411
+ kwargs: dict, optional
412
+ Arguments for the model class
413
+
414
+ Returns
415
+ -------
416
+ model: mclass
417
+ The model object
418
+
419
+ """
420
+ if name not in self.sources[model_type]:
421
+ if class_name is None:
422
+ raise KeyError(f"Model '{name}' of type '{model_type}' not found in model book. Available: {sorted(list(self.sources[model_type].keys()))}")
423
+ bclass = self.base_classes[model_type]
424
+ self.sources[model_type][name] = bclass.new(class_name, *args, **kwargs)
425
+ return self.sources[model_type][name]
386
426
 
387
427
  def finalize(self, algo, verbosity=0):
388
428
  """
@@ -49,8 +49,7 @@ class RotorCentreCalc(TurbineModel):
49
49
  The verbosity level, 0 = silent
50
50
 
51
51
  """
52
- pvars = list(self.calc_vars.values())
53
- self._wcalc = algo.PointWakesCalculation(point_vars=pvars)
52
+ self._wcalc = algo.get_model("PointWakesCalculation")()
54
53
  super().initialize(algo, verbosity)
55
54
 
56
55
  def sub_models(self):
@@ -4,7 +4,7 @@ import pandas as pd
4
4
  from .PCt_file import PCtFile
5
5
  from foxes.data import parse_Pct_file_name
6
6
  from foxes.utils import PandasFileHelper
7
-
7
+ import foxes.constants as FC
8
8
 
9
9
  class CpCtFile(PCtFile):
10
10
  """
@@ -55,6 +55,16 @@ class CpCtFile(PCtFile):
55
55
  A = np.pi * (D / 2) ** 2
56
56
  ws = data[col_ws].to_numpy()
57
57
  cp = data[col_cp].to_numpy()
58
- data["P"] = 0.5 * rho * A * cp * ws**3
58
+ P_unit = pars.pop("P_unit", FC.kW)
59
+
60
+ ws_delta = 0.0001
61
+ ws_min = np.min(ws)
62
+ ws_max = np.max(ws)
63
+ N = int((ws_max - ws_min)/ws_delta)
64
+
65
+ data_P = pd.DataFrame(index=range(N), dtype=FC.DTYPE)
66
+ data_P["ws"] = np.linspace(ws_min, ws_max, N, endpoint=True)
67
+ data_P["cp"] = np.interp(data_P["ws"], ws, cp, left=0, right=0)
68
+ data_P["P"] = 0.5 * rho * A * data_P["cp"] * data_P["ws"]**3 / FC.P_UNITS[P_unit]
59
69
 
60
- super().__init__(data, col_ws=col_ws, col_P="P", rho=rho, **pars)
70
+ super().__init__(data_P, col_ws="ws", col_P="P", rho=rho, P_unit=P_unit, **pars)
@@ -66,14 +66,24 @@ class CpCtFromTwo(PCtFromTwo):
66
66
  A = np.pi * (D / 2) ** 2
67
67
  ws = data_cp[col_ws_cp_file].to_numpy()
68
68
  cp = data_cp[col_cp].to_numpy()
69
- data_cp["P"] = 0.5 * rho * A * cp * ws**3 / FC.P_UNITS[FC.kW]
69
+ P_unit = pars.pop("P_unit", FC.kW)
70
+
71
+ ws_delta = 0.0001
72
+ ws_min = np.min(ws)
73
+ ws_max = np.max(ws)
74
+ N = int((ws_max - ws_min)/ws_delta)
75
+
76
+ data_P = pd.DataFrame(index=range(N), dtype=FC.DTYPE)
77
+ data_P["ws"] = np.linspace(ws_min, ws_max, N, endpoint=True)
78
+ data_P["cp"] = np.interp(data_P["ws"], ws, cp, left=0, right=0)
79
+ data_P["P"] = 0.5 * rho * A * data_P["cp"] * data_P["ws"]**3 / FC.P_UNITS[P_unit]
70
80
 
71
81
  super().__init__(
72
- data_cp,
82
+ data_P,
73
83
  data_ct,
74
- col_ws_P_file=col_ws_cp_file,
84
+ col_ws_P_file="ws",
75
85
  col_P="P",
76
86
  rho=rho,
77
- P_unit=FC.kW,
87
+ P_unit=P_unit,
78
88
  **pars,
79
89
  )
@@ -8,10 +8,32 @@ class ABLLogNeutralWsProfile(VerticalProfile):
8
8
  """
9
9
  The neutral ABL wind speed log profile.
10
10
 
11
+ Attributes
12
+ ----------
13
+ ustar_input: bool
14
+ Flag for using ustar as an input
15
+
11
16
  :group: models.vertical_profiles
12
17
 
13
18
  """
14
19
 
20
+ def __init__(self, *args, ustar_input=False, **kwargs):
21
+ """
22
+ Constructor.
23
+
24
+ Parameters
25
+ ----------
26
+ args: tuple, optional
27
+ Additional arguments for VerticalProfile
28
+ ustar_input: bool
29
+ Flag for using ustar as an input
30
+ kwargs: dict, optional
31
+ Additional arguments for VerticalProfile
32
+
33
+ """
34
+ super().__init__(*args, **kwargs)
35
+ self.ustar_input = ustar_input
36
+
15
37
  def input_vars(self):
16
38
  """
17
39
  The input variables needed for the profile
@@ -23,7 +45,10 @@ class ABLLogNeutralWsProfile(VerticalProfile):
23
45
  The variable names
24
46
 
25
47
  """
26
- return [FV.WS, FV.H, FV.Z0]
48
+ if self.ustar_input:
49
+ return [FV.USTAR, FV.Z0]
50
+ else:
51
+ return [FV.WS, FV.H, FV.Z0]
27
52
 
28
53
  def calculate(self, data, heights):
29
54
  """
@@ -44,9 +69,11 @@ class ABLLogNeutralWsProfile(VerticalProfile):
44
69
 
45
70
  """
46
71
  z0 = data[FV.Z0]
47
- h0 = data[FV.H]
48
- ws = data[FV.WS]
49
-
50
- ustar = neutral.ustar(ws, h0, z0, kappa=FC.KAPPA)
72
+ if self.ustar_input:
73
+ ustar = data[FV.USTAR]
74
+ else:
75
+ h0 = data[FV.H]
76
+ ws = data[FV.WS]
77
+ ustar = neutral.ustar(ws, h0, z0, kappa=FC.KAPPA)
51
78
 
52
79
  return neutral.calc_ws(heights, z0, ustar, kappa=FC.KAPPA)
@@ -8,10 +8,32 @@ class ABLLogStableWsProfile(VerticalProfile):
8
8
  """
9
9
  The stable ABL wind speed log profile.
10
10
 
11
+ Attributes
12
+ ----------
13
+ ustar_input: bool
14
+ Flag for using ustar as an input
15
+
11
16
  :group: models.vertical_profiles
12
17
 
13
18
  """
14
19
 
20
+ def __init__(self, *args, ustar_input=False, **kwargs):
21
+ """
22
+ Constructor.
23
+
24
+ Parameters
25
+ ----------
26
+ args: tuple, optional
27
+ Additional arguments for VerticalProfile
28
+ ustar_input: bool
29
+ Flag for using ustar as an input
30
+ kwargs: dict, optional
31
+ Additional arguments for VerticalProfile
32
+
33
+ """
34
+ super().__init__(*args, **kwargs)
35
+ self.ustar_input = ustar_input
36
+
15
37
  def input_vars(self):
16
38
  """
17
39
  The input variables needed for the profile
@@ -23,7 +45,10 @@ class ABLLogStableWsProfile(VerticalProfile):
23
45
  The variable names
24
46
 
25
47
  """
26
- return [FV.WS, FV.H, FV.Z0, FV.MOL]
48
+ if self.ustar_input:
49
+ return [FV.USTAR, FV.Z0, FV.MOL]
50
+ else:
51
+ return [FV.WS, FV.H, FV.Z0, FV.MOL]
27
52
 
28
53
  def calculate(self, data, heights):
29
54
  """
@@ -43,12 +68,15 @@ class ABLLogStableWsProfile(VerticalProfile):
43
68
  shape as heights
44
69
 
45
70
  """
46
- ws = data[FV.WS]
47
- h0 = data[FV.H]
48
71
  z0 = data[FV.Z0]
49
72
  mol = data[FV.MOL]
50
73
 
51
- ustar = stable.ustar(ws, h0, z0, mol, kappa=FC.KAPPA)
74
+ if self.ustar_input:
75
+ ustar = data[FV.USTAR]
76
+ else:
77
+ ws = data[FV.WS]
78
+ h0 = data[FV.H]
79
+ ustar = stable.ustar(ws, h0, z0, mol, kappa=FC.KAPPA)
52
80
  psi = stable.psi(heights, mol)
53
81
 
54
82
  return stable.calc_ws(heights, z0, ustar, psi, kappa=FC.KAPPA)
@@ -8,10 +8,32 @@ class ABLLogUnstableWsProfile(VerticalProfile):
8
8
  """
9
9
  The unstable ABL wind speed log profile.
10
10
 
11
+ Attributes
12
+ ----------
13
+ ustar_input: bool
14
+ Flag for using ustar as an input
15
+
11
16
  :group: models.vertical_profiles
12
17
 
13
18
  """
14
19
 
20
+ def __init__(self, *args, ustar_input=False, **kwargs):
21
+ """
22
+ Constructor.
23
+
24
+ Parameters
25
+ ----------
26
+ args: tuple, optional
27
+ Additional arguments for VerticalProfile
28
+ ustar_input: bool
29
+ Flag for using ustar as an input
30
+ kwargs: dict, optional
31
+ Additional arguments for VerticalProfile
32
+
33
+ """
34
+ super().__init__(*args, **kwargs)
35
+ self.ustar_input = ustar_input
36
+
15
37
  def input_vars(self):
16
38
  """
17
39
  The input variables needed for the profile
@@ -23,7 +45,10 @@ class ABLLogUnstableWsProfile(VerticalProfile):
23
45
  The variable names
24
46
 
25
47
  """
26
- return [FV.WS, FV.H, FV.Z0, FV.MOL]
48
+ if self.ustar_input:
49
+ return [FV.USTAR, FV.Z0, FV.MOL]
50
+ else:
51
+ return [FV.WS, FV.H, FV.Z0, FV.MOL]
27
52
 
28
53
  def calculate(self, data, heights):
29
54
  """
@@ -43,12 +68,15 @@ class ABLLogUnstableWsProfile(VerticalProfile):
43
68
  shape as heights
44
69
 
45
70
  """
46
- ws = data[FV.WS]
47
- h0 = data[FV.H]
48
71
  z0 = data[FV.Z0]
49
72
  mol = data[FV.MOL]
50
73
 
51
- ustar = unstable.ustar(ws, h0, z0, mol, kappa=FC.KAPPA)
74
+ if self.ustar_input:
75
+ ustar = data[FV.USTAR]
76
+ else:
77
+ ws = data[FV.WS]
78
+ h0 = data[FV.H]
79
+ ustar = unstable.ustar(ws, h0, z0, mol, kappa=FC.KAPPA)
52
80
  psi = unstable.psi(heights, mol)
53
81
 
54
82
  return unstable.calc_ws(heights, z0, ustar, psi, kappa=FC.KAPPA)