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
@@ -13,10 +13,32 @@ class ABLLogWsProfile(VerticalProfile):
13
13
  This profile picks the profile according to the mol value
14
14
  (neutral: mol = None or mol = 0)
15
15
 
16
+ Attributes
17
+ ----------
18
+ ustar_input: bool
19
+ Flag for using ustar as an input
20
+
16
21
  :group: models.vertical_profiles
17
22
 
18
23
  """
19
24
 
25
+ def __init__(self, *args, ustar_input=False, **kwargs):
26
+ """
27
+ Constructor.
28
+
29
+ Parameters
30
+ ----------
31
+ args: tuple, optional
32
+ Additional arguments for VerticalProfile
33
+ ustar_input: bool
34
+ Flag for using ustar as an input
35
+ kwargs: dict, optional
36
+ Additional arguments for VerticalProfile
37
+
38
+ """
39
+ super().__init__(*args, **kwargs)
40
+ self.ustar_input = ustar_input
41
+
20
42
  def input_vars(self):
21
43
  """
22
44
  The input variables needed for the profile
@@ -28,7 +50,10 @@ class ABLLogWsProfile(VerticalProfile):
28
50
  The variable names
29
51
 
30
52
  """
31
- return [FV.WS, FV.H, FV.Z0, FV.MOL]
53
+ if self.ustar_input:
54
+ return [FV.USTAR, FV.Z0, FV.MOL]
55
+ else:
56
+ return [FV.WS, FV.H, FV.Z0, FV.MOL]
32
57
 
33
58
  def calculate(self, data, heights):
34
59
  """
@@ -48,52 +73,59 @@ class ABLLogWsProfile(VerticalProfile):
48
73
  shape as heights
49
74
 
50
75
  """
51
- ws = np.zeros_like(heights)
52
- ws[:] = data[FV.WS]
53
-
54
- h0 = np.zeros_like(heights)
55
- h0[:] = data[FV.H]
56
76
 
57
77
  z0 = np.zeros_like(heights)
58
78
  z0[:] = data[FV.Z0]
59
79
 
60
80
  mol = np.zeros_like(heights)
61
81
  mol[:] = data[FV.MOL]
82
+
83
+ if self.ustar_input:
84
+ ustar = data[FV.USTAR]
85
+ else:
86
+ ws = np.zeros_like(heights)
87
+ ws[:] = data[FV.WS]
88
+
89
+ h0 = np.zeros_like(heights)
90
+ h0[:] = data[FV.H]
62
91
 
63
92
  out = np.zeros_like(heights)
64
93
 
65
94
  # neutral profiles:
66
95
  sel = np.isnan(mol) | (mol == 0.0)
67
96
  if np.any(sel):
68
- sws = ws[sel]
69
- sh0 = h0[sel]
70
97
  sz0 = z0[sel]
71
98
  sh = heights[sel]
72
- ustar = abl.neutral.ustar(sws, sh0, sz0, kappa=FC.KAPPA)
73
- out[sel] = abl.neutral.calc_ws(sh, sz0, ustar, kappa=FC.KAPPA)
99
+ if self.ustar_input:
100
+ sus = ustar[sel]
101
+ else:
102
+ sus = abl.neutral.ustar(ws[sel], h0[sel], sz0, kappa=FC.KAPPA)
103
+ out[sel] = abl.neutral.calc_ws(sh, sz0, sus, kappa=FC.KAPPA)
74
104
 
75
105
  # stable profiles:
76
106
  sel = mol > 0.0
77
107
  if np.any(sel):
78
- sws = ws[sel]
79
- sh0 = h0[sel]
80
108
  sz0 = z0[sel]
81
109
  smo = mol[sel]
82
110
  sh = heights[sel]
83
- ustar = abl.stable.ustar(sws, sh0, sz0, smo, kappa=FC.KAPPA)
111
+ if self.ustar_input:
112
+ sus = ustar[sel]
113
+ else:
114
+ sus = abl.stable.ustar(ws[sel], h0[sel], sz0, smo, kappa=FC.KAPPA)
84
115
  psi = abl.stable.psi(sh, smo)
85
- out[sel] = abl.stable.calc_ws(sh, sz0, ustar, psi, kappa=FC.KAPPA)
116
+ out[sel] = abl.stable.calc_ws(sh, sz0, sus, psi, kappa=FC.KAPPA)
86
117
 
87
118
  # unstable profiles:
88
119
  sel = mol < 0.0
89
120
  if np.any(sel):
90
- sws = ws[sel]
91
- sh0 = h0[sel]
92
121
  sz0 = z0[sel]
93
122
  smo = mol[sel]
94
123
  sh = heights[sel]
95
- ustar = abl.unstable.ustar(sws, sh0, sz0, smo, kappa=FC.KAPPA)
124
+ if self.ustar_input:
125
+ sus = ustar[sel]
126
+ else:
127
+ sus = abl.unstable.ustar(ws[sel], h0[sel], sz0, smo, kappa=FC.KAPPA)
96
128
  psi = abl.unstable.psi(sh, smo)
97
- out[sel] = abl.unstable.calc_ws(sh, sz0, ustar, psi, kappa=FC.KAPPA)
129
+ out[sel] = abl.unstable.calc_ws(sh, sz0, sus, psi, kappa=FC.KAPPA)
98
130
 
99
131
  return out
@@ -1,7 +1,7 @@
1
1
  import numpy as np
2
2
 
3
3
  from foxes.core import WakeFrame
4
- from foxes.models.wake_models.wind.porte_agel import PorteAgelModel
4
+ from foxes.models.wake_models.wind.bastankhah16 import Bastankhah2016Model
5
5
  import foxes.variables as FV
6
6
  import foxes.constants as FC
7
7
  from .rotor_wd import RotorWD
@@ -9,13 +9,19 @@ from .rotor_wd import RotorWD
9
9
 
10
10
  class YawedWakes(WakeFrame):
11
11
  """
