foxes 0.6.2__py3-none-any.whl → 0.7.0.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 (120) 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/from_random.py +10 -9
  32. foxes/input/states/create/random_timeseries.py +17 -19
  33. foxes/input/states/field_data_nc.py +12 -8
  34. foxes/input/states/multi_height.py +24 -14
  35. foxes/input/states/scan_ws.py +13 -17
  36. foxes/input/states/single.py +28 -20
  37. foxes/input/states/states_table.py +22 -18
  38. foxes/models/axial_induction_models/betz.py +1 -1
  39. foxes/models/farm_models/turbine2farm.py +2 -2
  40. foxes/models/model_book.py +39 -14
  41. foxes/models/partial_wakes/__init__.py +2 -3
  42. foxes/models/partial_wakes/axiwake.py +73 -200
  43. foxes/models/partial_wakes/centre.py +11 -79
  44. foxes/models/partial_wakes/grid.py +7 -63
  45. foxes/models/partial_wakes/rotor_points.py +53 -147
  46. foxes/models/partial_wakes/segregated.py +158 -0
  47. foxes/models/partial_wakes/top_hat.py +88 -196
  48. foxes/models/point_models/set_uniform_data.py +4 -4
  49. foxes/models/point_models/tke2ti.py +4 -4
  50. foxes/models/point_models/wake_deltas.py +4 -4
  51. foxes/models/rotor_models/centre.py +15 -19
  52. foxes/models/rotor_models/grid.py +2 -1
  53. foxes/models/rotor_models/levels.py +2 -1
  54. foxes/models/turbine_models/__init__.py +0 -1
  55. foxes/models/turbine_models/calculator.py +11 -7
  56. foxes/models/turbine_models/kTI_model.py +13 -11
  57. foxes/models/turbine_models/lookup_table.py +22 -9
  58. foxes/models/turbine_models/power_mask.py +81 -51
  59. foxes/models/turbine_models/rotor_centre_calc.py +17 -20
  60. foxes/models/turbine_models/sector_management.py +5 -6
  61. foxes/models/turbine_models/set_farm_vars.py +49 -20
  62. foxes/models/turbine_models/table_factors.py +5 -5
  63. foxes/models/turbine_models/thrust2ct.py +9 -5
  64. foxes/models/turbine_models/yaw2yawm.py +7 -13
  65. foxes/models/turbine_models/yawm2yaw.py +7 -11
  66. foxes/models/turbine_types/PCt_file.py +84 -3
  67. foxes/models/turbine_types/PCt_from_two.py +7 -3
  68. foxes/models/turbine_types/null_type.py +2 -2
  69. foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -2
  70. foxes/models/turbine_types/wsti2PCt_from_two.py +6 -2
  71. foxes/models/wake_frames/farm_order.py +26 -22
  72. foxes/models/wake_frames/rotor_wd.py +32 -31
  73. foxes/models/wake_frames/seq_dynamic_wakes.py +112 -64
  74. foxes/models/wake_frames/streamlines.py +51 -47
  75. foxes/models/wake_frames/timelines.py +59 -47
  76. foxes/models/wake_frames/yawed_wakes.py +63 -40
  77. foxes/models/wake_models/axisymmetric.py +31 -35
  78. foxes/models/wake_models/dist_sliced.py +50 -56
  79. foxes/models/wake_models/gaussian.py +33 -35
  80. foxes/models/wake_models/induction/rankine_half_body.py +79 -87
  81. foxes/models/wake_models/induction/rathmann.py +56 -63
  82. foxes/models/wake_models/induction/self_similar.py +59 -62
  83. foxes/models/wake_models/ti/crespo_hernandez.py +83 -74
  84. foxes/models/wake_models/ti/iec_ti.py +65 -75
  85. foxes/models/wake_models/top_hat.py +60 -69
  86. foxes/models/wake_models/wake_mirror.py +49 -54
  87. foxes/models/wake_models/wind/bastankhah14.py +44 -66
  88. foxes/models/wake_models/wind/bastankhah16.py +84 -111
  89. foxes/models/wake_models/wind/jensen.py +67 -89
  90. foxes/models/wake_models/wind/turbopark.py +93 -133
  91. foxes/models/wake_superpositions/ti_linear.py +33 -27
  92. foxes/models/wake_superpositions/ti_max.py +33 -27
  93. foxes/models/wake_superpositions/ti_pow.py +35 -27
  94. foxes/models/wake_superpositions/ti_quadratic.py +33 -27
  95. foxes/models/wake_superpositions/ws_linear.py +39 -32
  96. foxes/models/wake_superpositions/ws_max.py +40 -33
  97. foxes/models/wake_superpositions/ws_pow.py +39 -32
  98. foxes/models/wake_superpositions/ws_product.py +35 -28
  99. foxes/models/wake_superpositions/ws_quadratic.py +39 -32
  100. foxes/opt/problems/layout/farm_layout.py +38 -97
  101. foxes/output/__init__.py +1 -0
  102. foxes/output/flow_plots_2d/flow_plots.py +2 -0
  103. foxes/output/rose_plot.py +3 -3
  104. foxes/output/rotor_point_plots.py +117 -0
  105. foxes/output/turbine_type_curves.py +2 -2
  106. foxes/utils/__init__.py +1 -1
  107. foxes/utils/load.py +29 -0
  108. foxes/utils/random_xy.py +11 -10
  109. foxes/utils/runners/runners.py +3 -4
  110. foxes/utils/windrose_plot.py +1 -1
  111. foxes/variables.py +10 -0
  112. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/METADATA +13 -7
  113. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/RECORD +117 -117
  114. foxes/models/partial_wakes/distsliced.py +0 -322
  115. foxes/models/partial_wakes/mapped.py +0 -252
  116. foxes/models/turbine_models/set_XYHD.py +0 -130
  117. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/LICENSE +0 -0
  118. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/WHEEL +0 -0
  119. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/top_level.txt +0 -0
  120. {foxes-0.6.2.dist-info → foxes-0.7.0.2.dist-info}/zip-safe +0 -0
