foxes 0.6.1__py3-none-any.whl → 0.7__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 (129) hide show
  1. foxes/VERSION +1 -1
  2. foxes/algorithms/downwind/downwind.py +131 -65
  3. foxes/algorithms/downwind/models/__init__.py +2 -1
  4. foxes/algorithms/downwind/models/farm_wakes_calc.py +87 -55
  5. foxes/algorithms/downwind/models/init_farm_data.py +134 -0
  6. foxes/algorithms/downwind/models/point_wakes_calc.py +54 -65
  7. foxes/algorithms/downwind/models/{calc_order.py → reorder_farm_output.py} +28 -26
  8. foxes/algorithms/iterative/iterative.py +100 -51
  9. foxes/algorithms/iterative/models/convergence.py +3 -3
  10. foxes/algorithms/iterative/models/farm_wakes_calc.py +55 -48
  11. foxes/algorithms/sequential/models/seq_state.py +7 -6
  12. foxes/algorithms/sequential/sequential.py +81 -44
  13. foxes/constants.py +33 -18
  14. foxes/core/__init__.py +2 -2
  15. foxes/core/algorithm.py +31 -12
  16. foxes/core/data.py +335 -41
  17. foxes/core/data_calc_model.py +27 -23
  18. foxes/core/farm_controller.py +27 -28
  19. foxes/core/farm_data_model.py +26 -4
  20. foxes/core/model.py +186 -129
  21. foxes/core/partial_wakes_model.py +84 -81
  22. foxes/core/point_data_model.py +51 -18
  23. foxes/core/rotor_model.py +59 -77
  24. foxes/core/states.py +6 -6
  25. foxes/core/turbine_model.py +4 -4
  26. foxes/core/turbine_type.py +24 -0
  27. foxes/core/vertical_profile.py +3 -3
  28. foxes/core/wake_frame.py +91 -50
  29. foxes/core/wake_model.py +74 -43
  30. foxes/core/wake_superposition.py +29 -26
  31. foxes/input/farm_layout/__init__.py +1 -0
  32. foxes/input/farm_layout/from_random.py +49 -0
  33. foxes/input/states/__init__.py +1 -1
  34. foxes/input/states/create/__init__.py +1 -0
  35. foxes/input/states/create/random_abl_states.py +6 -2
  36. foxes/input/states/create/random_timeseries.py +56 -0
  37. foxes/input/states/field_data_nc.py +12 -8
  38. foxes/input/states/multi_height.py +24 -14
  39. foxes/input/states/scan_ws.py +13 -17
  40. foxes/input/states/single.py +28 -20
  41. foxes/input/states/states_table.py +22 -18
  42. foxes/models/axial_induction_models/betz.py +1 -1
  43. foxes/models/farm_models/turbine2farm.py +2 -2
  44. foxes/models/model_book.py +40 -14
  45. foxes/models/partial_wakes/__init__.py +2 -2
  46. foxes/models/partial_wakes/axiwake.py +73 -200
  47. foxes/models/partial_wakes/centre.py +40 -0
  48. foxes/models/partial_wakes/grid.py +7 -63
  49. foxes/models/partial_wakes/rotor_points.py +53 -147
  50. foxes/models/partial_wakes/segregated.py +158 -0
  51. foxes/models/partial_wakes/top_hat.py +88 -196
  52. foxes/models/point_models/set_uniform_data.py +4 -4
  53. foxes/models/point_models/tke2ti.py +4 -4
  54. foxes/models/point_models/wake_deltas.py +4 -4
  55. foxes/models/rotor_models/centre.py +15 -19
  56. foxes/models/rotor_models/grid.py +2 -1
  57. foxes/models/rotor_models/levels.py +2 -1
  58. foxes/models/turbine_models/__init__.py +0 -1
  59. foxes/models/turbine_models/calculator.py +11 -7
  60. foxes/models/turbine_models/kTI_model.py +13 -11
  61. foxes/models/turbine_models/lookup_table.py +22 -9
  62. foxes/models/turbine_models/power_mask.py +81 -51
  63. foxes/models/turbine_models/rotor_centre_calc.py +17 -20
  64. foxes/models/turbine_models/sector_management.py +5 -6
  65. foxes/models/turbine_models/set_farm_vars.py +49 -20
  66. foxes/models/turbine_models/table_factors.py +5 -5
  67. foxes/models/turbine_models/thrust2ct.py +9 -5
  68. foxes/models/turbine_models/yaw2yawm.py +7 -13
  69. foxes/models/turbine_models/yawm2yaw.py +7 -11
  70. foxes/models/turbine_types/PCt_file.py +84 -3
  71. foxes/models/turbine_types/PCt_from_two.py +7 -3
  72. foxes/models/turbine_types/null_type.py +2 -2
  73. foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -2
  74. foxes/models/turbine_types/wsti2PCt_from_two.py +6 -2
  75. foxes/models/wake_frames/farm_order.py +26 -22
  76. foxes/models/wake_frames/rotor_wd.py +32 -31
  77. foxes/models/wake_frames/seq_dynamic_wakes.py +112 -64
  78. foxes/models/wake_frames/streamlines.py +51 -47
  79. foxes/models/wake_frames/timelines.py +59 -47
  80. foxes/models/wake_frames/yawed_wakes.py +63 -40
  81. foxes/models/wake_models/axisymmetric.py +31 -35
  82. foxes/models/wake_models/dist_sliced.py +50 -56
  83. foxes/models/wake_models/gaussian.py +33 -35
  84. foxes/models/wake_models/induction/rankine_half_body.py +79 -87
  85. foxes/models/wake_models/induction/rathmann.py +56 -63
  86. foxes/models/wake_models/induction/self_similar.py +59 -62
  87. foxes/models/wake_models/ti/crespo_hernandez.py +83 -74
  88. foxes/models/wake_models/ti/iec_ti.py +65 -75
  89. foxes/models/wake_models/top_hat.py +60 -69
  90. foxes/models/wake_models/wake_mirror.py +49 -54
  91. foxes/models/wake_models/wind/bastankhah14.py +44 -66
  92. foxes/models/wake_models/wind/bastankhah16.py +84 -111
  93. foxes/models/wake_models/wind/jensen.py +67 -89
  94. foxes/models/wake_models/wind/turbopark.py +93 -133
  95. foxes/models/wake_superpositions/ti_linear.py +33 -27
  96. foxes/models/wake_superpositions/ti_max.py +33 -27
  97. foxes/models/wake_superpositions/ti_pow.py +35 -27
  98. foxes/models/wake_superpositions/ti_quadratic.py +33 -27
  99. foxes/models/wake_superpositions/ws_linear.py +39 -32
  100. foxes/models/wake_superpositions/ws_max.py +40 -33
  101. foxes/models/wake_superpositions/ws_pow.py +39 -32
  102. foxes/models/wake_superpositions/ws_product.py +35 -28
  103. foxes/models/wake_superpositions/ws_quadratic.py +39 -32
  104. foxes/opt/constraints/min_dist.py +1 -1
  105. foxes/opt/objectives/farm_vars.py +1 -1
  106. foxes/opt/problems/layout/farm_layout.py +38 -97
  107. foxes/output/__init__.py +1 -0
  108. foxes/output/farm_results_eval.py +1 -1
  109. foxes/output/flow_plots_2d/flow_plots.py +2 -0
  110. foxes/output/flow_plots_2d/get_fig.py +2 -0
  111. foxes/output/grids.py +1 -1
  112. foxes/output/rose_plot.py +3 -3
  113. foxes/output/rotor_point_plots.py +117 -0
  114. foxes/output/turbine_type_curves.py +2 -2
  115. foxes/utils/__init__.py +2 -1
  116. foxes/utils/load.py +29 -0
  117. foxes/utils/random_xy.py +56 -0
  118. foxes/utils/runners/runners.py +13 -1
  119. foxes/utils/windrose_plot.py +1 -1
  120. foxes/variables.py +10 -0
  121. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/METADATA +13 -7
  122. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/RECORD +126 -122
  123. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/WHEEL +1 -1
  124. foxes/models/partial_wakes/distsliced.py +0 -322
  125. foxes/models/partial_wakes/mapped.py +0 -252
  126. foxes/models/turbine_models/set_XYHD.py +0 -130
  127. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/LICENSE +0 -0
  128. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/top_level.txt +0 -0
  129. {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/zip-safe +0 -0
@@ -1,11 +1,11 @@
1
1
  import numpy as np
2
2
 
3
- from foxes.core import WakeModel
3
+ from foxes.core import TurbineInductionModel
4
4
  import foxes.variables as FV
5
5
  import foxes.constants as FC
6
6
 
7
7
 
8
- class Rathmann(WakeModel):
8
+ class Rathmann(TurbineInductionModel):
9
9
  """
10
10
  The Rathmann induction wake model
11
11
 
@@ -47,6 +47,12 @@ class Rathmann(WakeModel):
47
47
  self.induction = induction
48
48
  self.pre_rotor_only = pre_rotor_only
49
49
 
50
+ def __repr__(self):
51
+ iname = (
52
+ self.induction if isinstance(self.induction, str) else self.induction.name
53
+ )
54
+ return f"{type(self).__name__}(induction={iname})"
55
+
50
56
  def sub_models(self):
51
57
  """
52
58
  List of all sub-models
@@ -77,116 +83,105 @@ class Rathmann(WakeModel):
77
83
  self.induction = algo.mbook.axial_induction[self.induction]
78
84
  super().initialize(algo, verbosity, force)
79
85
 
80
- def init_wake_deltas(self, algo, mdata, fdata, pdata, wake_deltas):
86
+ def new_wake_deltas(self, algo, mdata, fdata, tdata):
81
87
  """
82
- Initialize wake delta storage.
83
-
84
- They are added on the fly to the wake_deltas dict.
88
+ Creates new empty wake delta arrays.
85
89
 
86
90
  Parameters
87
91
  ----------
88
92
  algo: foxes.core.Algorithm
89
93
  The calculation algorithm
90
- mdata: foxes.core.Data
94
+ mdata: foxes.core.MData
91
95
  The model data
92
- fdata: foxes.core.Data
96
+ fdata: foxes.core.FData
93
97
  The farm data
94
- pdata: foxes.core.Data
95
- The evaluation point data
98
+ tdata: foxes.core.TData
99
+ The target point data
100
+
101
+ Returns
102
+ -------
96
103
  wake_deltas: dict
97
- The wake deltas storage, add wake deltas
98
- on the fly. Keys: Variable name str, for which the
99
- wake delta applies, values: numpy.ndarray with
100
- shape (n_states, n_points, ...)
104
+ Key: variable name, value: The zero filled
105
+ wake deltas, shape: (n_states, n_turbines, n_rpoints, ...)
101
106
 
102
107
  """
103
- n_states = mdata.n_states
104
- n_points = pdata.n_points
105
- wake_deltas[FV.WS] = np.zeros((n_states, n_points), dtype=FC.DTYPE)
108
+ return {FV.WS: np.zeros_like(tdata[FC.TARGETS][..., 0])}
106
109
 
107
- def contribute_to_wake_deltas(
110
+ def contribute(
108
111
  self,
109
112
  algo,
110
113
  mdata,
111
114
  fdata,
112
- pdata,
113
- states_source_turbine,
115
+ tdata,
116
+ downwind_index,
114
117
  wake_coos,
115
118
  wake_deltas,
116
119
  ):
117
120
  """
118
- Calculate the contribution to the wake deltas
119
- by this wake model.
120
-
121
- Modifies wake_deltas on the fly.
121
+ Modifies wake deltas at target points by
122
+ contributions from the specified wake source turbines.
122
123
 
123
124
  Parameters
124
125
  ----------
125
126
  algo: foxes.core.Algorithm
126
127
  The calculation algorithm
127
- mdata: foxes.core.Data
128
+ mdata: foxes.core.MData
128
129
  The model data
129
- fdata: foxes.core.Data
130
+ fdata: foxes.core.FData
130
131
  The farm data
131
- pdata: foxes.core.Data
132
- The evaluation point data
133
- states_source_turbine: numpy.ndarray
134
- For each state, one turbine index for the
135
- wake causing turbine. Shape: (n_states,)
132
+ tdata: foxes.core.TData
133
+ The target point data
134
+ downwind_index: int
135
+ The index of the wake causing turbine
136
+ in the downwnd order
136
137
  wake_coos: numpy.ndarray
137
138
  The wake frame coordinates of the evaluation
138
- points, shape: (n_states, n_points, 3)
139
+ points, shape: (n_states, n_targets, n_tpoints, 3)
139
140
  wake_deltas: dict
140
- The wake deltas, are being modified ob the fly.
141
- Key: Variable name str, for which the
142
- wake delta applies, values: numpy.ndarray with
143
- shape (n_states, n_points, ...)
141
+ The wake deltas. Key: variable name,
142
+ value: numpy.ndarray with shape
143
+ (n_states, n_targets, n_tpoints, ...)
144
144
 
145
145
  """
146
-
147
- # get x, y and z
148
- x = wake_coos[:, :, 0]
149
- y = wake_coos[:, :, 1]
150
- z = wake_coos[:, :, 2]
151
-
152
146
  # get ct:
153
147
  ct = self.get_data(
154
148
  FV.CT,
155
- FC.STATE_POINT,
149
+ FC.STATE_TARGET_TPOINT,
156
150
  lookup="w",
157
151
  algo=algo,
158
152
  fdata=fdata,
159
- pdata=pdata,
153
+ tdata=tdata,
160
154
  upcast=True,
161
- states_source_turbine=states_source_turbine,
155
+ downwind_index=downwind_index,
162
156
  )
163
157
 
164
158
  # get ws:
165
159
  ws = self.get_data(
166
160
  FV.REWS,
167
- FC.STATE_POINT,
161
+ FC.STATE_TARGET_TPOINT,
168
162
  lookup="w",
169
163
  algo=algo,
170
164
  fdata=fdata,
171
- pdata=pdata,
165
+ tdata=tdata,
172
166
  upcast=True,
173
- states_source_turbine=states_source_turbine,
167
+ downwind_index=downwind_index,
174
168
  )
175
169
 
176
170
  # get D
177
- D = self.get_data(
171
+ R = 0.5 * self.get_data(
178
172
  FV.D,
179
- FC.STATE_POINT,
173
+ FC.STATE_TARGET_TPOINT,
180
174
  lookup="w",
181
175
  algo=algo,
182
176
  fdata=fdata,
183
- pdata=pdata,
184
- upcast=True,
185
- states_source_turbine=states_source_turbine,
177
+ tdata=tdata,
178
+ upcast=False,
179
+ downwind_index=downwind_index,
186
180
  )
187
181
 
188
- x_R = x / (D / 2)
189
- r_R = np.sqrt(y**2 + z**2) / (D / 2)
182
+ # get x, r and R etc. Rounding for safe x < 0 condition below
183
+ x_R = np.round(wake_coos[..., 0] / R, 12)
184
+ r_R = np.linalg.norm(wake_coos[..., 1:3], axis=-1) / R
190
185
 
191
186
  def mu(x_R):
192
187
  """axial shape function at r=0 from vortex cylinder model (eqn 11)"""
@@ -204,23 +199,21 @@ class Rathmann(WakeModel):
204
199
  return sin_alpha * sin_beta * (1 + x_R**2)
205
200
 
206
201
  # ws delta in front of rotor
207
- sp_sel = (ct > 0) & (x < 0)
202
+ sp_sel = (ct > 0) & (x_R <= 0)
208
203
  if np.any(sp_sel):
204
+ xr = x_R[sp_sel]
209
205
  a = self.induction.ct2a(ct[sp_sel])
210
- blockage = (
211
- ws[sp_sel] * a * mu(x_R[sp_sel]) * G(x_R[sp_sel], r_R[sp_sel])
212
- ) # eqn 10
206
+ blockage = ws[sp_sel] * a * mu(xr) * G(xr, r_R[sp_sel]) # eqn 10
213
207
  wake_deltas[FV.WS][sp_sel] += -blockage
214
208
 
215
209
  # ws delta behind rotor
216
210
  if not self.pre_rotor_only:
217
211
  # mirror -blockage in rotor plane
218
- sp_sel = (ct > 0) & (x > 0) & (r_R > 1)
212
+ sp_sel = (ct > 0) & (x_R > 0) & (r_R > 1)
219
213
  if np.any(sp_sel):
214
+ xr = x_R[sp_sel]
220
215
  a = self.induction.ct2a(ct[sp_sel])
221
- blockage = (
222
- ws[sp_sel] * a * mu(-x_R[sp_sel]) * G(-x_R[sp_sel], r_R[sp_sel])
223
- ) # eqn 10
216
+ blockage = ws[sp_sel] * a * mu(-xr) * G(-xr, r_R[sp_sel]) # eqn 10
224
217
  wake_deltas[FV.WS][sp_sel] += blockage
225
218
 
226
219
  return wake_deltas
@@ -1,11 +1,11 @@
1
1
  import numpy as np
2
2
 
3
- from foxes.core import WakeModel
3
+ from foxes.core import TurbineInductionModel
4
4
  import foxes.variables as FV
5
5
  import foxes.constants as FC
6
6
 
7
7
 
8
- class SelfSimilar(WakeModel):
8
+ class SelfSimilar(TurbineInductionModel):
9
9
  """
10
10
  The self-similar induction wake model
11
11
  from Troldborg and Meyer Forsting
@@ -38,7 +38,7 @@ class SelfSimilar(WakeModel):
38
38
 
39
39
  """
40
40
 
41
- def __init__(self, pre_rotor_only=False, induction="Madsen"):
41
+ def __init__(self, pre_rotor_only=False, induction="Madsen", gamma=1.1):
42
42
  """
43
43
  Constructor.
44
44
 
@@ -48,11 +48,20 @@ class SelfSimilar(WakeModel):
48
48
  Calculate only the pre-rotor region
49
49
  induction: foxes.core.AxialInductionModel or str
50
50
  The induction model
51
+ gamma: float, default=1.1
52
+ The parameter that multiplies Ct in the ct2a calculation
51
53
 
52
54
  """
53
55
  super().__init__()
54
56
  self.induction = induction
55
57
  self.pre_rotor_only = pre_rotor_only
58
+ self.gamma = gamma
59
+
60
+ def __repr__(self):
61
+ iname = (
62
+ self.induction if isinstance(self.induction, str) else self.induction.name
63
+ )
64
+ return f"{type(self).__name__}(gamma={self.gamma}, induction={iname})"
56
65
 
57
66
  def sub_models(self):
58
67
  """
@@ -84,40 +93,37 @@ class SelfSimilar(WakeModel):
84
93
  self.induction = algo.mbook.axial_induction[self.induction]
85
94
  super().initialize(algo, verbosity, force)
86
95
 
87
- def init_wake_deltas(self, algo, mdata, fdata, pdata, wake_deltas):
96
+ def new_wake_deltas(self, algo, mdata, fdata, tdata):
88
97
  """
89
- Initialize wake delta storage.
90
-
91
- They are added on the fly to the wake_deltas dict.
98
+ Creates new empty wake delta arrays.
92
99
 
93
100
  Parameters
94
101
  ----------
95
102
  algo: foxes.core.Algorithm
96
103
  The calculation algorithm
97
- mdata: foxes.core.Data
104
+ mdata: foxes.core.MData
98
105
  The model data
99
- fdata: foxes.core.Data
106
+ fdata: foxes.core.FData
100
107
  The farm data
101
- pdata: foxes.core.Data
102
- The evaluation point data
108
+ tdata: foxes.core.TData
109
+ The target point data
110
+
111
+ Returns
112
+ -------
103
113
  wake_deltas: dict
104
- The wake deltas storage, add wake deltas
105
- on the fly. Keys: Variable name str, for which the
106
- wake delta applies, values: numpy.ndarray with
107
- shape (n_states, n_points, ...)
114
+ Key: variable name, value: The zero filled
115
+ wake deltas, shape: (n_states, n_turbines, n_rpoints, ...)
108
116
 
109
117
  """
110
- n_states = mdata.n_states
111
- n_points = pdata.n_points
112
- wake_deltas[FV.WS] = np.zeros((n_states, n_points), dtype=FC.DTYPE)
118
+ return {FV.WS: np.zeros_like(tdata[FC.TARGETS][..., 0])}
113
119
 
114
120
  def _mu(self, x_R):
115
121
  """Helper function: define mu (eqn 11 from [1])"""
116
122
  return 1 + (x_R / np.sqrt(1 + x_R**2))
117
123
 
118
- def _a0(self, ct, x_R, gamma=1.1):
124
+ def _a0(self, ct, x_R):
119
125
  """Helper function: define a0 with gamma factor, eqn 8 from [2]"""
120
- return self.induction.ct2a(gamma * ct)
126
+ return self.induction.ct2a(self.gamma * ct)
121
127
 
122
128
  def _a(self, ct, x_R):
123
129
  """Helper function: define axial shape function (eqn 11 from [1])"""
@@ -131,93 +137,84 @@ class SelfSimilar(WakeModel):
131
137
  """Helper function: define radial shape function (eqn 12 from [1])"""
132
138
  return (1 / np.cosh(beta * (r_R) / self._r_half(x_R))) ** alpha # * (x_R < 0)
133
139
 
134
- def contribute_to_wake_deltas(
140
+ def contribute(
135
141
  self,
136
142
  algo,
137
143
  mdata,
138
144
  fdata,
139
- pdata,
140
- states_source_turbine,
145
+ tdata,
146
+ downwind_index,
141
147
  wake_coos,
142
148
  wake_deltas,
143
149
  ):
144
150
  """
145
- Calculate the contribution to the wake deltas
146
- by this wake model.
147
-
148
- Modifies wake_deltas on the fly.
151
+ Modifies wake deltas at target points by
152
+ contributions from the specified wake source turbines.
149
153
 
150
154
  Parameters
151
155
  ----------
152
156
  algo: foxes.core.Algorithm
153
157
  The calculation algorithm
154
- mdata: foxes.core.Data
158
+ mdata: foxes.core.MData
155
159
  The model data
156
- fdata: foxes.core.Data
160
+ fdata: foxes.core.FData
157
161
  The farm data
158
- pdata: foxes.core.Data
159
- The evaluation point data
160
- states_source_turbine: numpy.ndarray
161
- For each state, one turbine index for the
162
- wake causing turbine. Shape: (n_states,)
162
+ tdata: foxes.core.TData
163
+ The target point data
164
+ downwind_index: int
165
+ The index of the wake causing turbine
166
+ in the downwnd order
163
167
  wake_coos: numpy.ndarray
164
168
  The wake frame coordinates of the evaluation
165
- points, shape: (n_states, n_points, 3)
169
+ points, shape: (n_states, n_targets, n_tpoints, 3)
166
170
  wake_deltas: dict
167
- The wake deltas, are being modified ob the fly.
168
- Key: Variable name str, for which the
169
- wake delta applies, values: numpy.ndarray with
170
- shape (n_states, n_points, ...)
171
+ The wake deltas. Key: variable name,
172
+ value: numpy.ndarray with shape
173
+ (n_states, n_targets, n_tpoints, ...)
171
174
 
172
175
  """
173
-
174
176
  # get ct
175
177
  ct = self.get_data(
176
178
  FV.CT,
177
- FC.STATE_POINT,
179
+ FC.STATE_TARGET_TPOINT,
178
180
  lookup="w",
179
181
  algo=algo,
180
182
  fdata=fdata,
181
- pdata=pdata,
183
+ tdata=tdata,
182
184
  upcast=True,
183
- states_source_turbine=states_source_turbine,
185
+ downwind_index=downwind_index,
184
186
  )
185
187
 
186
188
  # get ws
187
189
  ws = self.get_data(
188
190
  FV.REWS,
189
- FC.STATE_POINT,
191
+ FC.STATE_TARGET_TPOINT,
190
192
  lookup="w",
191
193
  algo=algo,
192
194
  fdata=fdata,
193
- pdata=pdata,
195
+ tdata=tdata,
194
196
  upcast=True,
195
- states_source_turbine=states_source_turbine,
197
+ downwind_index=downwind_index,
196
198
  )
197
199
 
198
- # get D
199
- D = self.get_data(
200
+ # get R
201
+ R = 0.5 * self.get_data(
200
202
  FV.D,
201
- FC.STATE_POINT,
203
+ FC.STATE_TARGET_TPOINT,
202
204
  lookup="w",
203
205
  algo=algo,
204
206
  fdata=fdata,
205
- pdata=pdata,
206
- upcast=True,
207
- states_source_turbine=states_source_turbine,
207
+ tdata=tdata,
208
+ upcast=False,
209
+ downwind_index=downwind_index,
208
210
  )
209
211
 
210
- # get x, r and R etc
211
- x = wake_coos[:, :, 0]
212
- y = wake_coos[:, :, 1]
213
- z = wake_coos[:, :, 2]
214
- R = D / 2
215
- x_R = x / R
216
- r = np.sqrt(y**2 + z**2)
217
- r_R = r / R
212
+ # get x, r and R etc. Rounding for safe x < 0 condition below
213
+ x_R = np.round(wake_coos[..., 0] / R, 12)
214
+ r_R = np.linalg.norm(wake_coos[..., 1:3], axis=-1) / R
218
215
 
219
216
  # select values
220
- sp_sel = (ct > 0) & (x < 0) # upstream
217
+ sp_sel = (ct > 0) & (x_R <= 0) # upstream
221
218
  if np.any(sp_sel):
222
219
  # velocity eqn 10 from [1]
223
220
  xr = x_R[sp_sel]
@@ -228,7 +225,7 @@ class SelfSimilar(WakeModel):
228
225
 
229
226
  # set area behind to mirrored value EXCEPT for area behind turbine
230
227
  if not self.pre_rotor_only:
231
- sp_sel = (ct > 0) & (x > 0) & (r_R > 1)
228
+ sp_sel = (ct > 0) & (x_R > 0) & (r_R > 1)
232
229
  if np.any(sp_sel):
233
230
  # velocity eqn 10 from [1]
234
231
  xr = x_R[sp_sel]