12
- Bend the wakes for yawed turbines.
12
+ Bend the wakes for yawed turbines, based on the
13
+ Bastankhah 2016 wake model
13
14
 
14
- Based on Bastankhah & Porte-Agel, 2016, https://doi.org/10.1017/jfm.2016.595
15
+ Notes
16
+ -----
17
+ Reference:
18
+ "Experimental and theoretical study of wind turbine wakes in yawed conditions"
19
+ Majid Bastankhah, Fernando Porté-Agel
20
+ https://doi.org/10.1017/jfm.2016.595
15
21
 
16
22
  Attributes
17
23
  ----------
18
- model: PorteAgelModel
24
+ model: Bastankhah2016Model
19
25
  The model for computing common data
20
26
  K: float
21
27
  The wake growth parameter k. If not given here
@@ -65,7 +71,7 @@ class YawedWakes(WakeFrame):
65
71
  super().__init__()
66
72
 
67
73
  self.base_frame = base_frame
68
- self.model = PorteAgelModel(ct_max, alpha, beta)
74
+ self.model = Bastankhah2016Model(ct_max, alpha, beta)
69
75
  self.k_var = k_var
70
76
 
71
77
  setattr(self, k_var, k)
@@ -143,20 +149,20 @@ class YawedWakes(WakeFrame):
143
149
  )
144
150
 
145
151
  # select targets:
146
- sp_sel = self.model.get_data(PorteAgelModel.SP_SEL, mdata)
152
+ sp_sel = self.model.get_data(Bastankhah2016Model.SP_SEL, mdata)
147
153
  if np.any(sp_sel):
148
154
  # prepare:
149
155
  n_sp_sel = np.sum(sp_sel)
150
156
  ydef = np.zeros((n_sp_sel,), dtype=FC.DTYPE)
151
157
 
152
158
  # collect data:
153
- near = self.model.get_data(PorteAgelModel.NEAR, mdata)
159
+ near = self.model.get_data(Bastankhah2016Model.NEAR, mdata)
154
160
  far = ~near
155
161
 
156
162
  # near wake:
157
163
  if np.any(near):
158
164
  # collect data:
159
- delta = self.model.get_data(PorteAgelModel.DELTA_NEAR, mdata)
165
+ delta = self.model.get_data(Bastankhah2016Model.DELTA_NEAR, mdata)
160
166
 
161
167
  # set deflection:
162
168
  ydef[near] = delta
@@ -164,7 +170,7 @@ class YawedWakes(WakeFrame):
164
170
  # far wake:
165
171
  if np.any(far):
166
172
  # collect data:
167
- delta = self.model.get_data(PorteAgelModel.DELTA_FAR, mdata)
173
+ delta = self.model.get_data(Bastankhah2016Model.DELTA_FAR, mdata)
168
174
 
169
175
  # set deflection:
170
176
  ydef[far] = delta
@@ -2,4 +2,4 @@
2
2
  Induction wake models