@@ -1,13 +1,14 @@
1
1
  import numpy as np
2
2
 
3
- from foxes.core import PartialWakesModel, Data
4
3
  from foxes.models.wake_models.top_hat import TopHatWakeModel
5
4
  from foxes.utils.two_circles import calc_area
6
5
  import foxes.variables as FV
7
6
  import foxes.constants as FC
8
7
 
8
+ from .centre import PartialCentre
9
9
 
10
- class PartialTopHat(PartialWakesModel):
10
+
11
+ class PartialTopHat(PartialCentre):
11
12
  """
12
13
  Partial wakes for top-hat models.
13
14
 
@@ -23,21 +24,17 @@ class PartialTopHat(PartialWakesModel):
23
24
 
24
25
  """
25
26
 
26
- def __init__(self, wake_models=None, wake_frame=None, rotor_model=None):
27
+ def __init__(self, rotor_model=None):
27
28
  """
28
29
  Constructor.
29
30
 
30
31
  Parameters
31
32
  ----------
32
- wake_models: list of foxes.core.WakeModel, optional
33
- The wake models, default are the ones from the algorithm
34
- wake_frame: foxes.core.WakeFrame, optional
35
- The wake frame, default is the one from the algorithm
36
33
  rotor_model: foxes.core.RotorModel, optional
37
34
  The rotor model, default is the one from the algorithm
38
35
 
39
36
  """
40
- super().__init__(wake_models, wake_frame)
37
+ super().__init__()
41
38
  self.rotor_model = rotor_model
42
39
 
43
40
  def initialize(self, algo, verbosity=0):
@@ -57,12 +54,6 @@ class PartialTopHat(PartialWakesModel):
57
54
 
58
55
  super().initialize(algo, verbosity)
59
56
 
