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
@@ -101,6 +101,10 @@ class PCtFile(TurbineType):
101
101
  self.WSP = var_ws_P
102
102
  self.rpars = pd_file_read_pars
103
103
 
104
+ def __repr__(self):
105
+ a = f"D={self.D}, H={self.H}, P_nominal={self.P_nominal}, P_unit={self.P_unit}, rho={self.rho}"
106
+ return f"{type(self).__name__}({a})"
107
+
104
108
  def output_farm_vars(self, algo):
105
109
  """
106
110
  The variables which are being modified by the model.
@@ -169,6 +173,83 @@ class PCtFile(TurbineType):
169
173
 
170
174
  return super().load_data(algo, verbosity)
171
175
 
176
+ def modify_cutin(
177
+ self,
178
+ modify_ct,
179
+ modify_P,
180
+ steps=20,
181
+ iterations=100,
182
+ a=0.55,
183
+ b=0.55,
184
+ ):
185
+ """
186
+ Modify the data such that a discontinuity
187
+ at cutin wind speed is avoided
188
+
189
+ Parameters
190
+ ----------
191
+ variable: str
192
+ The target variable
193
+ modify_ct: bool
194
+ Flag for modification of the ct curve
195
+ modify_P: bool
196
+ Flag for modification of the power curve
197
+ steps: int
198
+ The number of wind speed steps between 0 and
199
+ the cutin wind speed
200
+ iterations: int
201
+ The number of iterations
202
+ a: float
203
+ Coefficient for iterative mixing
204
+ b: float
205
+ Coefficient for iterative mixing
206
+
207
+ """
208
+ if modify_ct or modify_P:
209
+
210
+ ws = self.data_ws
211
+ ct = self.data_ct
212
+ P = self.data_P
213
+
214
+ i = 0
215
+ try:
216
+ while (
217
+ i < len(ws)
218
+ and (not modify_ct or ct[i] < 1e-5)
219
+ and (not modify_P or P[i] < 0.1)
220
+ ):
221
+ i += 1
222
+ except IndexError:
223
+ raise IndexError(
224
+ f"Turbine type '{self.name}': Failed not determine cutin wind speed. ws = {ws}, ct = {ct}, P = {P}"
225
+ )
226
+
227
+ if ws[i] > 0:
228
+ ws = ws[i:]
229
+ ct = ct[i:]
230
+ P = P[i:]
231
+
232
+ new_ws = np.linspace(0.0, ws[0], steps + 1, dtype=ws.dtype)
233
+ new_ct = np.zeros_like(new_ws)
234
+ new_P = np.zeros_like(new_ws)
235
+
236
+ if modify_ct:
237
+ new_ct[-1] = ct[0]
238
+ for it in range(iterations):
239
+ new_ct[1:-1] = a * new_ct[:-2] + (1 - a) * new_ct[2:]
240
+
241
+ if modify_P:
242
+ new_P[-1] = P[0]
243
+ for it in range(iterations):
244
+ new_P[1:-1] = b * new_P[:-2] + (1 - b) * new_P[2:]
245
+
246
+ self.data_ws = np.concatenate([new_ws[:-1], ws], axis=0)
247
+ self.data_ct = np.concatenate([new_ct[:-1], ct], axis=0)
248
+ self.data_P = np.concatenate([new_P[:-1], P], axis=0)
249
+
250
+ else:
251
+ super().modify_cutin(modify_ct, modify_P)
252
+
172
253
  def calculate(self, algo, mdata, fdata, st_sel):
173
254
  """ "
174
255
  The main model calculation.
@@ -180,9 +261,9 @@ class PCtFile(TurbineType):
180
261
  ----------
181
262
  algo: foxes.core.Algorithm
182
263
  The calculation algorithm
183
- mdata: foxes.core.Data
264
+ mdata: foxes.core.MData
184
265
  The model data
185
- fdata: foxes.core.Data
266
+ fdata: foxes.core.FData
186
267
  The farm data
187
268
  st_sel: numpy.ndarray of bool
188
269
  The state-turbine selection,
@@ -204,7 +285,7 @@ class PCtFile(TurbineType):
204
285
  # that in the partial load region the
205
286
  # correct value is reconstructed:
206
287
  rho = fdata[FV.RHO][st_sel]