3
3
  """
4
4
 
5
- from .rankine_half_body import RHB
5
+ from .rankine_half_body import RankineHalfBody
@@ -6,7 +6,7 @@ import foxes.variables as FV
6
6
  import foxes.constants as FC
7
7
 
8
8
 
9
- class RHB(WakeModel):
9
+ class RankineHalfBody(WakeModel):
10
10
  """
11
11
  The Rankine half body induction wake model
12
12
 
@@ -18,11 +18,27 @@ class RHB(WakeModel):
18
18
 
19
19
  https://www.fnc.co.uk/media/o5eosxas/a-potential-flow-model-for-wind-turbine-induction-and-wind-farm-blockage.pdf
20
20
 
21
+ Attributes
22
+ ----------
23
+ ct_max: float
24
+ The maximal value for ct, values beyond will be limited
25
+ to this number
26
+
21
27
  :group: models.wake_models.induction
22
28
 
23
29
  """
24
30
 
25
31
  def __init__(self, ct_max=0.9999):
32
+ """
33
+ Constructor.
34
+
35
+ Parameters
36
+ ----------
37
+ ct_max: float
38
+ The maximal value for ct, values beyond will be limited
39
+ to this number
40
+
41
+ """
26
42
  super().__init__()
27
43
  self.ct_max = ct_max
28
44
 
@@ -157,17 +173,28 @@ class RHB(WakeModel):
157
173
  # stagnation point condition
158
174
  xs = -np.sqrt(m / (4 * ws))
159
175
 
160
- # select targets
161
- sp_sel = (ct > 0) & ((RHB_shape <= -1) | (x < xs))
176
+ # set values out of body shape
177
+ sp_sel = (ct > 0) & ((RHB_shape < -1) | (x < xs))
162
178
  if np.any(sp_sel):
163
179
  # apply selection
164
- xyz = wake_coos[sp_sel]
180
+ xyz = wake_coos[sp_sel]
165
181
 
166
182
  # calc velocity components
167
183
  vel_factor = m[sp_sel] / (4 * np.linalg.norm(xyz, axis=-1) ** 3)
168
184
  wake_deltas["U"][sp_sel] += vel_factor * xyz[:, 0]
169
185
  wake_deltas["V"][sp_sel] += vel_factor * xyz[:, 1]
170
186
 
187
+ # set values inside body shape
188
+ sp_sel = (ct > 0) & (RHB_shape >= -1) & (x >= xs) & (x < 0)
189
+ if np.any(sp_sel):
190
+ # apply selection
191
+ xyz = np.zeros_like(wake_coos[sp_sel])
192
+ xyz[:, 0] = xs[sp_sel]
193
+
194
+ # calc velocity components
195
+ vel_factor = m[sp_sel] / (4 * np.linalg.norm(xyz, axis=-1) ** 3)
196
+ wake_deltas["U"][sp_sel] += vel_factor * xyz[:, 0]
197
+
171
198
  return wake_deltas
172
199
 
173
200
  def finalize_wake_deltas(
@@ -212,9 +239,8 @@ class RHB(WakeModel):
212
239
 
213
240
  # add ambient result to wake deltas
214
241
  delta_uv = np.stack((wake_deltas["U"], wake_deltas["V"]), axis=2)
215
- sel = np.linalg.norm(delta_uv, axis=-1) < ws0
216
- wind_vec[sel] += delta_uv[sel]
217
- del delta_uv, sel, ws0
242
+ wind_vec += delta_uv
243
+ del delta_uv, ws0
218
244
 
219
245
  # deduce WS and WD deltas:
220
246
  new_wd = uv2wd(wind_vec)
@@ -9,7 +9,12 @@ class CrespoHernandezTIWake(TopHatWakeModel):
9
9
  """
10
10
  The Crespo and Hernandez TI empirical correlation
11
11
 
12
- Source: https://doi.org/10.1016/0167-6105(95)00033-X
12
+ Notes
13
+ -----
14
+ Reference:
15
+ "Turbulence characteristics in wind-turbine wakes"
16
+ A. Crespo, J. Hernandez
17
+ https://doi.org/10.1016/0167-6105(95)00033-X
13
18
 
14
19
  For the wake diameter we use Eqns. (17), (15), (4), (5) from
15
20
  doi:10.1088/1742-6596/625/1/012039