60
- for w in self.wake_models:
61
- if not isinstance(w, TopHatWakeModel):
62
- raise TypeError(
63
- f"Partial wakes '{self.name}': Cannot be applied to wake model '{w.name}', since not a TopHatWakeModel"
64
- )
65
-
66
57
  self.WCOOS_ID = self.var("WCOOS_ID")
67
58
  self.WCOOS_X = self.var("WCOOS_X")
68
59
  self.WCOOS_R = self.var("WCOOS_R")
@@ -79,211 +70,112 @@ class PartialTopHat(PartialWakesModel):
79
70
  """
80
71
  return super().sub_models() + [self.rotor_model]
81
72
 
82
- def new_wake_deltas(self, algo, mdata, fdata):
83
- """
84
- Creates new initial wake deltas, filled
85
- with zeros.
86
-
87
- Parameters
88
- ----------
89
- algo: foxes.core.Algorithm
90
- The calculation algorithm
91
- mdata: foxes.core.Data
92
- The model data
93
- fdata: foxes.core.Data
94
- The farm data
95
-
96
- Returns
97
- -------
98
- wake_deltas: dict
99
- Keys: Variable name str, values: any
100
- pdata: foxes.core.Data
101
- The evaluation point data
102
-
103
- """
104
- pdata = Data.from_points(points=fdata[FV.TXYH])
105
-
106
- wake_deltas = {}
107
- for w in self.wake_models:
108
- w.init_wake_deltas(algo, mdata, fdata, pdata, wake_deltas)
109
-
110
- return wake_deltas, pdata
111
-
112
- def contribute_to_wake_deltas(
73
+ def contribute(
113
74
  self,
114
75
  algo,
115
76
  mdata,
116
77
  fdata,
117
- pdata,
118
- states_source_turbine,
78
+ tdata,
79
+ downwind_index,
119
80
  wake_deltas,
81
+ wmodel,
120
82
  ):
121
83
  """
122
- Modifies wake deltas by contributions from the
123
- specified wake source turbines.
84
+ Modifies wake deltas at target points by
85
+ contributions from the specified wake source turbines.
124
86
 
125
87
  Parameters
126
88
  ----------
127
89
  algo: foxes.core.Algorithm
128
90
  The calculation algorithm
129
- mdata: foxes.core.Data
91
+ mdata: foxes.core.MData
130
92
  The model data
131
- fdata: foxes.core.Data
93
+ fdata: foxes.core.FData
132
94
  The farm data
133
- pdata: foxes.core.Data
134
- The evaluation point data
135
- states_source_turbine: numpy.ndarray of int
136
- For each state, one turbine index corresponding
137
- to the wake causing turbine. Shape: (n_states,)
138
- wake_deltas: Any
139
- The wake deltas object created by the
140
- `new_wake_deltas` function
95
+ tdata: foxes.core.TData
96
+ The target point data
97
+ downwind_index: int
98
+ The index of the wake causing turbine
99
+ in the downwnd order
100
+ wake_deltas: dict
101
+ The wake deltas. Key: variable name,
102
+ value: numpy.ndarray with shape
103
+ (n_states, n_targets, n_tpoints, ...)
104
+ wmodel: foxes.core.WakeModel
105
+ The wake model
141
106
 
