foxes 1.2.5__py3-none-any.whl → 1.4__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 (201) hide show
  1. docs/source/conf.py +3 -3
  2. examples/abl_states/run.py +2 -2
  3. examples/compare_rotors_pwakes/run.py +1 -1
  4. examples/compare_wakes/run.py +1 -2
  5. examples/dyn_wakes/run.py +29 -6
  6. examples/induction/run.py +3 -3
  7. examples/multi_height/run.py +1 -1
  8. examples/power_mask/run.py +2 -2
  9. examples/quickstart/run.py +16 -0
  10. examples/random_timeseries/run.py +3 -4
  11. examples/scan_row/run.py +3 -3
  12. examples/sequential/run.py +33 -10
  13. examples/single_state/run.py +3 -4
  14. examples/states_lookup_table/run.py +3 -3
  15. examples/streamline_wakes/run.py +27 -4
  16. examples/tab_file/run.py +3 -3
  17. examples/timelines/run.py +29 -5
  18. examples/timeseries/run.py +3 -3
  19. examples/timeseries_slurm/run.py +3 -3
  20. examples/wind_rose/run.py +3 -3
  21. examples/yawed_wake/run.py +16 -8
  22. foxes/__init__.py +22 -18
  23. foxes/algorithms/__init__.py +6 -6
  24. foxes/algorithms/downwind/__init__.py +2 -2
  25. foxes/algorithms/downwind/downwind.py +53 -27
  26. foxes/algorithms/downwind/models/__init__.py +6 -6
  27. foxes/algorithms/downwind/models/farm_wakes_calc.py +22 -14
  28. foxes/algorithms/downwind/models/init_farm_data.py +4 -5
  29. foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
  30. foxes/algorithms/downwind/models/reorder_farm_output.py +5 -1
  31. foxes/algorithms/downwind/models/set_amb_point_results.py +7 -7
  32. foxes/algorithms/iterative/__init__.py +7 -3
  33. foxes/algorithms/iterative/iterative.py +1 -2
  34. foxes/algorithms/iterative/models/__init__.py +7 -3
  35. foxes/algorithms/iterative/models/farm_wakes_calc.py +15 -8
  36. foxes/algorithms/sequential/__init__.py +3 -3
  37. foxes/algorithms/sequential/models/__init__.py +2 -2
  38. foxes/algorithms/sequential/models/seq_state.py +0 -18
  39. foxes/algorithms/sequential/sequential.py +8 -22
  40. foxes/config/__init__.py +5 -1
  41. foxes/constants.py +22 -0
  42. foxes/core/__init__.py +45 -22
  43. foxes/core/algorithm.py +0 -1
  44. foxes/core/data.py +56 -29
  45. foxes/core/engine.py +28 -14
  46. foxes/core/farm_controller.py +2 -2
  47. foxes/core/farm_data_model.py +1 -0
  48. foxes/core/ground_model.py +4 -13
  49. foxes/core/model.py +5 -5
  50. foxes/core/partial_wakes_model.py +147 -10
  51. foxes/core/point_data_model.py +2 -3
  52. foxes/core/rotor_model.py +42 -38
  53. foxes/core/states.py +4 -50
  54. foxes/core/turbine.py +2 -1
  55. foxes/core/wake_deflection.py +130 -0
  56. foxes/core/wake_model.py +222 -9
  57. foxes/core/wake_superposition.py +122 -4
  58. foxes/core/wind_farm.py +6 -6
  59. foxes/data/__init__.py +7 -2
  60. foxes/data/states/weibull_sectors_12.csv +13 -0
  61. foxes/data/states/weibull_sectors_12.nc +0 -0
  62. foxes/engines/__init__.py +14 -15
  63. foxes/engines/dask.py +39 -14
  64. foxes/engines/numpy.py +0 -3
  65. foxes/input/__init__.py +3 -3
  66. foxes/input/farm_layout/__init__.py +8 -8
  67. foxes/input/farm_layout/from_csv.py +1 -1
  68. foxes/input/farm_layout/ring.py +0 -1
  69. foxes/input/states/__init__.py +22 -11
  70. foxes/input/states/create/__init__.py +3 -2
  71. foxes/input/states/field_data_nc.py +48 -84
  72. foxes/input/states/multi_height.py +40 -60
  73. foxes/input/states/one_point_flow.py +22 -25
  74. foxes/input/states/scan.py +6 -19
  75. foxes/input/states/single.py +6 -18
  76. foxes/input/states/states_table.py +25 -44
  77. foxes/input/states/weibull_sectors.py +225 -0
  78. foxes/input/states/wrg_states.py +151 -37
  79. foxes/input/yaml/__init__.py +9 -3
  80. foxes/input/yaml/dict.py +19 -19
  81. foxes/input/yaml/windio/__init__.py +10 -5
  82. foxes/input/yaml/windio/read_attributes.py +2 -2
  83. foxes/input/yaml/windio/read_farm.py +5 -5
  84. foxes/input/yaml/windio/read_fields.py +4 -2
  85. foxes/input/yaml/windio/read_site.py +52 -0
  86. foxes/input/yaml/windio/windio.py +1 -1
  87. foxes/models/__init__.py +15 -14
  88. foxes/models/axial_induction/__init__.py +2 -2
  89. foxes/models/farm_controllers/__init__.py +1 -1
  90. foxes/models/farm_models/__init__.py +1 -1
  91. foxes/models/ground_models/__init__.py +3 -2
  92. foxes/models/ground_models/wake_mirror.py +3 -3
  93. foxes/models/model_book.py +175 -49
  94. foxes/models/partial_wakes/__init__.py +6 -6
  95. foxes/models/partial_wakes/axiwake.py +30 -5
  96. foxes/models/partial_wakes/centre.py +47 -0
  97. foxes/models/partial_wakes/rotor_points.py +45 -9
  98. foxes/models/partial_wakes/segregated.py +2 -20
  99. foxes/models/partial_wakes/top_hat.py +27 -2
  100. foxes/models/point_models/__init__.py +4 -4
  101. foxes/models/rotor_models/__init__.py +3 -3
  102. foxes/models/rotor_models/centre.py +6 -4
  103. foxes/models/turbine_models/__init__.py +11 -11
  104. foxes/models/turbine_models/set_farm_vars.py +0 -1
  105. foxes/models/turbine_types/PCt_file.py +0 -2
  106. foxes/models/turbine_types/PCt_from_two.py +0 -2
  107. foxes/models/turbine_types/__init__.py +9 -9
  108. foxes/models/vertical_profiles/__init__.py +7 -7
  109. foxes/models/wake_deflections/__init__.py +3 -0
  110. foxes/models/{wake_frames/yawed_wakes.py → wake_deflections/bastankhah2016.py} +32 -111
  111. foxes/models/wake_deflections/jimenez.py +277 -0
  112. foxes/models/wake_deflections/no_deflection.py +94 -0
  113. foxes/models/wake_frames/__init__.py +6 -7
  114. foxes/models/wake_frames/dynamic_wakes.py +12 -3
  115. foxes/models/wake_frames/rotor_wd.py +3 -1
  116. foxes/models/wake_frames/seq_dynamic_wakes.py +45 -8
  117. foxes/models/wake_frames/streamlines.py +8 -6
  118. foxes/models/wake_frames/timelines.py +19 -3
  119. foxes/models/wake_models/__init__.py +7 -7
  120. foxes/models/wake_models/dist_sliced.py +50 -84
  121. foxes/models/wake_models/gaussian.py +20 -0
  122. foxes/models/wake_models/induction/__init__.py +5 -5
  123. foxes/models/wake_models/induction/rankine_half_body.py +30 -71
  124. foxes/models/wake_models/induction/rathmann.py +65 -64
  125. foxes/models/wake_models/induction/self_similar.py +65 -68
  126. foxes/models/wake_models/induction/self_similar2020.py +0 -3
  127. foxes/models/wake_models/induction/vortex_sheet.py +71 -75
  128. foxes/models/wake_models/ti/__init__.py +2 -2
  129. foxes/models/wake_models/ti/crespo_hernandez.py +5 -3
  130. foxes/models/wake_models/ti/iec_ti.py +6 -4
  131. foxes/models/wake_models/top_hat.py +58 -7
  132. foxes/models/wake_models/wind/__init__.py +6 -4
  133. foxes/models/wake_models/wind/bastankhah14.py +25 -7
  134. foxes/models/wake_models/wind/bastankhah16.py +35 -3
  135. foxes/models/wake_models/wind/jensen.py +15 -2
  136. foxes/models/wake_models/wind/turbopark.py +28 -2
  137. foxes/models/wake_superpositions/__init__.py +18 -9
  138. foxes/models/wake_superpositions/ti_linear.py +4 -4
  139. foxes/models/wake_superpositions/ti_max.py +4 -4
  140. foxes/models/wake_superpositions/ti_pow.py +4 -4
  141. foxes/models/wake_superpositions/ti_quadratic.py +4 -4
  142. foxes/models/wake_superpositions/wind_vector.py +257 -0
  143. foxes/models/wake_superpositions/ws_linear.py +9 -10
  144. foxes/models/wake_superpositions/ws_max.py +8 -8
  145. foxes/models/wake_superpositions/ws_pow.py +8 -8
  146. foxes/models/wake_superpositions/ws_product.py +4 -4
  147. foxes/models/wake_superpositions/ws_quadratic.py +8 -8
  148. foxes/output/__init__.py +21 -19
  149. foxes/output/farm_layout.py +14 -6
  150. foxes/output/farm_results_eval.py +51 -27
  151. foxes/output/flow_plots_2d/__init__.py +2 -2
  152. foxes/output/flow_plots_2d/get_fig.py +4 -2
  153. foxes/output/rose_plot.py +23 -5
  154. foxes/output/seq_plugins/__init__.py +2 -2
  155. foxes/output/seq_plugins/seq_flow_ani_plugin.py +0 -3
  156. foxes/output/seq_plugins/seq_wake_debug_plugin.py +0 -1
  157. foxes/output/slice_data.py +16 -19
  158. foxes/output/turbine_type_curves.py +7 -8
  159. foxes/utils/__init__.py +37 -19
  160. foxes/utils/abl/__init__.py +4 -4
  161. foxes/utils/cubic_roots.py +1 -1
  162. foxes/utils/data_book.py +4 -3
  163. foxes/utils/dict.py +3 -3
  164. foxes/utils/exec_python.py +5 -5
  165. foxes/utils/factory.py +1 -3
  166. foxes/utils/geom2d/__init__.py +7 -5
  167. foxes/utils/geopandas_utils.py +2 -2
  168. foxes/utils/pandas_utils.py +4 -3
  169. foxes/utils/tab_files.py +0 -1
  170. foxes/utils/weibull.py +28 -0
  171. foxes/utils/wrg_utils.py +3 -1
  172. foxes/utils/xarray_utils.py +9 -2
  173. foxes/variables.py +67 -9
  174. {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/METADATA +14 -21
  175. foxes-1.4.dist-info/RECORD +320 -0
  176. {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/WHEEL +1 -1
  177. tests/0_consistency/iterative/test_iterative.py +2 -3
  178. tests/0_consistency/partial_wakes/test_partial_wakes.py +2 -2
  179. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +2 -3
  180. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +48 -56
  181. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
  182. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +33 -36
  183. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +0 -1
  184. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +0 -2
  185. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +3 -3
  186. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +3 -4
  187. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +3 -4
  188. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +3 -4
  189. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +3 -4
  190. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
  191. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +3 -3
  192. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +3 -3
  193. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +0 -1
  194. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +3 -4
  195. tests/3_examples/test_examples.py +3 -2
  196. foxes/output/round.py +0 -10
  197. foxes/utils/pandas_helpers.py +0 -178
  198. foxes-1.2.5.dist-info/RECORD +0 -312
  199. {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/entry_points.txt +0 -0
  200. {foxes-1.2.5.dist-info → foxes-1.4.dist-info/licenses}/LICENSE +0 -0
  201. {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/top_level.txt +0 -0
foxes/core/wake_model.py CHANGED
@@ -1,11 +1,10 @@
1
1
  from abc import abstractmethod
2
- import numpy as np
3
2
 
4
3
  from foxes.utils import new_instance
5
4
  import foxes.variables as FV
6
- import foxes.constants as FC
7
5
 
8
6
  from .model import Model
7
+ from .wake_superposition import WindVectorWakeSuperposition
9
8
 
10
9
 
11
10
  class WakeModel(Model):
@@ -16,6 +15,26 @@ class WakeModel(Model):
16
15
 
17
16
  """
18
17
 
18
+ def __init__(self):
19
+ """
20
+ Constructor.
21
+ """
22
+ super().__init__()
23
+ self._has_uv = False
24
+
25
+ @property
26
+ def affects_ws(self):
27
+ """
28
+ Flag for wind speed wake models
29
+
30
+ Returns
31
+ -------
32
+ dws: bool
33
+ If True, this model affects wind speed
34
+
35
+ """
36
+ return False
37
+
19
38
  @property
20
39
  def affects_downwind(self):
21
40
  """
@@ -30,6 +49,38 @@ class WakeModel(Model):
30
49
  """
31
50
  return True
32
51
 
52
+ @property
53
+ def has_uv(self):
54
+ """
55
+ This model uses wind vector data
56
+
57
+ Returns
58
+ -------
59
+ hasuv: bool
60
+ Flag for wind vector data
61
+
62
+ """
63
+ return self._has_uv
64
+
65
+ def initialize(self, algo, verbosity=0, force=False):
66
+ """
67
+ Initializes the model.
68
+
69
+ Parameters
70
+ ----------
71
+ algo: foxes.core.Algorithm
72
+ The calculation algorithm
73
+ verbosity: int
74
+ The verbosity level, 0 = silent
75
+ force: bool
76
+ Overwrite existing data
77
+
78
+ """
79
+ if self.affects_ws and algo.wake_deflection.has_uv:
80
+ self._has_uv = True
81
+ super().initialize(algo, verbosity, force)
82
+
83
+ @abstractmethod
33
84
  def new_wake_deltas(self, algo, mdata, fdata, tdata):
34
85
  """
35
86
  Creates new empty wake delta arrays.
@@ -52,7 +103,7 @@ class WakeModel(Model):
52
103
  wake deltas, shape: (n_states, n_targets, n_tpoints, ...)
53
104
 
54
105
  """
55
- return {FV.WS: np.zeros_like(tdata[FC.TARGETS][..., 0])}
106
+ pass
56
107
 
57
108
  @abstractmethod
58
109
  def contribute(
@@ -98,7 +149,7 @@ class WakeModel(Model):
98
149
  algo,
99
150
  mdata,
100
151
  fdata,
101
- amb_results,
152
+ tdata,
102
153
  wake_deltas,
103
154
  ):
104
155
  """
@@ -114,10 +165,8 @@ class WakeModel(Model):
114
165
  The model data
115
166
  fdata: foxes.core.FData
116
167
  The farm data
117
- amb_results: dict
118
- The ambient results, key: variable name str,
119
- values: numpy.ndarray with shape
120
- (n_states, n_targets, n_tpoints)
168
+ tdata: foxes.core.TData
169
+ The target point data
121
170
  wake_deltas: dict
122
171
  The wake deltas object at the selected target
123
172
  turbines. Key: variable str, value: numpy.ndarray
@@ -144,7 +193,171 @@ class WakeModel(Model):
144
193
  return new_instance(cls, wmodel_type, *args, **kwargs)
145
194
 
146
195
 
147
- class TurbineInductionModel(WakeModel):
196
+ class SingleTurbineWakeModel(WakeModel):
197
+ """
198
+ Abstract base class for wake models that represent
199
+ a single turbine wake
200
+
201
+ Single turbine wake models depend on superposition models.
202
+
203
+ Attributes
204
+ ----------
205
+ wind_superposition: str
206
+ The wind superposition model name (vector or compenent model),
207
+ will be looked up in model book
208
+ other_superpositions: dict
209
+ The superpositions for other than (ws, wd) variables.
210
+ Key: variable name str, value: The wake superposition
211
+ model name, will be looked up in model book
212
+ vec_superp: foxes.core.WindVectorWakeSuperposition or None
213
+ The wind vector wake superposition model
214
+ superp: dict
215
+ The superposition dict, key: variable name str,
216
+ value: `foxes.core.WakeSuperposition`
217
+
218
+ :group: models.wake_models
219
+
220
+ """
221
+
222
+ def __init__(self, wind_superposition=None, other_superpositions={}):
223
+ """
224
+ Constructor.
225
+
226
+ Parameters
227
+ ----------
228
+ wind_superposition: str, optional
229
+ The wind superposition model name (vector or compenent model),
230
+ will be looked up in model book
231
+ other_superpositions: dict
232
+ The superpositions for other than (ws, wd) variables.
233
+ Key: variable name str, value: The wake superposition
234
+ model name, will be looked up in model book
235
+
236
+ """
237
+ super().__init__()
238
+ self.wind_superposition = wind_superposition
239
+ self.other_superpositions = other_superpositions
240
+ self.vec_superp = None
241
+ self.superp = {}
242
+
243
+ for v in [FV.WS, FV.WD]:
244
+ assert v not in other_superpositions, (
245
+ f"Wake model '{self.name}': Found variable '{v}' among 'other_superposition' keyword, use 'wind_superposition' instead"
246
+ )
247
+
248
+ self.__has_vector_superp = False
249
+
250
+ @property
251
+ def has_vector_wind_superp(self):
252
+ """
253
+ This model uses a wind vector superposition
254
+
255
+ Returns
256
+ -------
257
+ hasv: bool
258
+ Flag for wind vector superposition
259
+
260
+ """
261
+ return self.__has_vector_superp
262
+
263
+ def sub_models(self):
264
+ """
265
+ List of all sub-models
266
+
267
+ Returns
268
+ -------
269
+ smdls: list of foxes.core.Model
270
+ Names of all sub models
271
+
272
+ """
273
+ w = [self.vec_superp] if self.vec_superp is not None else []
274
+ return w + list(self.superp.values())
275
+
276
+ def initialize(self, algo, verbosity=0, force=False):
277
+ """
278
+ Initializes the model.
279
+
280
+ Parameters
281
+ ----------
282
+ algo: foxes.core.Algorithm
283
+ The calculation algorithm
284
+ verbosity: int
285
+ The verbosity level, 0 = silent
286
+ force: bool
287
+ Overwrite existing data
288
+
289
+ """
290
+ self.superp = {
291
+ v: algo.mbook.wake_superpositions[s]
292
+ for v, s in self.other_superpositions.items()
293
+ }
294
+
295
+ if self.wind_superposition is not None:
296
+ self.vec_superp = algo.mbook.wake_superpositions[self.wind_superposition]
297
+ self.__has_vector_superp = isinstance(
298
+ self.vec_superp, WindVectorWakeSuperposition
299
+ )
300
+ if self.__has_vector_superp:
301
+ self._has_uv = True
302
+ else:
303
+ self.superp[FV.WS] = self.vec_superp
304
+ self.vec_superp = None
305
+
306
+ super().initialize(algo, verbosity, force)
307
+
308
+ def finalize_wake_deltas(
309
+ self,
310
+ algo,
311
+ mdata,
312
+ fdata,
313
+ tdata,
314
+ wake_deltas,
315
+ ):
316
+ """
317
+ Finalize the wake calculation.
318
+
319
+ Modifies wake_deltas on the fly.
320
+
321
+ Parameters
322
+ ----------
323
+ algo: foxes.core.Algorithm
324
+ The calculation algorithm
325
+ mdata: foxes.core.MData
326
+ The model data
327
+ fdata: foxes.core.FData
328
+ The farm data
329
+ tdata: foxes.core.TData
330
+ The target point data
331
+ wake_deltas: dict
332
+ The wake deltas object at the selected target
333
+ turbines. Key: variable str, value: numpy.ndarray
334
+ with shape (n_states, n_targets, n_tpoints)
335
+
336
+ """
337
+ for v in wake_deltas.keys():
338
+ if v != FV.UV:
339
+ try:
340
+ wake_deltas[v] = self.superp[v].calc_final_wake_delta(
341
+ algo, mdata, fdata, tdata, v, wake_deltas[v]
342
+ )
343
+ except KeyError:
344
+ raise KeyError(
345
+ f"Wake model '{self.name}': Variable '{v}' appears to be modified, missing superposition model"
346
+ )
347
+
348
+ if FV.UV in wake_deltas:
349
+ assert self.has_vector_wind_superp, (
350
+ f"{self.name}: Expecting wind vector superposition, got '{self.wind_superposition}'"
351
+ )
352
+ dws, dwd = self.vec_superp.calc_final_wake_delta_uv(
353
+ algo, mdata, fdata, tdata, wake_deltas.pop(FV.UV)
354
+ )
355
+
356
+ wake_deltas[FV.WS] = dws
357
+ wake_deltas[FV.WD] = dwd
358
+
359
+
360
+ class TurbineInductionModel(SingleTurbineWakeModel):
148
361
  """
149
362
  Abstract base class for turbine induction models.
150
363
 
@@ -74,8 +74,8 @@ class WakeSuperposition(Model):
74
74
  algo,
75
75
  mdata,
76
76
  fdata,
77
+ tdata,
77
78
  variable,
78
- amb_results,
79
79
  wake_delta,
80
80
  ):
81
81
  """
@@ -90,11 +90,10 @@ class WakeSuperposition(Model):
90
90
  The model data
91
91
  fdata: foxes.core.FData
92
92
  The farm data
93
+ tdata: foxes.core.TData
94
+ The target point data
93
95
  variable: str
94
96
  The variable name for which the wake deltas applies
95
- amb_results: numpy.ndarray
96
- The ambient results at targets,
97
- shape: (n_states, n_targets, n_tpoints)
98
97
  wake_delta: numpy.ndarray
99
98
  The wake deltas at targets, shape:
100
99
  (n_states, n_targets, n_tpoints)
@@ -125,3 +124,122 @@ class WakeSuperposition(Model):
125
124
 
126
125
  """
127
126
  return new_instance(cls, superp_type, *args, **kwargs)
127
+
128
+
129
+ class WindVectorWakeSuperposition(Model):
130
+ """
131
+ Base class for wind vector superposition.
132
+
133
+ Note that it is a matter of the wake model
134
+ if superposition models are used, or if the
135
+ wake model computes the total wake result by
136
+ other means.
137
+
138
+ :group: core
139
+
140
+ """
141
+
142
+ @abstractmethod
143
+ def add_wake_vector(
144
+ self,
145
+ algo,
146
+ mdata,
147
+ fdata,
148
+ tdata,
149
+ downwind_index,
150
+ st_sel,
151
+ wake_delta_uv,
152
+ wake_model_result_uv,
153
+ ):
154
+ """
155
+ Add a wake delta vector to previous wake deltas,
156
+ at rotor points.
157
+
158
+ Parameters
159
+ ----------
160
+ algo: foxes.core.Algorithm
161
+ The calculation algorithm
162
+ mdata: foxes.core.MData
163
+ The model data
164
+ fdata: foxes.core.FData
165
+ The farm data
166
+ tdata: foxes.core.TData
167
+ The target point data
168
+ downwind_index: int
169
+ The index of the wake causing turbine
170
+ in the downwind order
171
+ st_sel: numpy.ndarray of bool
172
+ The selection of targets, shape: (n_states, n_targets)
173
+ wake_delta_uv: numpy.ndarray
174
+ The original wind vector wake deltas, shape:
175
+ (n_states, n_targets, n_tpoints, 2)
176
+ wake_model_result_uv: numpy.ndarray
177
+ The new wind vector wake deltas of the selected rotors,
178
+ shape: (n_st_sel, n_tpoints, 2, ...)
179
+
180
+ Returns
181
+ -------
182
+ wdelta_uv: numpy.ndarray
183
+ The updated wind vector wake deltas, shape:
184
+ (n_states, n_targets, n_tpoints, ...)
185
+
186
+ """
187
+ pass
188
+
189
+ @abstractmethod
190
+ def calc_final_wake_delta_uv(
191
+ self,
192
+ algo,
193
+ mdata,
194
+ fdata,
195
+ tdata,
196
+ wake_delta_uv,
197
+ ):
198
+ """
199
+ Calculate the final wind vector wake delta after adding all
200
+ contributions.
201
+
202
+ Parameters
203
+ ----------
204
+ algo: foxes.core.Algorithm
205
+ The calculation algorithm
206
+ mdata: foxes.core.MData
207
+ The model data
208
+ fdata: foxes.core.FData
209
+ The farm data
210
+ tdata: foxes.core.TData
211
+ The target point data
212
+ wake_delta_uv: numpy.ndarray
213
+ The original wind vector wake deltas, shape:
214
+ (n_states, n_targets, n_tpoints, 2)
215
+
216
+ Returns
217
+ -------
218
+ final_wake_delta_ws: numpy.ndarray
219
+ The final wind speed wake delta, which will be added to
220
+ the ambient results by simple plus operation. Shape:
221
+ (n_states, n_targets, n_tpoints)
222
+ final_wake_delta_wd: numpy.ndarray
223
+ The final wind direction wake delta, which will be added to
224
+ the ambient results by simple plus operation. Shape:
225
+ (n_states, n_targets, n_tpoints)
226
+
227
+ """
228
+ pass
229
+
230
+ @classmethod
231
+ def new(cls, superp_type, *args, **kwargs):
232
+ """
233
+ Run-time wind wake superposition model factory.
234
+
235
+ Parameters
236
+ ----------
237
+ superp_type: str
238
+ The selected derived class name
239
+ args: tuple, optional
240
+ Additional parameters for constructor
241
+ kwargs: dict, optional
242
+ Additional parameters for constructor
243
+
244
+ """
245
+ return new_instance(cls, superp_type, *args, **kwargs)
foxes/core/wind_farm.py CHANGED
@@ -124,12 +124,12 @@ class WindFarm:
124
124
 
125
125
  if extra_space is not None:
126
126
  if isinstance(extra_space, str):
127
- assert (
128
- algo is not None
129
- ), f"WindFarm: require algo argument for extra_space '{extra_space}'"
130
- assert (
131
- len(extra_space) > 1 and extra_space[-1] == "D"
132
- ), f"Expecting float or str like '2.5D', got extra_space = '{extra_space}'"
127
+ assert algo is not None, (
128
+ f"WindFarm: require algo argument for extra_space '{extra_space}'"
129
+ )
130
+ assert len(extra_space) > 1 and extra_space[-1] == "D", (
131
+ f"Expecting float or str like '2.5D', got extra_space = '{extra_space}'"
132
+ )
133
133
  extra_space = float(extra_space[:-1])
134
134
  rds = self.get_rotor_diameters(algo)
135
135
  if xy is None:
foxes/data/__init__.py CHANGED
@@ -2,5 +2,10 @@
2
2
  Static data collection.
3
3
  """
4
4
 
5
- from .parse import parse_Pct_file_name, parse_Pct_two_files
6
- from .static_data import FARM, STATES, PCTCURVE, StaticData
5
+ from .parse import parse_Pct_file_name as parse_Pct_file_name
6
+ from .parse import parse_Pct_two_files as parse_Pct_two_files
7
+
8
+ from .static_data import FARM as FARM
9
+ from .static_data import STATES as STATES
10
+ from .static_data import PCTCURVE as PCTCURVE
11
+ from .static_data import StaticData as StaticData
@@ -0,0 +1,13 @@
1
+ sector,wind_direction,sector_probability,weibull_a,weibull_k,turbulence_intensity
2
+ 0,0.0,0.0359715203597152,9.176929,2.392578,0.1
3
+ 1,30.0,0.0394868203948682,9.782334,2.447266,0.1
4
+ 2,60.0,0.0516739505167395,9.531809,2.412109,0.1
5
+ 3,90.0,0.07000154070001541,9.909545,2.591797,0.1
6
+ 4,120.0,0.08364547083645471,10.04269,2.755859,0.1
7
+ 5,150.0,0.064348500643485,9.593921,2.595703,0.1
8
+ 6,180.0,0.0864319408643194,9.584007,2.583984,0.1
9
+ 7,210.0,0.117705101177051,10.51499,2.548828,0.1
10
+ 8,240.0,0.151575701515757,11.39895,2.470703,0.1
11
+ 9,270.0,0.14737920147379202,11.68746,2.607422,0.1
12
+ 10,300.0,0.10012050100120501,11.63732,2.626953,0.1
13
+ 11,330.0,0.051659750516597505,10.08803,2.326172,0.1
Binary file
foxes/engines/__init__.py CHANGED
@@ -1,17 +1,16 @@
1
- from .pool import PoolEngine
2
- from .multiprocess import MultiprocessEngine
3
- from .numpy import NumpyEngine
4
- from .single import SingleChunkEngine
5
- from .futures import ThreadsEngine, ProcessEngine
6
- from .mpi import MPIEngine
7
- from .ray import RayEngine
1
+ from .pool import PoolEngine as PoolEngine
2
+ from .multiprocess import MultiprocessEngine as MultiprocessEngine
3
+ from .numpy import NumpyEngine as NumpyEngine
4
+ from .single import SingleChunkEngine as SingleChunkEngine
5
+ from .mpi import MPIEngine as MPIEngine
6
+ from .ray import RayEngine as RayEngine
7
+ from .default import DefaultEngine as DefaultEngine
8
8
 
9
- from .dask import (
10
- DaskBaseEngine,
11
- XArrayEngine,
12
- DaskEngine,
13
- LocalClusterEngine,
14
- SlurmClusterEngine,
15
- )
9
+ from .futures import ThreadsEngine as ThreadsEngine
10
+ from .futures import ProcessEngine as ProcessEngine
16
11
 
17
- from .default import DefaultEngine
12
+ from .dask import DaskBaseEngine as DaskBaseEngine
13
+ from .dask import XArrayEngine as XArrayEngine
14
+ from .dask import DaskEngine as DaskEngine
15
+ from .dask import LocalClusterEngine as LocalClusterEngine
16
+ from .dask import SlurmClusterEngine as SlurmClusterEngine
foxes/engines/dask.py CHANGED
@@ -222,19 +222,28 @@ def _run_as_ufunc(
222
222
  if i == 0:
223
223
  data.append(
224
224
  MData(
225
- data=hdata, dims=hdims, loop_dims=loop_dims, states_i0=state_inds[0]
225
+ data=hdata,
226
+ dims=hdims,
227
+ # loop_dims=loop_dims,
228
+ states_i0=state_inds[0],
226
229
  )
227
230
  )
228
231
  elif i == 1:
229
232
  data.append(
230
233
  FData(
231
- data=hdata, dims=hdims, loop_dims=loop_dims, states_i0=state_inds[0]
234
+ data=hdata,
235
+ dims=hdims,
236
+ # loop_dims=loop_dims,
237
+ states_i0=state_inds[0],
232
238
  )
233
239
  )
234
240
  elif i == 2:
235
241
  data.append(
236
242
  TData(
237
- data=hdata, dims=hdims, loop_dims=loop_dims, states_i0=state_inds[0]
243
+ data=hdata,
244
+ dims=hdims,
245
+ # loop_dims=loop_dims,
246
+ states_i0=state_inds[0],
238
247
  )
239
248
  )
240
249
  else:
@@ -246,13 +255,13 @@ def _run_as_ufunc(
246
255
 
247
256
  # deduce output shape:
248
257
  oshape = []
249
- for li, l in enumerate(out_coords):
258
+ for li, ld in enumerate(out_coords):
250
259
  for i, dims in enumerate(ldims):
251
- if l in dims:
252
- oshape.append(ldata[i].shape[dims.index(l)])
260
+ if ld in dims:
261
+ oshape.append(ldata[i].shape[dims.index(ld)])
253
262
  break
254
263
  if len(oshape) != li + 1:
255
- raise ValueError(f"Failed to find loop dimension")
264
+ raise ValueError("Failed to find loop dimension")
256
265
 
257
266
  # add zero output data arrays:
258
267
  odims = {v: tuple(out_coords) for v in out_vars}
@@ -267,14 +276,31 @@ def _run_as_ufunc(
267
276
  }
268
277
 
269
278
  if len(data) == 1:
270
- data.append(FData(odata, odims, loop_dims, states_i0=state_inds[0]))
279
+ data.append(
280
+ FData(
281
+ odata,
282
+ odims,
283
+ # loop_dims,
284
+ states_i0=state_inds[0],
285
+ )
286
+ )
271
287
  else:
272
288
  odata.update(data[-1])
273
289
  odims.update(data[-1].dims)
274
290
  if len(data) == 2:
275
- data[-1] = FData(odata, odims, loop_dims, states_i0=state_inds[0])
291
+ data[-1] = FData(
292
+ odata,
293
+ odims,
294
+ # loop_dims,
295
+ states_i0=state_inds[0],
296
+ )
276
297
  else:
277
- data[-1] = TData(odata, odims, loop_dims, states_i0=state_inds[0])
298
+ data[-1] = TData(
299
+ odata,
300
+ odims,
301
+ # loop_dims,
302
+ states_i0=state_inds[0],
303
+ )
278
304
  del odims, odata
279
305
 
280
306
  # link chunk state indices from mdata to fdata and tdata:
@@ -451,7 +477,6 @@ class XArrayEngine(DaskBaseEngine):
451
477
  if d is not None
452
478
  ]
453
479
  for ds in data:
454
-
455
480
  hvarsl = [v for v, d in ds.items() if len(loopd.intersection(d.dims))]
456
481
  ldata += [ds[v] for v in hvarsl]
457
482
  ldims += [ds[v].dims for v in hvarsl]
@@ -734,7 +759,7 @@ def _run_on_cluster(
734
759
  mdata = MData(
735
760
  data={names[i]: data[i] for i in range(mdata_size)},
736
761
  dims={names[i]: dims[i] for i in range(mdata_size)},
737
- loop_dims=loop_dims[0],
762
+ # loop_dims=loop_dims[0],
738
763
  states_i0=i0_states,
739
764
  )
740
765
 
@@ -742,7 +767,7 @@ def _run_on_cluster(
742
767
  fdata = FData(
743
768
  data={names[i]: data[i].copy() for i in range(mdata_size, fdata_end)},
744
769
  dims={names[i]: dims[i] for i in range(mdata_size, fdata_end)},
745
- loop_dims=loop_dims[1],
770
+ # loop_dims=loop_dims[1],
746
771
  states_i0=i0_states,
747
772
  )
748
773
 
@@ -751,7 +776,7 @@ def _run_on_cluster(
751
776
  tdata = TData(
752
777
  data={names[i]: data[i].copy() for i in range(fdata_end, len(data))},
753
778
  dims={names[i]: dims[i] for i in range(fdata_end, len(data))},
754
- loop_dims=loop_dims[2],
779
+ # loop_dims=loop_dims[2],
755
780
  states_i0=i0_states,
756
781
  )
757
782
 
foxes/engines/numpy.py CHANGED
@@ -1,6 +1,5 @@
1
1
  from tqdm import tqdm
2
2
  from xarray import Dataset
3
- from tqdm import tqdm
4
3
 
5
4
  from foxes.core import Engine
6
5
  import foxes.constants as FC
@@ -146,8 +145,6 @@ class NumpyEngine(Engine):
146
145
  for chunki_points in range(n_chunks_targets):
147
146
  i1_targets = i0_targets + chunk_sizes_targets[chunki_points]
148
147
 
149
- i = chunki_states * n_chunks_targets + chunki_points
150
-
151
148
  # get this chunk's data:
152
149
  data = self.get_chunk_input_data(
153
150
  algo=algo,
foxes/input/__init__.py CHANGED
@@ -2,6 +2,6 @@
2
2
  Functions and classes for input data definition.
3
3
  """
4
4
 
5
- from . import farm_layout
6
- from . import states
7
- from . import yaml
5
+ from . import farm_layout as farm_layout
6
+ from . import states as states
7
+ from . import yaml as yaml
@@ -2,11 +2,11 @@
2
2
  Functions for adding turbines to the wind farm.
3
3
  """
4
4
 
5
- from .row import add_row
6
- from .grid import add_grid
7
- from .from_json import add_from_json
8
- from .from_csv import add_from_csv
9
- from .from_file import add_from_file
10
- from .from_df import add_from_df
11
- from .from_random import add_random
12
- from .ring import add_ring
5
+ from .row import add_row as add_row
6
+ from .grid import add_grid as add_grid
7
+ from .from_json import add_from_json as add_from_json
8
+ from .from_csv import add_from_csv as add_from_csv
9
+ from .from_file import add_from_file as add_from_file
10
+ from .from_df import add_from_df as add_from_df
11
+ from .from_random import add_random as add_random
12
+ from .ring import add_ring as add_ring
@@ -86,7 +86,7 @@ def add_from_csv(
86
86
  for i in data.index:
87
87
  s = 1 if turbine_base_name_count_shift else 0
88
88
  tname = (
89
- f"{turbine_base_name}{i+s}" if col_name is None else data.loc[i, col_name]
89
+ f"{turbine_base_name}{i + s}" if col_name is None else data.loc[i, col_name]
90
90
  )
91
91
  txy = data.loc[i, [col_x, col_y]].values
92
92
 
@@ -49,7 +49,6 @@ def add_ring(
49
49
  da = 360 / n_turbines
50
50
 
51
51
  for i in range(n_turbines):
52
-
53
52
  n = wd2wdvec(a)[0]
54
53
 
55
54
  farm.add_turbine(