207
- rews2 *= (self.rho / rho) ** 0.5
288
+ # rews2 *= (self.rho / rho) ** 0.5
208
289
  rews3 *= (self.rho / rho) ** (1.0 / 3.0)
209
290
  del rho
210
291
 
@@ -121,6 +121,10 @@ class PCtFromTwo(TurbineType):
121
121
  self._data_ws_P = None
122
122
  self._data_ws_ct = None
123
123
 
124
+ def __repr__(self):
125
+ a = f"D={self.D}, H={self.H}, P_nominal={self.P_nominal}, P_unit={self.P_unit}, rho={self.rho}"
126
+ return f"{type(self).__name__}({a})"
127
+
124
128
  def output_farm_vars(self, algo):
125
129
  """
126
130
  The variables which are being modified by the model.
@@ -203,9 +207,9 @@ class PCtFromTwo(TurbineType):
203
207
  ----------
204
208
  algo: foxes.core.Algorithm
205
209
  The calculation algorithm
206
- mdata: foxes.core.Data
210
+ mdata: foxes.core.MData
207
211
  The model data
208
- fdata: foxes.core.Data
212
+ fdata: foxes.core.FData
209
213
  The farm data
210
214
  st_sel: numpy.ndarray of bool
211
215
  The state-turbine selection,
@@ -227,7 +231,7 @@ class PCtFromTwo(TurbineType):
227
231
  # that in the partial load region the
228
232
  # correct value is reconstructed:
229
233
  rho = fdata[FV.RHO][st_sel]
230
- rews2 *= (self.rho / rho) ** 0.5
234
+ # rews2 *= (self.rho / rho) ** 0.5
231
235
  rews3 *= (self.rho / rho) ** (1.0 / 3.0)
232
236
  del rho
233
237
 
@@ -37,9 +37,9 @@ class NullType(TurbineType):
37
37
  ----------
38
38
  algo: foxes.core.Algorithm
39
39
  The calculation algorithm
40
- mdata: foxes.core.Data
40
+ mdata: foxes.core.MData
41
41
  The model data
42
- fdata: foxes.core.Data
42
+ fdata: foxes.core.FData
43
43
  The farm data
44
44
  st_sel: numpy.ndarray of bool
45
45
  The state-turbine selection,
@@ -215,9 +215,9 @@ class WsRho2PCtFromTwo(TurbineType):
215
215
  ----------
216
216
  algo: foxes.core.Algorithm
217
217
  The calculation algorithm
218
- mdata: foxes.core.Data
218
+ mdata: foxes.core.MData
219
219
  The model data
220
- fdata: foxes.core.Data
220
+ fdata: foxes.core.FData
221
221
  The farm data
222
222
  st_sel: numpy.ndarray of bool
223
223
  The state-turbine selection,
@@ -123,6 +123,10 @@ class WsTI2PCtFromTwo(TurbineType):
123
123
  self._P = None
124
124
  self._ct = None
125
125
 
126
+ def __repr__(self):
127
+ a = f"D={self.D}, H={self.H}, P_nominal={self.P_nominal}, P_unit={self.P_unit}, rho={self.rho}"
128
+ return f"{type(self).__name__}({a})"
129
+
126
130
  def output_farm_vars(self, algo):
127
131
  """
128
132
  The variables which are being modified by the model.
@@ -223,9 +227,9 @@ class WsTI2PCtFromTwo(TurbineType):
223
227
  ----------
224
228
  algo: foxes.core.Algorithm
225
229
  The calculation algorithm
226
- mdata: foxes.core.Data
230
+ mdata: foxes.core.MData
227
231
  The model data
228
- fdata: foxes.core.Data
232
+ fdata: foxes.core.FData
229
233
  The farm data
230
234
  st_sel: numpy.ndarray of bool
231
235
  The state-turbine selection,
@@ -59,9 +59,9 @@ class FarmOrder(WakeFrame):
59
59
  ----------
60
60
  algo: foxes.core.Algorithm
61
61
  The calculation algorithm
62
- mdata: foxes.core.Data
62
+ mdata: foxes.core.MData
63
63
  The model data
64
- fdata: foxes.core.Data
64
+ fdata: foxes.core.FData
65
65
  The farm data