142
107
  """
143
- n_states = mdata.n_states
144
- n_points = fdata.n_turbines
145
- stsel = (np.arange(n_states), states_source_turbine)
146
-
147
- if (
148
- self.WCOOS_ID not in mdata
149
- or mdata[self.WCOOS_ID] != states_source_turbine[0]
150
- ):
151
- wcoos = self.wake_frame.get_wake_coos(
152
- algo, mdata, fdata, pdata, states_source_turbine
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"
153
111
  )
154
- mdata[self.WCOOS_ID] = states_source_turbine[0]
155
- mdata[self.WCOOS_X] = wcoos[:, :, 0]
156
- mdata[self.WCOOS_R] = np.linalg.norm(wcoos[:, :, 1:3], axis=-1)
157
- wcoos[:, :, 1:3] = 0
158
- else:
159
- wcoos = np.zeros((n_states, n_points), dtype=FC.DTYPE)
160
- wcoos[:, :, 0] = mdata[self.WCOOS_X]
161
-
162
- ct = np.zeros((n_states, n_points), dtype=FC.DTYPE)
163
- ct[:] = fdata[FV.CT][stsel][:, None]
164
- x = mdata[self.WCOOS_X]
165
-
166
- sel0 = (ct > 0.0) & (x > 0.0)
112
+
113
+ wcoos = algo.wake_frame.get_wake_coos(algo, mdata, fdata, tdata, downwind_index)
114
+ x = wcoos[:, :, 0, 0]
115
+ yz = wcoos[:, :, 0, 1:3]
116
+ del wcoos
117
+
118
+ ct = self.get_data(
119
+ FV.CT,
120
+ FC.STATE_TARGET,
121
+ lookup="w",
122
+ fdata=fdata,
123
+ tdata=tdata,
124
+ downwind_index=downwind_index,
125
+ algo=algo,
126
+ upcast=True,
127
+ )
128
+
129
+ sel0 = (ct > 0) & (x > 0)
167
130
  if np.any(sel0):
168
- R = mdata[self.WCOOS_R]
169
- r = np.zeros_like(R)
170
- D = fdata[FV.D]
131
+ R = np.linalg.norm(yz, axis=-1)
132
+ del yz
133
+
134
+ D = self.get_data(
135
+ FV.D,
136
+ FC.STATE_TARGET,
137
+ lookup="w",
138
+ fdata=fdata,
139
+ tdata=tdata,
140
+ downwind_index=downwind_index,
141
+ algo=algo,
142
+ upcast=True,
143
+ )
171
144
 
172
- for w in self.wake_models:
173
- wr = w.calc_wake_radius(
174
- algo, mdata, fdata, pdata, states_source_turbine, x, ct
145
+ wr = wmodel.calc_wake_radius(
146
+ algo, mdata, fdata, tdata, downwind_index, x, ct
147
+ )
148
+
149
+ st_sel = sel0 & (wr > R - D / 2)
150
+ if np.any(st_sel):
151
+ x = x[st_sel]
152
+ ct = ct[st_sel]
153
+ wr = wr[st_sel]
154
+ R = R[st_sel]
155
+ D = D[st_sel]
156
+
157
+ clw = wmodel.calc_centreline(
158
+ algo, mdata, fdata, tdata, downwind_index, st_sel, x, wr, ct
175
159
  )
176
160
 
177
- sel_sp = sel0 & (wr > R - D / 2)
178
- if np.any(sel_sp):
179
- hx = x[sel_sp]
180
- hct = ct[sel_sp]
181
- hwr = wr[sel_sp]
161
+ weights = calc_area(D / 2, wr, R) / (np.pi * (D / 2) ** 2)
162
+
163
+ for v, d in clw.items():
164
+ try:
165
+ superp = wmodel.superp[v]
166
+ except KeyError:
167
+ raise KeyError(
168
+ f"Model '{self.name}': Missing wake superposition entry for variable '{v}' in wake model '{wmodel.name}', found {sorted(list(wmodel.superp.keys()))}"
169
+ )
182
170
 
183
- clw = w.calc_centreline_wake_deltas(
171
+ wake_deltas[v] = superp.add_wake(
184
172
  algo,
185
173
  mdata,
186
174
  fdata,
187
- pdata,
188
- states_source_turbine,
189
- sel_sp,
190
- hx,
191
- hwr,
192
- hct,
175
+ tdata,
176
+ downwind_index,
177
+ st_sel,
178
+ v,
179
+ wake_deltas[v],
180
+ weights[:, None] * d[:, None],
193
181
  )
194
- del hx, hct
195
-
196
- hR = R[sel_sp]
197
- hD = D[sel_sp]
198
- weights = calc_area(hD / 2, hwr, hR) / (np.pi * (hD / 2) ** 2)
199
- del hD, hwr, hR
200
-
201
- for v, d in clw.items():
202
- try:
203
- superp = w.superp[v]
204
- except KeyError:
205
- raise KeyError(
206
- f"Model '{self.name}': Missing wake superposition entry for variable '{v}' in wake model '{w.name}', found {sorted(list(w.superp.keys()))}"
207
- )
208
-
209
- wake_deltas[v] = superp.calc_wakes_plus_wake(
210
- algo,
211
- mdata,
212
- fdata,
213
- pdata,
214
- states_source_turbine,
215
- sel_sp,
216
- v,
217
- wake_deltas[v],
218
- weights * d,
219
- )
220
-
221
- def evaluate_results(
222
- self,
223
- algo,
224
- mdata,
225
- fdata,
226
- pdata,
227
- wake_deltas,
228
- states_turbine,
229
- amb_res=None,
230
- ):
231
- """
232
- Updates the farm data according to the wake
233
- deltas.
234
-
235
- Parameters
236
- ----------
237
- algo: foxes.core.Algorithm
238
- The calculation algorithm
239
- mdata: foxes.core.Data
240
- The model data
241
- fdata: foxes.core.Data
242
- The farm data
243
- Modified in-place by this function
244
- pdata: foxes.core.Data
245
- The evaluation point data
246
- wake_deltas: Any
247
- The wake deltas object, created by the
248
- `new_wake_deltas` function and filled
249
- by `contribute_to_wake_deltas`
250
- states_turbine: numpy.ndarray of int
251
- For each state, the index of one turbine
252
- for which to evaluate the wake deltas.
253
- Shape: (n_states,)
254
- amb_res: dict, optional
255
- Ambient states results. Keys: var str, values:
256
- numpy.ndarray of shape (n_states, n_points)
257
-
258
- """
259
- weights = algo.rotor_model.from_data_or_store(FC.RWEIGHTS, algo, mdata)
260
- rpoints = algo.rotor_model.from_data_or_store(FC.RPOINTS, algo, mdata)
261
- n_states, n_turbines, n_rpoints, __ = rpoints.shape
262
-
263
- amb_res_in = amb_res is not None
264
- if not amb_res_in:
265
- amb_res = algo.rotor_model.from_data_or_store(
266
- FC.AMB_RPOINT_RESULTS, algo, mdata
267
- )
268
-
269
- wres = {}
270
- st_sel = (np.arange(n_states), states_turbine)
271
- for v, ares in amb_res.items():
272
- wres[v] = ares.reshape(n_states, n_turbines, n_rpoints)[st_sel]
273
-
274
- wdel = {}
275
- for v, d in wake_deltas.items():
276
- wdel[v] = d.reshape(n_states, n_turbines, 1)[st_sel]
277
- for w in self.wake_models:
278
- w.finalize_wake_deltas(algo, mdata, fdata, pdata, wres, wdel)
279
-
280
- for v in wres.keys():
281
- if v in wake_deltas:
282
- wres[v] += wdel[v]
283
- if amb_res_in:
284
- amb_res[v][st_sel] = wres[v]
285
- wres[v] = wres[v][:, None]
286
-
287
- self.rotor_model.eval_rpoint_results(
288
- algo, mdata, fdata, wres, weights, states_turbine=states_turbine
289
- )
@@ -129,12 +129,12 @@ class SetUniformData(PointDataModel):
129
129
  ----------
130
130
  algo: foxes.core.Algorithm
131
131
  The calculation algorithm
132
- mdata: foxes.core.Data
132
+ mdata: foxes.core.MData
133
133
  The model data
134
- fdata: foxes.core.Data
134
+ fdata: foxes.core.FData
135
135
  The farm data
136
- pdata: foxes.core.Data
137
- The point data
136
+ tdata: foxes.core.TData
137
+ The target point data
138
138
 
139
139
  Returns
140
140
  -------
@@ -40,12 +40,12 @@ class TKE2TI(PointDataModel):
40
40
  ----------
41
41
  algo: foxes.core.Algorithm
42
42
  The calculation algorithm
43
- mdata: foxes.core.Data
43
+ mdata: foxes.core.MData
44
44
  The model data
45
- fdata: foxes.core.Data
45
+ fdata: foxes.core.FData
46
46
  The farm data
47
- pdata: foxes.core.Data
48
- The point data
47
+ tdata: foxes.core.TData
48
+ The target point data
49
49
 
50
50
  Returns
51
51
  -------
@@ -62,12 +62,12 @@ class WakeDeltas(PointDataModel):
62
62
  ----------
63
63
  algo: foxes.core.Algorithm
64
64
  The calculation algorithm
65
- mdata: foxes.core.Data
65
+ mdata: foxes.core.MData
66
66
  The model data
67
- fdata: foxes.core.Data
67
+ fdata: foxes.core.FData
68
68
  The farm data
69
- pdata: foxes.core.Data
70
- The point data
69
+ tdata: foxes.core.TData
70
+ The target point data
71
71
 
72
72
  Returns
73
73
  -------
@@ -69,9 +69,9 @@ class CentreRotor(RotorModel):
69
69
  ----------
70
70
  algo: foxes.core.Algorithm
71
71
  The calculation algorithm
72
- mdata: foxes.core.Data
72
+ mdata: foxes.core.MData
73
73
  The model data
74
- fdata: foxes.core.Data
74
+ fdata: foxes.core.FData
75
75
  The farm data
76
76
 
77
77
  Returns
@@ -90,7 +90,7 @@ class CentreRotor(RotorModel):
90
90
  fdata,
91
91
  rpoint_results,
92
92
  weights,
93
- states_turbine=None,
93
+ downwind_index=None,
94
94
  copy_to_ambient=False,
95
95
  ):
96
96
  """