@@ -9,13 +9,15 @@ class IECTIWake(TopHatWakeModel):
9
9
  """
10
10
  The TI wake model from IEC-64100-1-2005-8 (2005):
11
11
 
12
- source: http://orbit.dtu.dk/files/3750291/2009_31.pdf
12
+ Notes
13
+ -----
14
+ Reference:
15
+ http://orbit.dtu.dk/files/3750291/2009_31.pdf
13
16
  v2: VolLuk: corrected implementation following: IEC-64100-1-2005-8
14
17
  (Appearently an error in the document by DTU)
15
18
 
16
19
  and the Frandsen wake TI model, from IEC-64100 (2019):
17
-
18
- Source: http://orbit.dtu.dk/files/3750291/2009_31.pdf
20
+ http://orbit.dtu.dk/files/3750291/2009_31.pdf
19
21
 
20
22
  Attributes
21
23
  ----------
@@ -2,6 +2,6 @@
2
2
  Wind deficit wake models.
3
3
  """
4
4
  from .jensen import JensenWake
5
- from .bastankhah import BastankhahWake
5
+ from .bastankhah14 import Bastankhah2014
6
+ from .bastankhah16 import Bastankhah2016Model, Bastankhah2016
6
7
  from .turbopark import TurbOParkWake, TurbOParkWakeIX
7
- from .porte_agel import PorteAgelModel, PorteAgelWake
@@ -5,14 +5,16 @@ import foxes.variables as FV
5
5
  import foxes.constants as FC
6
6
 
7
7
 
8
- class BastankhahWake(GaussianWakeModel):
8
+ class Bastankhah2014(GaussianWakeModel):
9
9
  """
10
- The Bastankhah wake model
10
+ The Bastankhah 2014 wake model
11
11
 
12
- (https://doi.org/10.1016/j.renene.2014.01.002)
13
- Modifications: In the calculation of the initial wake radius
14
- a constant of 0.25 instead of 0.2 is used as it fits better
15
- to the validation data
12
+ Notes
13
+ -----
14
+ Reference:
15
+ "A new analytical model for wind-turbine wakes"
16
+ Majid Bastankhah, Fernando Porté-Agel
17
+ https://doi.org/10.1016/j.renene.2014.01.002
16
18
 
17
19
  Attributes
18
20
  ----------
@@ -32,7 +34,7 @@ class BastankhahWake(GaussianWakeModel):
32
34
  """
33
35
 
34
36
  def __init__(
35
- self, superposition, k=None, sbeta_factor=0.25, ct_max=0.9999, k_var=FV.K
37
+ self, superposition, k=None, sbeta_factor=0.2, ct_max=0.9999, k_var=FV.K
36
38
  ):
37
39
  """
38
40
  Constructor.
@@ -188,13 +190,8 @@ class BastankhahWake(GaussianWakeModel):
188
190
  del x, k, sbeta, sblim
189
191
 
190
192
  # calculate amplitude:
191
- if self.sbeta_factor < 0.25:
192
- radicant = 1.0 - ct / (8 * (sigma / D) ** 2)
193
- reals = radicant >= 0
194
- ampld = -np.ones_like(radicant)
195
- ampld[reals] = np.sqrt(radicant[reals]) - 1.0
196
- else:
197
- ampld = np.sqrt(1.0 - ct / (8 * (sigma / D) ** 2)) - 1.0
193
+ term = 1.0 - ct / (8 * (sigma / D) ** 2)
194
+ ampld = np.sqrt(np.where(term > 0, term, 0)) - 1
198
195
 
199
196
  # case no targets:
200
197
  else:
@@ -6,12 +6,16 @@ import foxes.variables as FV
6
6
  import foxes.constants as FC
7
7
 
8
8
 
9
- class PorteAgelModel(Model):
9
+ class Bastankhah2016Model(Model):
10
10
  """
11
11
  Common calculations for the wake model and the wake
12
12
  frame, such that code repetitions can be avoided.
13
13
 
14
- Based on Bastankhah & Porte-Agel, 2016,
14
+ Notes
15
+ -----
16
+ Reference:
17
+ "Experimental and theoretical study of wind turbine wakes in yawed conditions"
18
+ Majid Bastankhah, Fernando Porté-Agel
15
19
  https://doi.org/10.1017/jfm.2016.595
16
20
 
17
21
  Attributes
@@ -28,7 +32,7 @@ class PorteAgelModel(Model):
28
32
 