66
66
 
67
67
  Returns
@@ -75,36 +75,41 @@ class FarmOrder(WakeFrame):
75
75
 
76
76
  return order
77
77
 
78
- def get_wake_coos(self, algo, mdata, fdata, pdata, states_source_turbine):
78
+ def get_wake_coos(
79
+ self,
80
+ algo,
81
+ mdata,
82
+ fdata,
83
+ tdata,
84
+ downwind_index,
85
+ ):
79
86
  """
80
- Calculate wake coordinates.
87
+ Calculate wake coordinates of rotor points.
81
88
 
82
89
  Parameters
83
90
  ----------
84
91
  algo: foxes.core.Algorithm
85
92
  The calculation algorithm
86
- mdata: foxes.core.Data
93
+ mdata: foxes.core.MData
87
94
  The model data
88
- fdata: foxes.core.Data
95
+ fdata: foxes.core.FData
89
96
  The farm data
90
- pdata: foxes.core.Data
91
- The evaluation point data
92
- states_source_turbine: numpy.ndarray
93
- For each state, one turbine index for the
94
- wake causing turbine. Shape: (n_states,)
97
+ tdata: foxes.core.TData
98
+ The target point data
99
+ downwind_index: int
100
+ The index of the wake causing turbine
101
+ in the downwnd order
95
102
 
96
103
  Returns
97
104
  -------
98
105
  wake_coos: numpy.ndarray
99
106
  The wake frame coordinates of the evaluation
100
- points, shape: (n_states, n_points, 3)
107
+ points, shape: (n_states, n_targets, n_tpoints, 3)
101
108
 
102
109
  """
103
- return self.base_frame.get_wake_coos(
104
- algo, mdata, fdata, pdata, states_source_turbine
105
- )
110
+ return self.base_frame.get_wake_coos(algo, mdata, fdata, tdata, downwind_index)
106
111
 
107
- def get_centreline_points(self, algo, mdata, fdata, states_source_turbine, x):
112
+ def get_centreline_points(self, algo, mdata, fdata, downwind_index, x):
108
113
  """
109
114
  Gets the points along the centreline for given
110
115
  values of x.
@@ -113,13 +118,12 @@ class FarmOrder(WakeFrame):
113
118
  ----------
114
119
  algo: foxes.core.Algorithm
115
120
  The calculation algorithm
116
- mdata: foxes.core.Data
121
+ mdata: foxes.core.MData
117
122
  The model data
118
- fdata: foxes.core.Data
123
+ fdata: foxes.core.FData
119
124
  The farm data
120
- states_source_turbine: numpy.ndarray
121
- For each state, one turbine index for the
122
- wake causing turbine. Shape: (n_states,)
125
+ downwind_index: int
126
+ The index in the downwind order
123
127
  x: numpy.ndarray
124
128
  The wake frame x coordinates, shape: (n_states, n_points)
125
129
 
@@ -130,5 +134,5 @@ class FarmOrder(WakeFrame):
130
134
 
131
135
  """
132
136
  return self.base_frame.get_centreline_points(
133
- algo, mdata, fdata, states_source_turbine, x
137
+ algo, mdata, fdata, downwind_index, x
134
138
  )
@@ -44,9 +44,9 @@ class RotorWD(WakeFrame):
44
44
  ----------
45
45
  algo: foxes.core.Algorithm
46
46
  The calculation algorithm
47
- mdata: foxes.core.Data
47
+ mdata: foxes.core.MData
48
48
  The model data
49
- fdata: foxes.core.Data
49
+ fdata: foxes.core.FData
50
50
  The farm data
51
51
 
52
52
  Returns
@@ -57,45 +57,50 @@ class RotorWD(WakeFrame):
57
57
  """
58
58
  n = np.mean(wd2uv(fdata[self.var_wd], axis=1), axis=-1)
59
59
  xy = fdata[FV.TXYH][:, :, :2]
60
-
61
60
  order = np.argsort(np.einsum("std,sd->st", xy, n), axis=-1)
62
61
 
63
62
  return order
64
63
 
65
- def get_wake_coos(self, algo, mdata, fdata, pdata, states_source_turbine):
64
+ def get_wake_coos(
65
+ self,
66
+ algo,
67
+ mdata,
68
+ fdata,
69
+ tdata,
70
+ downwind_index,
71
+ ):
66
72
  """