@@ -106,9 +106,9 @@ class CentreRotor(RotorModel):
106
106
  ----------
107
107
  algo: foxes.core.Algorithm
108
108
  The calculation algorithm
109
- mdata: foxes.core.Data
109
+ mdata: foxes.core.MData
110
110
  The model data
111
- fdata: foxes.core.Data
111
+ fdata: foxes.core.FData
112
112
  The farm data
113
113
  rpoint_results: dict
114
114
  The results at rotor points. Keys: variable str.
@@ -117,25 +117,21 @@ class CentreRotor(RotorModel):
117
117
  Else: (n_states, 1, n_rpoints)
118
118
  weights: numpy.ndarray
119
119
  The rotor point weights, shape: (n_rpoints,)
120
- states_turbine: numpy.ndarray of int, optional
121
- The turbine indices, one per state. Shape: (n_states,)
122
- copy_to_ambient: bool, optional
120
+ downwind_index: int, optional
121
+ The index in the downwind order
122
+ copy_to_ambient: bool
123
123
  If `True`, the fdata results are copied to ambient
124
124
  variables after calculation
125
125
 
126
126
  """
127
127
  if len(weights) > 1:
128
128
  return super().eval_rpoint_results(
129
- algo, mdata, fdata, rpoint_results, weights, states_turbine
129
+ algo, mdata, fdata, rpoint_results, weights, downwind_index
130
130
  )
131
131
 
132
132
  n_states = mdata.n_states
133
133
  n_turbines = algo.n_turbines
134
134
 
135
- stsel = None
136
- if states_turbine is not None:
137
- stsel = (np.arange(n_states), states_turbine)
138
-
139
135
  uvp = None
140
136
  uv = None
141
137
  if (
@@ -160,11 +156,11 @@ class CentreRotor(RotorModel):
160
156
  if v == FV.WD or v == FV.YAW:
161
157
  if wd is None:
162
158
  wd = uv2wd(uv, axis=-1)
163
- self._set_res(fdata, v, wd, stsel)
159
+ self._set_res(fdata, v, wd, downwind_index)
164
160
  vdone.append(v)
165
161
 
166
162
  elif v == FV.WS:
167
- self._set_res(fdata, v, ws[:, :, 0], stsel)
163
+ self._set_res(fdata, v, ws[:, :, 0], downwind_index)
168
164
  del ws
169
165
  vdone.append(v)
170
166
  del uv, wd
@@ -174,17 +170,17 @@ class CentreRotor(RotorModel):
174
170
  or FV.REWS2 in self.calc_vars
175
171
  or FV.REWS3 in self.calc_vars
176
172
  ):
177
- if stsel is None:
173
+ if downwind_index is None:
178
174
  yaw = fdata[FV.YAW]
179
175
  else:
180
- yaw = fdata[FV.YAW][stsel][:, None]
176
+ yaw = fdata[FV.YAW][:, downwind_index, None]
181
177
  nax = wd2uv(yaw, axis=-1)
182
178
  wsp = np.einsum("stpd,std->stp", uvp, nax)
183
179
 
184
180
  for v in self.calc_vars:
185
181
  if v == FV.REWS or v == FV.REWS2 or v == FV.REWS3:
186
182
  rews = wsp[:, :, 0]
187
- self._set_res(fdata, v, rews, stsel)
183
+ self._set_res(fdata, v, rews, downwind_index)
188
184
  del rews
189
185
  vdone.append(v)
190
186
 
@@ -194,7 +190,7 @@ class CentreRotor(RotorModel):
194
190
  for v in self.calc_vars:
195
191
  if v not in vdone:
196
192
  res = rpoint_results[v][:, :, 0]
197
- self._set_res(fdata, v, res, stsel)
193
+ self._set_res(fdata, v, res, downwind_index)
198
194
  del res
199
195
  if copy_to_ambient and v in FV.var2amb:
200
196
  fdata[FV.var2amb[v]] = fdata[v].copy()
@@ -54,7 +54,8 @@ class GridRotor(RotorModel):
54
54
  self.nint = nint
55
55
 
56
56
  def __repr__(self):
57
- return super().__repr__() + f"(n={self.n})"
57
+ r = "" if self.reduce else ", reduce=False"
58
+ return f"{type(self).__name__}(n={self.n}){r}"
58
59
 
59
60
  def initialize(self, algo, verbosity=0):
60
61
  """
