foxes 1.3__py3-none-any.whl → 1.5__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 (228) 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/field_data_nc/run.py +1 -1
  7. examples/induction/run.py +3 -3
  8. examples/multi_height/run.py +1 -1
  9. examples/power_mask/run.py +2 -2
  10. examples/quickstart/run.py +0 -1
  11. examples/random_timeseries/run.py +3 -4
  12. examples/scan_row/run.py +3 -3
  13. examples/sequential/run.py +33 -10
  14. examples/single_state/run.py +3 -4
  15. examples/states_lookup_table/run.py +3 -3
  16. examples/streamline_wakes/run.py +29 -6
  17. examples/tab_file/run.py +3 -3
  18. examples/timelines/run.py +29 -5
  19. examples/timeseries/run.py +3 -3
  20. examples/timeseries_slurm/run.py +3 -3
  21. examples/wind_rose/run.py +3 -3
  22. examples/yawed_wake/run.py +19 -9
  23. foxes/__init__.py +21 -17
  24. foxes/algorithms/__init__.py +6 -6
  25. foxes/algorithms/downwind/__init__.py +2 -2
  26. foxes/algorithms/downwind/downwind.py +49 -17
  27. foxes/algorithms/downwind/models/__init__.py +6 -6
  28. foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -9
  29. foxes/algorithms/downwind/models/init_farm_data.py +58 -29
  30. foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
  31. foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
  32. foxes/algorithms/downwind/models/set_amb_point_results.py +6 -6
  33. foxes/algorithms/iterative/__init__.py +7 -3
  34. foxes/algorithms/iterative/iterative.py +1 -2
  35. foxes/algorithms/iterative/models/__init__.py +7 -3
  36. foxes/algorithms/iterative/models/farm_wakes_calc.py +9 -5
  37. foxes/algorithms/sequential/__init__.py +3 -3
  38. foxes/algorithms/sequential/models/__init__.py +2 -2
  39. foxes/algorithms/sequential/sequential.py +3 -4
  40. foxes/config/__init__.py +5 -1
  41. foxes/constants.py +16 -0
  42. foxes/core/__init__.py +45 -22
  43. foxes/core/algorithm.py +5 -6
  44. foxes/core/data.py +94 -22
  45. foxes/core/data_calc_model.py +4 -2
  46. foxes/core/engine.py +42 -53
  47. foxes/core/farm_controller.py +2 -2
  48. foxes/core/farm_data_model.py +16 -13
  49. foxes/core/ground_model.py +4 -13
  50. foxes/core/model.py +24 -6
  51. foxes/core/partial_wakes_model.py +147 -10
  52. foxes/core/point_data_model.py +21 -17
  53. foxes/core/rotor_model.py +4 -3
  54. foxes/core/states.py +2 -3
  55. foxes/core/turbine.py +2 -1
  56. foxes/core/wake_deflection.py +130 -0
  57. foxes/core/wake_model.py +222 -9
  58. foxes/core/wake_superposition.py +122 -4
  59. foxes/core/wind_farm.py +6 -6
  60. foxes/data/__init__.py +7 -2
  61. foxes/data/states/point_cloud_100.nc +0 -0
  62. foxes/data/states/weibull_cloud_4.nc +0 -0
  63. foxes/data/states/weibull_grid.nc +0 -0
  64. foxes/data/states/weibull_sectors_12.csv +13 -0
  65. foxes/data/states/weibull_sectors_12.nc +0 -0
  66. foxes/engines/__init__.py +14 -15
  67. foxes/engines/dask.py +42 -20
  68. foxes/engines/default.py +2 -2
  69. foxes/engines/numpy.py +11 -13
  70. foxes/engines/pool.py +20 -11
  71. foxes/engines/single.py +8 -6
  72. foxes/input/__init__.py +3 -3
  73. foxes/input/farm_layout/__init__.py +9 -8
  74. foxes/input/farm_layout/from_arrays.py +68 -0
  75. foxes/input/farm_layout/from_csv.py +1 -1
  76. foxes/input/farm_layout/ring.py +0 -1
  77. foxes/input/states/__init__.py +28 -12
  78. foxes/input/states/create/__init__.py +3 -2
  79. foxes/input/states/dataset_states.py +710 -0
  80. foxes/input/states/field_data.py +531 -0
  81. foxes/input/states/multi_height.py +11 -6
  82. foxes/input/states/one_point_flow.py +1 -4
  83. foxes/input/states/point_cloud_data.py +618 -0
  84. foxes/input/states/scan.py +2 -0
  85. foxes/input/states/single.py +3 -1
  86. foxes/input/states/states_table.py +23 -30
  87. foxes/input/states/weibull_sectors.py +330 -0
  88. foxes/input/states/wrg_states.py +8 -6
  89. foxes/input/yaml/__init__.py +9 -3
  90. foxes/input/yaml/dict.py +42 -41
  91. foxes/input/yaml/windio/__init__.py +10 -5
  92. foxes/input/yaml/windio/read_attributes.py +42 -29
  93. foxes/input/yaml/windio/read_farm.py +17 -15
  94. foxes/input/yaml/windio/read_fields.py +4 -2
  95. foxes/input/yaml/windio/read_outputs.py +25 -15
  96. foxes/input/yaml/windio/read_site.py +172 -11
  97. foxes/input/yaml/windio/windio.py +23 -11
  98. foxes/input/yaml/yaml.py +1 -0
  99. foxes/models/__init__.py +15 -14
  100. foxes/models/axial_induction/__init__.py +2 -2
  101. foxes/models/farm_controllers/__init__.py +1 -1
  102. foxes/models/farm_models/__init__.py +1 -1
  103. foxes/models/ground_models/__init__.py +3 -2
  104. foxes/models/ground_models/wake_mirror.py +3 -3
  105. foxes/models/model_book.py +190 -63
  106. foxes/models/partial_wakes/__init__.py +6 -6
  107. foxes/models/partial_wakes/axiwake.py +30 -5
  108. foxes/models/partial_wakes/centre.py +47 -0
  109. foxes/models/partial_wakes/rotor_points.py +41 -11
  110. foxes/models/partial_wakes/segregated.py +2 -25
  111. foxes/models/partial_wakes/top_hat.py +27 -2
  112. foxes/models/point_models/__init__.py +4 -4
  113. foxes/models/rotor_models/__init__.py +4 -3
  114. foxes/models/rotor_models/centre.py +1 -1
  115. foxes/models/rotor_models/direct_infusion.py +241 -0
  116. foxes/models/turbine_models/__init__.py +11 -11
  117. foxes/models/turbine_models/calculator.py +16 -3
  118. foxes/models/turbine_models/kTI_model.py +1 -0
  119. foxes/models/turbine_models/lookup_table.py +2 -0
  120. foxes/models/turbine_models/power_mask.py +1 -0
  121. foxes/models/turbine_models/rotor_centre_calc.py +2 -0
  122. foxes/models/turbine_models/sector_management.py +1 -0
  123. foxes/models/turbine_models/set_farm_vars.py +3 -9
  124. foxes/models/turbine_models/table_factors.py +2 -0
  125. foxes/models/turbine_models/thrust2ct.py +1 -0
  126. foxes/models/turbine_models/yaw2yawm.py +2 -0
  127. foxes/models/turbine_models/yawm2yaw.py +2 -0
  128. foxes/models/turbine_types/PCt_file.py +2 -6
  129. foxes/models/turbine_types/PCt_from_two.py +1 -2
  130. foxes/models/turbine_types/__init__.py +10 -9
  131. foxes/models/turbine_types/calculator_type.py +123 -0
  132. foxes/models/turbine_types/null_type.py +1 -0
  133. foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -0
  134. foxes/models/turbine_types/wsti2PCt_from_two.py +3 -1
  135. foxes/models/vertical_profiles/__init__.py +7 -7
  136. foxes/models/wake_deflections/__init__.py +3 -0
  137. foxes/models/{wake_frames/yawed_wakes.py → wake_deflections/bastankhah2016.py} +32 -111
  138. foxes/models/wake_deflections/jimenez.py +277 -0
  139. foxes/models/wake_deflections/no_deflection.py +94 -0
  140. foxes/models/wake_frames/__init__.py +6 -7
  141. foxes/models/wake_frames/dynamic_wakes.py +12 -3
  142. foxes/models/wake_frames/rotor_wd.py +3 -1
  143. foxes/models/wake_frames/seq_dynamic_wakes.py +41 -7
  144. foxes/models/wake_frames/streamlines.py +8 -6
  145. foxes/models/wake_frames/timelines.py +9 -3
  146. foxes/models/wake_models/__init__.py +7 -7
  147. foxes/models/wake_models/dist_sliced.py +50 -84
  148. foxes/models/wake_models/gaussian.py +20 -0
  149. foxes/models/wake_models/induction/__init__.py +5 -5
  150. foxes/models/wake_models/induction/rankine_half_body.py +30 -71
  151. foxes/models/wake_models/induction/rathmann.py +65 -64
  152. foxes/models/wake_models/induction/self_similar.py +65 -68
  153. foxes/models/wake_models/induction/self_similar2020.py +0 -3
  154. foxes/models/wake_models/induction/vortex_sheet.py +71 -75
  155. foxes/models/wake_models/ti/__init__.py +2 -2
  156. foxes/models/wake_models/ti/crespo_hernandez.py +5 -3
  157. foxes/models/wake_models/ti/iec_ti.py +6 -4
  158. foxes/models/wake_models/top_hat.py +58 -7
  159. foxes/models/wake_models/wind/__init__.py +6 -4
  160. foxes/models/wake_models/wind/bastankhah14.py +25 -7
  161. foxes/models/wake_models/wind/bastankhah16.py +35 -3
  162. foxes/models/wake_models/wind/jensen.py +15 -2
  163. foxes/models/wake_models/wind/turbopark.py +28 -2
  164. foxes/models/wake_superpositions/__init__.py +18 -9
  165. foxes/models/wake_superpositions/ti_linear.py +4 -4
  166. foxes/models/wake_superpositions/ti_max.py +4 -4
  167. foxes/models/wake_superpositions/ti_pow.py +4 -4
  168. foxes/models/wake_superpositions/ti_quadratic.py +4 -4
  169. foxes/models/wake_superpositions/wind_vector.py +257 -0
  170. foxes/models/wake_superpositions/ws_linear.py +9 -10
  171. foxes/models/wake_superpositions/ws_max.py +8 -8
  172. foxes/models/wake_superpositions/ws_pow.py +8 -8
  173. foxes/models/wake_superpositions/ws_product.py +4 -4
  174. foxes/models/wake_superpositions/ws_quadratic.py +8 -8
  175. foxes/output/__init__.py +21 -19
  176. foxes/output/farm_layout.py +4 -2
  177. foxes/output/farm_results_eval.py +19 -16
  178. foxes/output/flow_plots_2d/__init__.py +2 -2
  179. foxes/output/flow_plots_2d/flow_plots.py +18 -0
  180. foxes/output/flow_plots_2d/get_fig.py +5 -2
  181. foxes/output/output.py +6 -1
  182. foxes/output/results_writer.py +1 -1
  183. foxes/output/rose_plot.py +13 -3
  184. foxes/output/rotor_point_plots.py +3 -0
  185. foxes/output/seq_plugins/__init__.py +2 -2
  186. foxes/output/seq_plugins/seq_flow_ani_plugin.py +0 -3
  187. foxes/output/seq_plugins/seq_wake_debug_plugin.py +0 -1
  188. foxes/output/state_turbine_map.py +3 -0
  189. foxes/output/turbine_type_curves.py +10 -8
  190. foxes/utils/__init__.py +37 -19
  191. foxes/utils/abl/__init__.py +4 -4
  192. foxes/utils/cubic_roots.py +1 -1
  193. foxes/utils/data_book.py +4 -3
  194. foxes/utils/dict.py +49 -37
  195. foxes/utils/exec_python.py +5 -5
  196. foxes/utils/factory.py +3 -5
  197. foxes/utils/geom2d/__init__.py +7 -5
  198. foxes/utils/geopandas_utils.py +2 -2
  199. foxes/utils/pandas_utils.py +4 -3
  200. foxes/utils/tab_files.py +0 -1
  201. foxes/utils/weibull.py +28 -0
  202. foxes/utils/wrg_utils.py +3 -1
  203. foxes/utils/xarray_utils.py +9 -2
  204. foxes/variables.py +67 -9
  205. {foxes-1.3.dist-info → foxes-1.5.dist-info}/METADATA +34 -63
  206. foxes-1.5.dist-info/RECORD +328 -0
  207. {foxes-1.3.dist-info → foxes-1.5.dist-info}/WHEEL +1 -1
  208. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +2 -3
  209. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +1 -1
  210. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
  211. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +0 -1
  212. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +0 -2
  213. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +0 -1
  214. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +0 -1
  215. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +0 -1
  216. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +0 -1
  217. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +0 -1
  218. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
  219. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +0 -1
  220. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +0 -1
  221. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +0 -1
  222. foxes/input/states/field_data_nc.py +0 -847
  223. foxes/output/round.py +0 -10
  224. foxes/utils/pandas_helpers.py +0 -178
  225. foxes-1.3.dist-info/RECORD +0 -313
  226. {foxes-1.3.dist-info → foxes-1.5.dist-info}/entry_points.txt +0 -0
  227. {foxes-1.3.dist-info → foxes-1.5.dist-info/licenses}/LICENSE +0 -0
  228. {foxes-1.3.dist-info → foxes-1.5.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
Binary file
Binary file
Binary file
@@ -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
@@ -199,7 +199,6 @@ def _run_as_ufunc(
199
199
  out_coords,
200
200
  calc_pars,
201
201
  init_vars,
202
- ensure_variables,
203
202
  calculate,
204
203
  ):
205
204
  """
@@ -222,19 +221,28 @@ def _run_as_ufunc(
222
221
  if i == 0:
223
222
  data.append(
224
223
  MData(
225
- data=hdata, dims=hdims, loop_dims=loop_dims, states_i0=state_inds[0]
224
+ data=hdata,
225
+ dims=hdims,
226
+ # loop_dims=loop_dims,
227
+ states_i0=state_inds[0],
226
228
  )
227
229
  )
228
230
  elif i == 1:
229
231
  data.append(
230
232
  FData(
231
- data=hdata, dims=hdims, loop_dims=loop_dims, states_i0=state_inds[0]
233
+ data=hdata,
234
+ dims=hdims,
235
+ # loop_dims=loop_dims,
236
+ states_i0=state_inds[0],
232
237
  )
233
238
  )
234
239
  elif i == 2:
235
240
  data.append(
236
241
  TData(
237
- data=hdata, dims=hdims, loop_dims=loop_dims, states_i0=state_inds[0]
242
+ data=hdata,
243
+ dims=hdims,
244
+ # loop_dims=loop_dims,
245
+ states_i0=state_inds[0],
238
246
  )
239
247
  )
240
248
  else:
@@ -246,13 +254,13 @@ def _run_as_ufunc(
246
254
 
247
255
  # deduce output shape:
248
256
  oshape = []
249
- for li, l in enumerate(out_coords):
257
+ for li, ld in enumerate(out_coords):
250
258
  for i, dims in enumerate(ldims):
251
- if l in dims:
252
- oshape.append(ldata[i].shape[dims.index(l)])
259
+ if ld in dims:
260
+ oshape.append(ldata[i].shape[dims.index(ld)])
253
261
  break
254
262
  if len(oshape) != li + 1:
255
- raise ValueError(f"Failed to find loop dimension")
263
+ raise ValueError("Failed to find loop dimension")
256
264
 
257
265
  # add zero output data arrays:
258
266
  odims = {v: tuple(out_coords) for v in out_vars}
@@ -267,14 +275,31 @@ def _run_as_ufunc(
267
275
  }
268
276
 
269
277
  if len(data) == 1:
270
- data.append(FData(odata, odims, loop_dims, states_i0=state_inds[0]))
278
+ data.append(
279
+ FData(
280
+ odata,
281
+ odims,
282
+ # loop_dims,
283
+ states_i0=state_inds[0],
284
+ )
285
+ )
271
286
  else:
272
287
  odata.update(data[-1])
273
288
  odims.update(data[-1].dims)
274
289
  if len(data) == 2:
275
- data[-1] = FData(odata, odims, loop_dims, states_i0=state_inds[0])
290
+ data[-1] = FData(
291
+ odata,
292
+ odims,
293
+ # loop_dims,
294
+ states_i0=state_inds[0],
295
+ )
276
296
  else:
277
- data[-1] = TData(odata, odims, loop_dims, states_i0=state_inds[0])
297
+ data[-1] = TData(
298
+ odata,
299
+ odims,
300
+ # loop_dims,
301
+ states_i0=state_inds[0],
302
+ )
278
303
  del odims, odata
279
304
 
280
305
  # link chunk state indices from mdata to fdata and tdata:
@@ -288,7 +313,6 @@ def _run_as_ufunc(
288
313
  data[1].dims[FV.WEIGHT] = data[0].dims[FV.WEIGHT]
289
314
 
290
315
  # run model calculation:
291
- ensure_variables(algo, *data)
292
316
  results = calculate(algo, *data, **calc_pars)
293
317
 
294
318
  # replace missing results by first input data with matching shape:
@@ -359,7 +383,7 @@ class XArrayEngine(DaskBaseEngine):
359
383
  self,
360
384
  algo,
361
385
  model,
362
- model_data=None,
386
+ model_data,
363
387
  farm_data=None,
364
388
  point_data=None,
365
389
  out_vars=[],
@@ -382,9 +406,9 @@ class XArrayEngine(DaskBaseEngine):
382
406
  should be run
383
407
  model_data: xarray.Dataset
384
408
  The initial model data
385
- farm_data: xarray.Dataset
409
+ farm_data: xarray.Dataset, optional
386
410
  The initial farm data
387
- point_data: xarray.Dataset
411
+ point_data: xarray.Dataset, optional
388
412
  The initial point data
389
413
  out_vars: list of str, optional
390
414
  Names of the output variables
@@ -451,7 +475,6 @@ class XArrayEngine(DaskBaseEngine):
451
475
  if d is not None
452
476
  ]
453
477
  for ds in data:
454
-
455
478
  hvarsl = [v for v, d in ds.items() if len(loopd.intersection(d.dims))]
456
479
  ldata += [ds[v] for v in hvarsl]
457
480
  ldims += [ds[v].dims for v in hvarsl]
@@ -512,7 +535,6 @@ class XArrayEngine(DaskBaseEngine):
512
535
  out_coords=out_coords,
513
536
  calc_pars=calc_pars,
514
537
  init_vars=ivars,
515
- ensure_variables=model.ensure_variables,
516
538
  calculate=model.calculate,
517
539
  )
518
540
 
@@ -734,7 +756,7 @@ def _run_on_cluster(
734
756
  mdata = MData(
735
757
  data={names[i]: data[i] for i in range(mdata_size)},
736
758
  dims={names[i]: dims[i] for i in range(mdata_size)},
737
- loop_dims=loop_dims[0],
759
+ # loop_dims=loop_dims[0],
738
760
  states_i0=i0_states,
739
761
  )
740
762
 
@@ -742,7 +764,7 @@ def _run_on_cluster(
742
764
  fdata = FData(
743
765
  data={names[i]: data[i].copy() for i in range(mdata_size, fdata_end)},
744
766
  dims={names[i]: dims[i] for i in range(mdata_size, fdata_end)},
745
- loop_dims=loop_dims[1],
767
+ # loop_dims=loop_dims[1],
746
768
  states_i0=i0_states,
747
769
  )
748
770
 
@@ -751,7 +773,7 @@ def _run_on_cluster(
751
773
  tdata = TData(
752
774
  data={names[i]: data[i].copy() for i in range(fdata_end, len(data))},
753
775
  dims={names[i]: dims[i] for i in range(fdata_end, len(data))},
754
- loop_dims=loop_dims[2],
776
+ # loop_dims=loop_dims[2],
755
777
  states_i0=i0_states,
756
778
  )
757
779
 
foxes/engines/default.py CHANGED
@@ -60,7 +60,7 @@ class DefaultEngine(Engine):
60
60
  self,
61
61
  algo,
62
62
  model,
63
- model_data=None,
63
+ model_data,
64
64
  farm_data=None,
65
65
  point_data=None,
66
66
  **kwargs,
@@ -75,7 +75,7 @@ class DefaultEngine(Engine):
75
75
  model: foxes.core.DataCalcModel
76
76
  The model that whose calculate function
77
77
  should be run
78
- model_data: xarray.Dataset, optional
78
+ model_data: xarray.Dataset
79
79
  The initial model data
80
80
  farm_data: xarray.Dataset, optional
81
81
  The initial farm data