67
- Calculate wake coordinates.
73
+ Calculate wake coordinates of rotor points.
68
74
 
69
75
  Parameters
70
76
  ----------
71
77
  algo: foxes.core.Algorithm
72
78
  The calculation algorithm
73
- mdata: foxes.core.Data
79
+ mdata: foxes.core.MData
74
80
  The model data
75
- fdata: foxes.core.Data
81
+ fdata: foxes.core.FData
76
82
  The farm data
77
- pdata: foxes.core.Data
78
- The evaluation point data
79
- states_source_turbine: numpy.ndarray
80
- For each state, one turbine index for the
81
- wake causing turbine. Shape: (n_states,)
83
+ tdata: foxes.core.TData
84
+ The target point data
85
+ downwind_index: int
86
+ The index of the wake causing turbine
87
+ in the downwnd order
82
88
 
83
89
  Returns
84
90
  -------
85
91
  wake_coos: numpy.ndarray
86
92
  The wake frame coordinates of the evaluation
87
- points, shape: (n_states, n_points, 3)
93
+ points, shape: (n_states, n_targets, n_tpoints, 3)
88
94
 
89
95
  """
90
- points = pdata[FC.POINTS]
91
- n_states = mdata.n_states
92
- stsel = (np.arange(n_states), states_source_turbine)
96
+ n_states = tdata.n_states
97
+ targets = tdata[FC.TARGETS]
93
98
 
94
- xyz = fdata[FV.TXYH][stsel]
95
- delta = points - xyz[:, None, :]
99
+ xyz = fdata[FV.TXYH][:, downwind_index]
100
+ delta = targets - xyz[:, None, None, :]
96
101
  del xyz
97
102
 
98
- wd = fdata[self.var_wd][stsel]
103
+ wd = fdata[self.var_wd][:, downwind_index]
99
104
 
100
105
  nax = np.zeros((n_states, 3, 3), dtype=FC.DTYPE)
101
106
  n = nax[:, 0, :2]
@@ -105,11 +110,11 @@ class RotorWD(WakeFrame):
105
110
  nax[:, 2, 2] = 1
106
111
  del wd
107
112
 
108
- coos = np.einsum("spd,sad->spa", delta, nax)
113
+ coos = np.einsum("stpd,sad->stpa", delta, nax)
109
114
 
110
115
  return coos
111
116
 
112
- def get_centreline_points(self, algo, mdata, fdata, states_source_turbine, x):
117
+ def get_centreline_points(self, algo, mdata, fdata, downwind_index, x):
113
118
  """
114
119
  Gets the points along the centreline for given
115
120
  values of x.
@@ -118,13 +123,12 @@ class RotorWD(WakeFrame):
118
123
  ----------
119
124
  algo: foxes.core.Algorithm
120
125
  The calculation algorithm
121
- mdata: foxes.core.Data
126
+ mdata: foxes.core.MData
122
127
  The model data
123
- fdata: foxes.core.Data
128
+ fdata: foxes.core.FData
124
129
  The farm data
125
- states_source_turbine: numpy.ndarray
126
- For each state, one turbine index for the
127
- wake causing turbine. Shape: (n_states,)
130
+ downwind_index: int
131
+ The index in the downwind order
128
132
  x: numpy.ndarray
129
133
  The wake frame x coordinates, shape: (n_states, n_points)
130
134
 
@@ -134,11 +138,8 @@ class RotorWD(WakeFrame):
134
138
  The centreline points, shape: (n_states, n_points, 3)
135
139
 
136
140
  """
137
- n_states = mdata.n_states
138
- stsel = (np.arange(n_states), states_source_turbine)
139
-
140
- wd = fdata[self.var_wd][stsel]
141
+ wd = fdata[self.var_wd][:, downwind_index]
141
142
  n = np.append(wd2uv(wd, axis=-1), np.zeros_like(wd)[:, None], axis=-1)
142
143
 
143
- xyz = fdata[FV.TXYH][stsel]
144
+ xyz = fdata[FV.TXYH][:, downwind_index]
144
145
  return xyz[:, None, :] + x[:, :, None] * n[:, None, :]