@@ -51,7 +51,8 @@ class LevelRotor(RotorModel):
51
51
  self.nint = nint
52
52
 
53
53
  def __repr__(self):
54
- return super().__repr__() + f"(n={self.n})"
54
+ r = "" if self.reduce else ", reduce=False"
55
+ return f"{type(self).__name__}(n={self.n}){r}"
55
56
 
56
57
  def initialize(self, algo, verbosity=0):
57
58
  """
@@ -2,7 +2,6 @@
2
2
  Turbine models.
3
3
  """
4
4
 
5
- from .set_XYHD import SetXYHD
6
5
  from .kTI_model import kTI
7
6
  from .set_farm_vars import SetFarmVars
8
7
  from .thrust2ct import Thrust2Ct
@@ -16,7 +16,7 @@ class Calculator(TurbineModel):
16
16
  func: Function
17
17
  The function: f(in0, in1, ..., stsel) -> (out0, ou1, ...)
18
18
  where inX and outY are numpy.ndarrays and
19
- st_sel is the boolean state-turbine selection.
19
+ st_sel is the state-turbine selection slice or array.
20
20
  All arrays have shape (n_states, n_turbines).
21
21
 
22
22
  :group: models.turbine_models
@@ -36,7 +36,7 @@ class Calculator(TurbineModel):
36
36
  func: Function