29
33
  """
30
34
 
31
- MDATA_KEY = "PorteAgelModel"
35
+ MDATA_KEY = "Bastankhah2016Model"
32
36
  PARS = "pars"
33
37
  CHECK = "check"
34
38
  SP_SEL = "sp_sel"
@@ -355,16 +359,20 @@ class PorteAgelModel(Model):
355
359
  del mdata[self.MDATA_KEY]
356
360
 
357
361
 
358
- class PorteAgelWake(DistSlicedWakeModel):
362
+ class Bastankhah2016(DistSlicedWakeModel):
359
363
  """
360
- The Bastankhah PorteAgel wake model
364
+ The Bastankhah 2016 wake model
361
365
 
362
- Based on Bastankhah & Porte-Agel, 2016,
366
+ Notes
367
+ -----
368
+ Reference:
369
+ "Experimental and theoretical study of wind turbine wakes in yawed conditions"
370
+ Majid Bastankhah, Fernando Porté-Agel
363
371
  https://doi.org/10.1017/jfm.2016.595
364
372
 
365
373
  Attributes
366
374
  ----------
367
- model: PorteAgelModel
375
+ model: Bastankhah2016Model
368
376
  The model for computing common data
369
377
  K: float
370
378
  The wake growth parameter k. If not given here
@@ -413,7 +421,7 @@ class PorteAgelWake(DistSlicedWakeModel):
413
421
  """
414
422
  super().__init__(superpositions={FV.WS: superposition})
415
423
 
416
- self.model = PorteAgelModel(ct_max, alpha, beta)
424
+ self.model = Bastankhah2016Model(ct_max, alpha, beta)
417
425
  self.k_var = k_var
418
426
 
419
427
  setattr(self, k_var, k)
@@ -533,7 +541,7 @@ class PorteAgelWake(DistSlicedWakeModel):
533
541
  )
534
542
 
535
543
  # select targets:
536
- sp_sel = self.model.get_data(PorteAgelModel.SP_SEL, mdata)
544
+ sp_sel = self.model.get_data(Bastankhah2016Model.SP_SEL, mdata)
537
545
  n_sp_sel = np.sum(sp_sel)
538
546
  wdeltas = {FV.WS: np.zeros((n_sp_sel, n_y_per_z), dtype=FC.DTYPE)}
539
547
  if np.any(sp_sel):
@@ -541,15 +549,15 @@ class PorteAgelWake(DistSlicedWakeModel):
541
549
  yz = yz[sp_sel]
542
550
 
543
551
  # collect data:
544
- near = self.model.get_data(PorteAgelModel.NEAR, mdata)
552
+ near = self.model.get_data(Bastankhah2016Model.NEAR, mdata)
545
553
  far = ~near
546
554
 
547
555
  # near wake:
548
556
  if np.any(near):
549
557
  # collect data:
550
- ampl = self.model.get_data(PorteAgelModel.AMPL_NEAR, mdata)
551
- r_pc = self.model.get_data(PorteAgelModel.R_PC, mdata)
552
- s = self.model.get_data(PorteAgelModel.R_PC_S, mdata)
558
+ ampl = self.model.get_data(Bastankhah2016Model.AMPL_NEAR, mdata)
559
+ r_pc = self.model.get_data(Bastankhah2016Model.R_PC, mdata)
560
+ s = self.model.get_data(Bastankhah2016Model.R_PC_S, mdata)
553
561
 
554
562
  # radial dependency:
555
563
  r = np.linalg.norm(yz[near], axis=-1)
@@ -569,11 +577,11 @@ class PorteAgelWake(DistSlicedWakeModel):
569
577
  yz = yz[far]
570
578
 
571
579
  # collect data:
572
- ampl = self.model.get_data(PorteAgelModel.AMPL_FAR, mdata)[:, None]
573
- sigma_y = self.model.get_data(PorteAgelModel.SIGMA_Y_FAR, mdata)[
580
+ ampl = self.model.get_data(Bastankhah2016Model.AMPL_FAR, mdata)[:, None]
581
+ sigma_y = self.model.get_data(Bastankhah2016Model.SIGMA_Y_FAR, mdata)[
574
582
  :, None
575
583
  ]
576
- sigma_z = self.model.get_data(PorteAgelModel.SIGMA_Z_FAR, mdata)[
584
+ sigma_z = self.model.get_data(Bastankhah2016Model.SIGMA_Z_FAR, mdata)[
577
585
  :, None
578
586
  ]
579
587
 
@@ -9,6 +9,11 @@ class TurbOParkWake(GaussianWakeModel):
9
9
  """