37
37
  The function: f(in0, in1, ..., stsel) -> (out0, ou1, ...)
38
38
  where inX and outY are numpy.ndarrays and
39
- st_sel is the boolean state-turbine selection.
39
+ st_sel is the state-turbine selection slice or array.
40
40
  All arrays have shape (n_states, n_turbines).
41
41
  kwargs: dict, optional
42
42
  Additional arguments for TurbineModel
@@ -47,6 +47,10 @@ class Calculator(TurbineModel):
47
47
  self.out_vars = out_vars
48
48
  self.func = func
49
49
 
50
+ def __repr__(self):
51
+ a = f"{self.in_vars}, {self.out_vars}"
52
+ return f"{type(self).__name__}({a})"
53
+
50
54
  def output_farm_vars(self, algo):
51
55
  """
52
56
  The variables which are being modified by the model.
@@ -65,7 +69,7 @@ class Calculator(TurbineModel):
65
69
  return self.out_vars
66
70
 
67
71
  def calculate(self, algo, mdata, fdata, st_sel):
68
- """ "
72
+ """
69
73
  The main model calculation.
70
74
 
71
75
  This function is executed on a single chunk of data,
@@ -75,13 +79,13 @@ class Calculator(TurbineModel):
75
79
  ----------
76
80
  algo: foxes.core.Algorithm
77
81
  The calculation algorithm
78
- mdata: foxes.core.Data
82
+ mdata: foxes.core.MData
79
83
  The model data
80
- fdata: foxes.core.Data
84
+ fdata: foxes.core.FData
81
85
  The farm data
82
- st_sel: numpy.ndarray of bool
86
+ st_sel: slice or numpy.ndarray of bool
83
87
  The state-turbine selection,
84
- shape: (n_states, n_turbines)
88
+ for shape: (n_states, n_turbines)
85
89
 
86
90
  Returns
87
91
  -------
@@ -51,10 +51,12 @@ class kTI(TurbineModel):
51
51
  setattr(self, FV.KB, 0 if kb is None else kb)
52
52
 
53
53
  def __repr__(self):
54
- return (
55
- super().__repr__()
56
- + f"({self.k_var}, kTI={getattr(self, FV.KTI)}, ti={self.ti_var})"
57
- )
54
+ kti = getattr(self, FV.KTI)
55
+ kb = getattr(self, FV.KB)
56
+ ti = getattr(self, self.ti_var)
57
+ tiv = f", ti_val={ti}" if ti is not None else ""
58
+ a = f"kTI={kti}, kb={kb}, ti_var={self.ti_var}{tiv}, k_var={self.k_var}"
59
+ return f"{type(self).__name__}({a})"
58
60
 
59
61
  def output_farm_vars(self, algo):
60
62
  """
@@ -74,7 +76,7 @@ class kTI(TurbineModel):
74
76
  return [self.k_var]
75
77
 
76
78
  def calculate(self, algo, mdata, fdata, st_sel):
77
- """ "
79
+ """
78
80
  The main model calculation.
79
81
 
80
82
  This function is executed on a single chunk of data,
@@ -84,13 +86,13 @@ class kTI(TurbineModel):
84
86
  ----------
85
87
  algo: foxes.core.Algorithm
86
88
  The calculation algorithm
87
- mdata: foxes.core.Data
89
+ mdata: foxes.core.MData
88
90
  The model data
89
- fdata: foxes.core.Data
91
+ fdata: foxes.core.FData
90
92
  The farm data
91
- st_sel: numpy.ndarray of bool
93
+ st_sel: slice or numpy.ndarray of bool
92
94
  The state-turbine selection,
93
- shape: (n_states, n_turbines)
95
+ for shape: (n_states, n_turbines)
94
96
 
95
97
  Returns
96
98
  -------
@@ -99,7 +101,7 @@ class kTI(TurbineModel):
99
101
  Values: numpy.ndarray with shape (n_states, n_turbines)
100
102
 
101
103
  """
102
- kTI = self.get_data(
104
+ kti = self.get_data(
103
105
  FV.KTI, FC.STATE_TURBINE, lookup="sf", fdata=fdata, upcast=True
104
106
  )[st_sel]
105
107
  kb = self.get_data(
@@ -113,6 +115,6 @@ class kTI(TurbineModel):
113
115
  self.k_var, np.zeros((fdata.n_states, fdata.n_turbines), dtype=FC.DTYPE)
114
116
  )
115
117
 
116
- k[st_sel] = kTI * ti + kb
118
+ k[st_sel] = kti * ti + kb
117
119
 
118
120
  return {self.k_var: k}