10
10
  The TurbOPark wake model
11
11
 
12
+ Notes
13
+ -----
14
+ Reference:
15
+ "Turbulence Optimized Park model with Gaussian wake profile"
16
+ J G Pedersen, E Svensson, L Poulsen and N G Nygaard
12
17
  https://iopscience.iop.org/article/10.1088/1742-6596/2265/2/022063/pdf
13
18
 
14
19
  Attributes
@@ -181,8 +186,6 @@ class TurbOParkWake(GaussianWakeModel):
181
186
 
182
187
  # calculate sigma:
183
188
  sbeta = np.sqrt(0.5 * (1 + np.sqrt(1.0 - ct)) / np.sqrt(1.0 - ct))
184
- # sblim = 1 / (np.sqrt(8) * self.sbeta_factor)
185
- # sbeta[sbeta > sblim] = sblim
186
189
  epsilon = self.sbeta_factor * sbeta
187
190
 
188
191
  alpha = self.c1 * ati
@@ -208,20 +211,14 @@ class TurbOParkWake(GaussianWakeModel):
208
211
  del (
209
212
  x,
210
213
  sbeta,
211
- # sblim,
212
214
  alpha,
213
215
  beta,
214
216
  epsilon,
215
217
  )
216
218
 
217
- # calculate amplitude, same as in Bastankha model (eqn 7)
218
- if self.sbeta_factor < 0.25:
219
- radicant = 1.0 - ct / (8 * (sigma / D) ** 2)
220
- reals = radicant >= 0
221
- ampld = -np.ones_like(radicant)
222
- ampld[reals] = np.sqrt(radicant[reals]) - 1.0
223
- else:
224
- ampld = np.sqrt(1.0 - ct / (8 * (sigma / D) ** 2)) - 1.0
219
+ # calculate amplitude, same as in Bastankhah model (eqn 7)
220
+ term = 1.0 - ct / (8 * (sigma / D) ** 2)
221
+ ampld = np.sqrt(np.where(term > 0, term, 0)) - 1
225
222
 
226
223
  # case no targets:
227
224
  else:
@@ -428,8 +425,6 @@ class TurbOParkWakeIX(GaussianWakeModel):
428
425
 
429
426
  # calculate sigma:
430
427
  sbeta = np.sqrt(0.5 * (1 + np.sqrt(1.0 - ct)) / np.sqrt(1.0 - ct))
431
- # sblim = 1 / (np.sqrt(8) * self.sbeta_factor)
432
- # sbeta[sbeta > sblim] = sblim
433
428
  epsilon = self.sbeta_factor * sbeta
434
429
 
435
430
  # get TI by integration along centre line:
@@ -452,18 +447,12 @@ class TurbOParkWakeIX(GaussianWakeModel):
452
447
  del (
453
448
  x,
454
449
  sbeta,
455
- # sblim,
456
450
  epsilon,
457
451
  )
458
452
 
459
- # calculate amplitude, same as in Bastankha model (eqn 7)
460
- if self.sbeta_factor < 0.25:
461
- radicant = 1.0 - ct / (8 * (sigma / D) ** 2)
462
- reals = radicant >= 0
463
- ampld = -np.ones_like(radicant)
464
- ampld[reals] = np.sqrt(radicant[reals]) - 1.0
465
- else:
466
- ampld = np.sqrt(1.0 - ct / (8 * (sigma / D) ** 2)) - 1.0
453
+ # calculate amplitude, same as in Bastankhah model (eqn 7)
454
+ term = 1.0 - ct / (8 * (sigma / D) ** 2)
455
+ ampld = np.sqrt(np.where(term > 0, term, 0)) - 1
467
456
 
468
457
  # case no targets:
469
458
  else:
@@ -1,8 +1,12 @@
1
1
  """
2
2
  Wake superposition models.
3
3
  """
4
- from .linear import LinearSuperposition
5
- from .quadratic import QuadraticSuperposition
6
- from .max import MaxSuperposition
7
- from .product import ProductSuperposition
8
- from .ti_superp import TISuperposition
4
+ from .ws_linear import WSLinear
5
+ from .ws_quadratic import WSQuadratic
6
+ from .ws_pow import WSPow
7
+ from .ws_max import WSMax
8
+ from .ws_product import WSProduct
9
+ from .ti_linear import TILinear
10
+ from .ti_quadratic import TIQuadratic
11
+ from .ti_pow import TIPow
12
+ from .ti_max import TIMax