foxes 0.8.2__py3-none-any.whl → 1.0__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 (174) hide show
  1. docs/source/conf.py +353 -0
  2. examples/abl_states/run.py +160 -0
  3. examples/compare_rotors_pwakes/run.py +217 -0
  4. examples/compare_wakes/run.py +241 -0
  5. examples/dyn_wakes/run.py +311 -0
  6. examples/field_data_nc/run.py +121 -0
  7. examples/induction_RHB/run.py +201 -0
  8. examples/multi_height/run.py +113 -0
  9. examples/power_mask/run.py +249 -0
  10. examples/random_timeseries/run.py +210 -0
  11. examples/scan_row/run.py +193 -0
  12. examples/sector_management/run.py +162 -0
  13. examples/sequential/run.py +209 -0
  14. examples/single_state/run.py +201 -0
  15. examples/states_lookup_table/run.py +137 -0
  16. examples/streamline_wakes/run.py +138 -0
  17. examples/tab_file/run.py +142 -0
  18. examples/timelines/run.py +267 -0
  19. examples/timeseries/run.py +183 -0
  20. examples/timeseries_slurm/run.py +185 -0
  21. examples/wind_rose/run.py +141 -0
  22. examples/windio/run.py +29 -0
  23. examples/yawed_wake/run.py +196 -0
  24. foxes/__init__.py +4 -8
  25. foxes/algorithms/__init__.py +1 -1
  26. foxes/algorithms/downwind/downwind.py +232 -101
  27. foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -6
  28. foxes/algorithms/downwind/models/init_farm_data.py +1 -1
  29. foxes/algorithms/downwind/models/point_wakes_calc.py +5 -6
  30. foxes/algorithms/downwind/models/reorder_farm_output.py +0 -1
  31. foxes/algorithms/downwind/models/set_amb_point_results.py +4 -2
  32. foxes/algorithms/iterative/iterative.py +73 -33
  33. foxes/algorithms/iterative/models/farm_wakes_calc.py +11 -6
  34. foxes/algorithms/sequential/models/plugin.py +1 -1
  35. foxes/algorithms/sequential/sequential.py +126 -255
  36. foxes/constants.py +17 -2
  37. foxes/core/__init__.py +1 -0
  38. foxes/core/algorithm.py +631 -146
  39. foxes/core/data.py +252 -20
  40. foxes/core/data_calc_model.py +13 -289
  41. foxes/core/engine.py +630 -0
  42. foxes/core/farm_controller.py +37 -9
  43. foxes/core/farm_data_model.py +15 -0
  44. foxes/core/model.py +133 -80
  45. foxes/core/point_data_model.py +15 -0
  46. foxes/core/rotor_model.py +27 -21
  47. foxes/core/states.py +16 -0
  48. foxes/core/turbine_type.py +28 -0
  49. foxes/core/wake_frame.py +22 -4
  50. foxes/core/wake_model.py +2 -3
  51. foxes/data/windio/windio_5turbines_timeseries.yaml +23 -1
  52. foxes/engines/__init__.py +16 -0
  53. foxes/engines/dask.py +975 -0
  54. foxes/engines/default.py +75 -0
  55. foxes/engines/futures.py +72 -0
  56. foxes/engines/mpi.py +38 -0
  57. foxes/engines/multiprocess.py +74 -0
  58. foxes/engines/numpy.py +185 -0
  59. foxes/engines/pool.py +263 -0
  60. foxes/engines/single.py +139 -0
  61. foxes/input/farm_layout/__init__.py +1 -0
  62. foxes/input/farm_layout/from_csv.py +4 -0
  63. foxes/input/farm_layout/from_json.py +1 -1
  64. foxes/input/farm_layout/grid.py +2 -2
  65. foxes/input/farm_layout/ring.py +65 -0
  66. foxes/input/farm_layout/row.py +2 -2
  67. foxes/input/states/__init__.py +6 -0
  68. foxes/input/states/create/random_abl_states.py +1 -1
  69. foxes/input/states/field_data_nc.py +157 -32
  70. foxes/input/states/multi_height.py +127 -13
  71. foxes/input/states/one_point_flow.py +577 -0
  72. foxes/input/states/scan_ws.py +73 -2
  73. foxes/input/states/states_table.py +204 -35
  74. foxes/input/windio/__init__.py +1 -1
  75. foxes/input/windio/get_states.py +44 -23
  76. foxes/input/windio/read_attributes.py +41 -16
  77. foxes/input/windio/read_farm.py +116 -102
  78. foxes/input/windio/read_fields.py +13 -6
  79. foxes/input/windio/read_outputs.py +63 -22
  80. foxes/input/windio/runner.py +31 -17
  81. foxes/input/windio/windio.py +36 -22
  82. foxes/models/ground_models/wake_mirror.py +8 -4
  83. foxes/models/model_book.py +29 -18
  84. foxes/models/partial_wakes/rotor_points.py +3 -3
  85. foxes/models/rotor_models/centre.py +4 -0
  86. foxes/models/rotor_models/grid.py +22 -23
  87. foxes/models/rotor_models/levels.py +4 -5
  88. foxes/models/turbine_models/calculator.py +0 -2
  89. foxes/models/turbine_models/lookup_table.py +27 -2
  90. foxes/models/turbine_models/rotor_centre_calc.py +4 -3
  91. foxes/models/turbine_models/set_farm_vars.py +103 -34
  92. foxes/models/turbine_types/PCt_file.py +24 -0
  93. foxes/models/turbine_types/PCt_from_two.py +24 -0
  94. foxes/models/turbine_types/__init__.py +1 -0
  95. foxes/models/turbine_types/lookup.py +316 -0
  96. foxes/models/turbine_types/null_type.py +50 -0
  97. foxes/models/turbine_types/wsrho2PCt_from_two.py +24 -0
  98. foxes/models/turbine_types/wsti2PCt_from_two.py +24 -0
  99. foxes/models/vertical_profiles/data_profile.py +1 -1
  100. foxes/models/wake_frames/__init__.py +1 -0
  101. foxes/models/wake_frames/dynamic_wakes.py +424 -0
  102. foxes/models/wake_frames/farm_order.py +23 -3
  103. foxes/models/wake_frames/rotor_wd.py +4 -2
  104. foxes/models/wake_frames/seq_dynamic_wakes.py +56 -63
  105. foxes/models/wake_frames/streamlines.py +19 -20
  106. foxes/models/wake_frames/timelines.py +328 -127
  107. foxes/models/wake_frames/yawed_wakes.py +4 -1
  108. foxes/models/wake_models/dist_sliced.py +1 -3
  109. foxes/models/wake_models/induction/rankine_half_body.py +4 -4
  110. foxes/models/wake_models/induction/rathmann.py +2 -2
  111. foxes/models/wake_models/induction/self_similar.py +2 -2
  112. foxes/models/wake_models/induction/vortex_sheet.py +2 -2
  113. foxes/models/wake_models/ti/iec_ti.py +34 -17
  114. foxes/models/wake_models/top_hat.py +1 -1
  115. foxes/models/wake_models/wind/bastankhah14.py +2 -2
  116. foxes/models/wake_models/wind/bastankhah16.py +8 -7
  117. foxes/models/wake_models/wind/jensen.py +1 -1
  118. foxes/models/wake_models/wind/turbopark.py +2 -2
  119. foxes/output/__init__.py +4 -1
  120. foxes/output/farm_layout.py +2 -2
  121. foxes/output/flow_plots_2d/__init__.py +0 -1
  122. foxes/output/flow_plots_2d/flow_plots.py +70 -30
  123. foxes/output/grids.py +91 -21
  124. foxes/output/seq_plugins/__init__.py +2 -0
  125. foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +62 -20
  126. foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
  127. foxes/output/slice_data.py +131 -111
  128. foxes/output/state_turbine_map.py +18 -13
  129. foxes/output/state_turbine_table.py +19 -19
  130. foxes/utils/__init__.py +1 -1
  131. foxes/utils/dev_utils.py +42 -0
  132. foxes/utils/dict.py +1 -1
  133. foxes/utils/factory.py +147 -52
  134. foxes/utils/pandas_helpers.py +4 -3
  135. foxes/utils/wind_dir.py +0 -2
  136. foxes/utils/xarray_utils.py +23 -13
  137. foxes/variables.py +37 -0
  138. {foxes-0.8.2.dist-info → foxes-1.0.dist-info}/METADATA +71 -33
  139. foxes-1.0.dist-info/RECORD +307 -0
  140. {foxes-0.8.2.dist-info → foxes-1.0.dist-info}/WHEEL +1 -1
  141. foxes-1.0.dist-info/top_level.txt +4 -0
  142. tests/0_consistency/iterative/test_iterative.py +92 -0
  143. tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
  144. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
  145. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
  146. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
  147. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
  148. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
  149. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
  150. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
  151. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
  152. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
  153. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
  154. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
  155. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
  156. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
  157. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
  158. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
  159. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
  160. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
  161. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
  162. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
  163. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
  164. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
  165. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
  166. tests/3_examples/test_examples.py +34 -0
  167. foxes/VERSION +0 -1
  168. foxes/output/flow_plots_2d.py +0 -0
  169. foxes/utils/runners/__init__.py +0 -1
  170. foxes/utils/runners/runners.py +0 -280
  171. foxes-0.8.2.dist-info/RECORD +0 -247
  172. foxes-0.8.2.dist-info/top_level.txt +0 -1
  173. foxes-0.8.2.dist-info/zip-safe +0 -1
  174. {foxes-0.8.2.dist-info → foxes-1.0.dist-info}/LICENSE +0 -0
@@ -1,4 +1,4 @@
1
- from foxes.core import Algorithm, FarmDataModelList
1
+ from foxes.core import Algorithm, FarmDataModelList, get_engine
2
2
  from foxes.core import PointDataModel, PointDataModelList, FarmController
3
3
  import foxes.models as fm
4
4
  import foxes.variables as FV
@@ -49,6 +49,7 @@ class Downwind(Algorithm):
49
49
  FV.AMB_REWS,
50
50
  FV.AMB_TI,
51
51
  FV.AMB_RHO,
52
+ FV.AMB_CT,
52
53
  FV.AMB_P,
53
54
  FV.WD,
54
55
  FV.REWS,
@@ -70,10 +71,8 @@ class Downwind(Algorithm):
70
71
  partial_wakes=None,
71
72
  ground_models=None,
72
73
  farm_controller="basic_ctrl",
73
- chunks={FC.STATE: 1000, FC.POINT: 4000},
74
74
  mbook=None,
75
- dbook=None,
76
- verbosity=1,
75
+ **kwargs,
77
76
  ):
78
77
  """
79
78
  Constructor.
@@ -102,33 +101,27 @@ class Downwind(Algorithm):
102
101
  farm_controller: str
103
102
  The farm controller. Will be
104
103
  looked up in the model book
105
- chunks: dict
106
- The chunks choice for running in parallel with dask,
107
- e.g. `{"state": 1000}` for chunks of 1000 states
108
104
  mbook: foxes.ModelBook, optional
109
105
  The model book
110
- dbook: foxes.DataBook, optional
111
- The data book, or None for default
112
- verbosity: int
113
- The verbosity level, 0 means silent
106
+ kwargs: dict, optional
107
+ Additional parameters for the base class
114
108
 
115
109
  """
116
110
  if mbook is None:
117
111
  mbook = fm.ModelBook()
118
112
 
119
- super().__init__(mbook, farm, chunks, verbosity, dbook)
113
+ super().__init__(mbook, farm, **kwargs)
120
114
 
121
- self.states = states
115
+ self.__states = states
122
116
  self.n_states = None
123
- self.states_data = None
124
117
 
125
- self.rotor_model = self.mbook.rotor_models[rotor_model]
118
+ self.__rotor_model = self.mbook.rotor_models[rotor_model]
126
119
  self.rotor_model.name = rotor_model
127
120
 
128
- self.wake_frame = self.mbook.wake_frames[wake_frame]
121
+ self.__wake_frame = self.mbook.wake_frames[wake_frame]
129
122
  self.wake_frame.name = wake_frame
130
123
 
131
- self.wake_models = {}
124
+ self.__wake_models = {}
132
125
  for w in wake_models:
133
126
  m = self.mbook.wake_models[w]
134
127
  m.name = w
@@ -167,7 +160,7 @@ class Downwind(Algorithm):
167
160
  target[w] = mbooks[pw]
168
161
  target[w].name = pw
169
162
 
170
- self.partial_wakes = {}
163
+ self.__partial_wakes = {}
171
164
  _set_wspecific(
172
165
  descr="partial wakes",
173
166
  target=self.partial_wakes,
@@ -177,7 +170,7 @@ class Downwind(Algorithm):
177
170
  checkw=True,
178
171
  )
179
172
 
180
- self.ground_models = {}
173
+ self.__ground_models = {}
181
174
  _set_wspecific(
182
175
  descr="ground models",
183
176
  target=self.ground_models,
@@ -187,9 +180,113 @@ class Downwind(Algorithm):
187
180
  checkw=False,
188
181
  )
189
182
 
190
- self.farm_controller = self.mbook.farm_controllers[farm_controller]
183
+ self.__farm_controller = self.mbook.farm_controllers[farm_controller]
191
184
  self.farm_controller.name = farm_controller
192
185
 
186
+ @property
187
+ def states(self):
188
+ """
189
+ The states
190
+
191
+ Returns
192
+ -------
193
+ m: foxes.core.States
194
+ The states
195
+
196
+ """
197
+ return self.__states
198
+
199
+ @states.setter
200
+ def states(self, value):
201
+ """Resets the states"""
202
+ if self.running:
203
+ raise ValueError(f"{self.name}: Cannot set states while running")
204
+ if self.states.initialized:
205
+ self.states.finalize(self, verbosity=self.verbosity)
206
+ self.__states = value
207
+ self.init_states()
208
+
209
+ @property
210
+ def rotor_model(self):
211
+ """
212
+ The rotor model
213
+
214
+ Returns
215
+ -------
216
+ m: foxes.core.RotorModel
217
+ The rotor model
218
+
219
+ """
220
+ return self.__rotor_model
221
+
222
+ @property
223
+ def wake_models(self):
224
+ """
225
+ The wake models
226
+
227
+ Returns
228
+ -------
229
+ m: dict
230
+ The wake models. Key: name,
231
+ value: foxes.core.WakeModel
232
+
233
+ """
234
+ return self.__wake_models
235
+
236
+ @property
237
+ def wake_frame(self):
238
+ """
239
+ The wake frame
240
+
241
+ Returns
242
+ -------
243
+ m: foxes.core.WakeFrame
244
+ The wake frame
245
+
246
+ """
247
+ return self.__wake_frame
248
+
249
+ @property
250
+ def partial_wakes(self):
251
+ """
252
+ The partial wakes models
253
+
254
+ Returns
255
+ -------
256
+ m: dict
257
+ The partial wakes models. Key: name,
258
+ value: foxes.core.PartialWakesModel
259
+
260
+ """
261
+ return self.__partial_wakes
262
+
263
+ @property
264
+ def ground_models(self):
265
+ """
266
+ The ground models
267
+
268
+ Returns
269
+ -------
270
+ m: dict
271
+ The ground models, key: name,
272
+ value: foxes.core.GroundModel
273
+
274
+ """
275
+ return self.__ground_models
276
+
277
+ @property
278
+ def farm_controller(self):
279
+ """
280
+ The farm controller
281
+
282
+ Returns
283
+ -------
284
+ m: foxes.core.FarmController
285
+ The farm controller
286
+
287
+ """
288
+ return self.__farm_controller
289
+
193
290
  @classmethod
194
291
  def get_model(cls, name):
195
292
  """
@@ -276,29 +373,25 @@ class Downwind(Algorithm):
276
373
  self.states.initialize(self, self.verbosity)
277
374
  self.n_states = self.states.size()
278
375
 
279
- def all_models(self, with_states=True):
376
+ def sub_models(self):
280
377
  """
281
- Return all models
282
-
283
- Parameters
284
- ----------
285
- with_states: bool
286
- Flag for including states
378
+ List of all sub-models
287
379
 
288
380
  Returns
289
381
  -------
290
- mdls: list of foxes.core.Model
291
- The list of models
382
+ smdls: list of foxes.core.Model
383
+ All sub models
292
384
 
293
385
  """
294
- mdls = [self.states] if with_states else []
295
- mdls += [
296
- self.rotor_model,
386
+ mdls = [
387
+ self.states,
297
388
  self.farm_controller,
389
+ self.rotor_model,
298
390
  self.wake_frame,
299
391
  ]
300
392
  mdls += list(self.wake_models.values())
301
393
  mdls += list(self.partial_wakes.values())
394
+ mdls += list(self.ground_models.values())
302
395
 
303
396
  return mdls
304
397
 
@@ -306,13 +399,10 @@ class Downwind(Algorithm):
306
399
  """
307
400
  Initializes the algorithm.
308
401
  """
309
- self.print(f"\nInitializing algorithm '{self.name}'")
310
- super().initialize()
311
-
312
402
  self.init_states()
313
403
 
314
- for m in self.all_models(with_states=False):
315
- m.initialize(self, self.verbosity)
404
+ self.print(f"\nInitializing algorithm '{self.name}'")
405
+ super().initialize()
316
406
 
317
407
  def _collect_farm_models(
318
408
  self,
@@ -370,17 +460,38 @@ class Downwind(Algorithm):
370
460
  """Helper function that gathers the farm variables"""
371
461
  self.farm_vars = sorted(list(set([FV.WEIGHT] + mlist.output_farm_vars(self))))
372
462
 
373
- def _run_farm_calc(self, mlist, *data, outputs=None, **kwargs):
374
- """Helper function for running the main farm calculation"""
375
- self.print(
376
- f"\nCalculating {self.n_states} states for {self.n_turbines} turbines"
377
- )
463
+ def _launch_parallel_farm_calc(
464
+ self,
465
+ mlist,
466
+ *data,
467
+ outputs=None,
468
+ **kwargs,
469
+ ):
470
+ """
471
+ Runs the main calculation, launching parallelization
472
+
473
+ Parameters
474
+ ----------
475
+ mlist: foxes.models.FarmDataModelList
476
+ The model list
477
+ data: tuple of xarray.Dataset
478
+ The (mdata, fdata) inputs
479
+ outputs: list of str, optional
480
+ The output variables, or None for defaults
481
+ kwargs: dict, optional
482
+ Additional parameters for running
483
+
484
+ Returns
485
+ -------
486
+ farm_results: xarray.Dataset
487
+ The farm results. The calculated variables have
488
+ dimensions (state, turbine)
489
+
490
+ """
378
491
  out_vars = self.farm_vars if outputs is None else outputs
379
- farm_results = mlist.run_calculation(self, *data, out_vars=out_vars, **kwargs)
380
- farm_results[FC.TNAME] = ((FC.TURBINE,), self.farm.turbine_names)
381
- for v in [FV.ORDER, FV.ORDER_SSEL, FV.ORDER_INV]:
382
- if v in farm_results:
383
- farm_results[v] = farm_results[v].astype(FC.ITYPE)
492
+ farm_results = get_engine().run_calculation(
493
+ self, mlist, *data, out_vars=out_vars, **kwargs
494
+ )
384
495
 
385
496
  return farm_results
386
497
 
@@ -388,10 +499,8 @@ class Downwind(Algorithm):
388
499
  self,
389
500
  outputs=None,
390
501
  calc_parameters={},
391
- persist=True,
392
502
  finalize=True,
393
503
  ambient=False,
394
- chunked_results=False,
395
504
  **kwargs,
396
505
  ):
397
506
  """
@@ -404,15 +513,10 @@ class Downwind(Algorithm):
404
513
  Key: model name str, value: parameter dict
405
514
  outputs: list of str, optional
406
515
  The output variables, or None for defaults
407
- persist: bool
408
- Switch for forcing dask to load all model data
409
- into memory
410
516
  finalize: bool
411
517
  Flag for finalization after calculation
412
518
  ambient: bool
413
519
  Flag for ambient instead of waked calculation
414
- chunked_results: bool
415
- Flag for chunked results
416
520
  kwargs: dict, optional
417
521
  Additional parameters for run_calculation
418
522
 
@@ -448,37 +552,37 @@ class Downwind(Algorithm):
448
552
  outputs = sorted(list(set(outputs).intersection(self.farm_vars)))
449
553
 
450
554
  # get input model data:
451
- models_data = self.get_models_data()
452
- if persist:
453
- models_data = models_data.persist()
454
- self.print("\nInput data:\n\n", models_data, "\n")
555
+ model_data = self.get_models_data()
556
+ self.print("\nInput data:\n\n", model_data, "\n")
455
557
  self.print(f"\nFarm variables:", ", ".join(self.farm_vars))
456
558
  self.print(f"\nOutput variables:", ", ".join(outputs))
457
- self.print(f"\nChunks: {self.chunks}\n")
458
559
 
459
560
  # run main calculation:
460
- farm_results = self._run_farm_calc(
561
+ farm_results = super().calc_farm(
461
562
  mlist,
462
- models_data,
563
+ model_data,
463
564
  parameters=calc_pars,
464
565
  outputs=outputs,
465
566
  **kwargs,
466
567
  )
467
- del models_data
568
+ farm_results[FC.TNAME] = ((FC.TURBINE,), self.farm.turbine_names)
569
+ for v in [FV.ORDER, FV.ORDER_SSEL, FV.ORDER_INV]:
570
+ if v in farm_results:
571
+ farm_results[v] = farm_results[v].astype(FC.ITYPE)
572
+ del model_data
468
573
 
469
574
  # finalize models:
470
575
  if finalize:
471
576
  self.print("\n")
472
577
  mlist.finalize(self, self.verbosity)
473
578
  self.finalize()
579
+ else:
580
+ self.del_model_data(mlist)
474
581
 
475
582
  if ambient:
476
583
  dvars = [v for v in farm_results.data_vars.keys() if v in FV.var2amb]
477
584
  farm_results = farm_results.drop_vars(dvars)
478
585
 
479
- if chunked_results:
480
- farm_results = self.chunked(farm_results)
481
-
482
586
  return farm_results
483
587
 
484
588
  def _collect_point_models(
@@ -534,6 +638,41 @@ class Downwind(Algorithm):
534
638
 
535
639
  return mlist, calc_pars
536
640
 
641
+ def _launch_parallel_points_calc(self, mlist, *data, outputs=None, **kwargs):
642
+ """
643
+ Runs the main points calculation, launching parallelization
644
+
645
+ Parameters
646
+ ----------
647
+ mlist: foxes.models.FarmDataModelList
648
+ The model list
649
+ data: tuple of xarray.Dataset
650
+ The (mdata, fdata) inputs
651
+ outputs: list of str, optional
652
+ The output variables, or None for defaults
653
+ kwargs: dict, optional
654
+ Additional parameters for running
655
+
656
+ Returns
657
+ -------
658
+ point_results: xarray.Dataset
659
+ The point results. The calculated variables have
660
+ dimensions (state, point)
661
+
662
+ """
663
+ return (
664
+ get_engine()
665
+ .run_calculation(
666
+ self,
667
+ mlist,
668
+ *data,
669
+ out_vars=outputs,
670
+ **kwargs,
671
+ )
672
+ .sel({FC.TPOINT: 0})
673
+ .rename({FC.TARGET: FC.POINT})
674
+ )
675
+
537
676
  def calc_points(
538
677
  self,
539
678
  farm_results,
@@ -545,6 +684,8 @@ class Downwind(Algorithm):
545
684
  finalize=True,
546
685
  ambient=False,
547
686
  chunked_results=False,
687
+ states_sel=None,
688
+ states_isel=None,
548
689
  **kwargs,
549
690
  ):
550
691
  """
@@ -574,6 +715,10 @@ class Downwind(Algorithm):
574
715
  Flag for ambient instead of waked calculation
575
716
  chunked_results: bool
576
717
  Flag for chunked results
718
+ states_sel: list, optional
719
+ Reduce to selected states
720
+ states_isel: list, optional
721
+ Reduce to the selected states indices
577
722
  kwargs: dict, optional
578
723
  Additional parameters for run_calculation
579
724
 
@@ -584,7 +729,6 @@ class Downwind(Algorithm):
584
729
  dimensions (state, point)
585
730
 
586
731
  """
587
-
588
732
  if not self.initialized:
589
733
  self.initialize()
590
734
  if not ambient and farm_results is None:
@@ -604,27 +748,33 @@ class Downwind(Algorithm):
604
748
  if not mlist.initialized:
605
749
  mlist.initialize(self, self.verbosity)
606
750
 
751
+ # subset selections:
752
+ sel = {} if states_sel is None else {FC.STATE: states_sel}
753
+ isel = {} if states_isel is None else {FC.STATE: states_isel}
754
+ if states_isel is not None:
755
+ farm_results = farm_results.isel(isel)
756
+ if states_sel is not None:
757
+ farm_results = farm_results.sel(sel)
758
+ n_states = farm_results.sizes[FC.STATE]
759
+
607
760
  # get input model data:
608
- models_data = self.get_models_data()
761
+ model_data = self.get_models_data(sel=sel, isel=isel)
609
762
  if persist_mdata:
610
- models_data = models_data.persist()
611
- self.print("\nInput data:\n\n", models_data, "\n")
763
+ model_data = model_data.persist()
764
+ self.print("\nInput data:\n\n", model_data, "\n")
612
765
  self.print(f"\nOutput farm variables:", ", ".join(self.farm_vars))
613
- self.print(f"\nChunks: {self.chunks}\n")
614
766
 
615
767
  # chunk farm results:
616
- if self.chunks is not None:
617
- farm_results = self.chunked(farm_results)
618
768
  self.print("\nInput farm data:\n\n", farm_results, "\n")
619
769
 
620
770
  # get point data:
621
771
  if FC.STATE in farm_results.coords:
622
772
  sinds = farm_results.coords[FC.STATE]
623
- elif models_data is not None and FC.STATE in models_data.coords:
624
- sinds = models_data.coords[FC.STATE]
773
+ elif model_data is not None and FC.STATE in model_data.coords:
774
+ sinds = model_data.coords[FC.STATE]
625
775
  else:
626
776
  sinds = None
627
- point_data = self.new_point_data(points, sinds)
777
+ point_data = self.new_point_data(points, sinds, n_states=n_states)
628
778
  if persist_pdata:
629
779
  point_data = point_data.persist()
630
780
  self.print("\nInput point data:\n\n", point_data, "\n")
@@ -632,24 +782,20 @@ class Downwind(Algorithm):
632
782
  # check vars:
633
783
  ovars = mlist.output_point_vars(self)
634
784
  self.print(f"\nOutput point variables:", ", ".join(ovars))
635
- self.print(f"\nChunks: {self.chunks}\n")
636
785
 
637
786
  # calculate:
638
- self.print(
639
- f"Calculating {len(ovars)} variables at {points.shape[1]} points in {self.n_states} states"
640
- )
641
-
642
- point_results = mlist.run_calculation(
643
- self,
644
- models_data,
787
+ point_results = super().calc_points(
788
+ mlist,
789
+ model_data,
645
790
  farm_results,
646
791
  point_data,
647
- out_vars=ovars,
792
+ outputs=ovars,
648
793
  parameters=calc_pars,
794
+ # sel=sel,
795
+ # isel=isel,
649
796
  **kwargs,
650
797
  )
651
-
652
- del models_data, farm_results, point_data
798
+ del model_data, farm_results, point_data
653
799
 
654
800
  # finalize models:
655
801
  if finalize:
@@ -665,18 +811,3 @@ class Downwind(Algorithm):
665
811
  point_results = self.chunked(point_results)
666
812
 
667
813
  return point_results
668
-
669
- def finalize(self, clear_mem=False):
670
- """
671
- Finalizes the algorithm.
672
-
673
- Parameters
674
- ----------
675
- clear_mem: bool
676
- Clear idata memory
677
-
678
- """
679
- for m in self.all_models():
680
- m.finalize(self, self.verbosity)
681
-
682
- super().finalize(clear_mem)
@@ -2,6 +2,7 @@ import numpy as np
2
2
  from copy import deepcopy
3
3
 
4
4
  from foxes.core import FarmDataModel, TData
5
+ import foxes.constants as FC
5
6
 
6
7
 
7
8
  class FarmWakesCalculation(FarmDataModel):
@@ -57,8 +58,8 @@ class FarmWakesCalculation(FarmDataModel):
57
58
  """
58
59
  # collect ambient rotor results and weights:
59
60
  rotor = algo.rotor_model
60
- weights = rotor.from_data_or_store(rotor.RWEIGHTS, algo, mdata)
61
- amb_res = rotor.from_data_or_store(rotor.AMBRES, algo, mdata)
61
+ weights = algo.get_from_chunk_store(FC.ROTOR_WEIGHTS, mdata=mdata)
62
+ amb_res = algo.get_from_chunk_store(FC.AMB_ROTOR_RES, mdata=mdata)
62
63
 
63
64
  # generate all wake evaluation points
64
65
  # (n_states, n_order, n_rpoints)
@@ -69,9 +70,9 @@ class FarmWakesCalculation(FarmDataModel):
69
70
  tpoints, tweights = pwake.get_wake_points(algo, mdata, fdata)
70
71
  pwake2tdata[pwake.name] = TData.from_tpoints(tpoints, tweights)
71
72
 
72
- def _get_wdata(tdatap, wdeltas, s):
73
+ def _get_wdata(tdatap, wdeltas, variables, s):
73
74
  """Helper function for wake data extraction"""
74
- tdata = tdatap.get_slice(s, keep=True)
75
+ tdata = tdatap.get_slice(variables, s)
75
76
  wdelta = {v: d[s] for v, d in wdeltas.items()}
76
77
  return tdata, wdelta
77
78
 
@@ -127,7 +128,9 @@ class FarmWakesCalculation(FarmDataModel):
127
128
  )
128
129
 
129
130
  if oi < n_turbines - 1:
130
- tdata, wdelta = _get_wdata(tdatap, wdeltas, np.s_[:, oi + 1 :])
131
+ tdata, wdelta = _get_wdata(
132
+ tdatap, wdeltas, [FC.STATE, FC.TARGET], np.s_[:, oi + 1 :]
133
+ )
131
134
  gmodel.contribute_to_farm_wakes(
132
135
  algo, mdata, fdata, tdata, oi, wdelta, wmodel, pwake
133
136
  )
@@ -150,7 +153,9 @@ class FarmWakesCalculation(FarmDataModel):
150
153
  )
151
154
 
152
155
  if oi > 0:
153
- tdata, wdelta = _get_wdata(tdatap, wdeltas, np.s_[:, :oi])
156
+ tdata, wdelta = _get_wdata(
157
+ tdatap, wdeltas, [FC.STATE, FC.TARGET], np.s_[:, :oi]
158
+ )
154
159
  gmodel.contribute_to_farm_wakes(
155
160
  algo, mdata, fdata, tdata, oi, wdelta, wmodel, pwake
156
161
  )
@@ -88,7 +88,7 @@ class InitFarmData(FarmDataModel):
88
88
  if len(t.xy.shape) == 1:
89
89
  fdata[FV.TXYH][:, ti, :2] = t.xy[None, :]
90
90
  else:
91
- i0 = fdata.states_i0()
91
+ i0 = fdata.states_i0(counter=True)
92
92
  s = np.s_[i0 : i0 + fdata.n_states]
93
93
  fdata[FV.TXYH][:, ti, :2] = t.xy[s]
94
94
 
@@ -1,7 +1,5 @@
1
- import numpy as np
2
- from foxes.core import PointDataModel, TData
1
+ from foxes.core import PointDataModel
3
2
  import foxes.variables as FV
4
- import foxes.constants as FC
5
3
 
6
4
 
7
5
  class PointWakesCalculation(PointDataModel):
@@ -55,7 +53,7 @@ class PointWakesCalculation(PointDataModel):
55
53
  """
56
54
  return [self.emodels] if self.emodels is not None else []
57
55
 
58
- def initialize(self, algo, verbosity=0):
56
+ def initialize(self, algo, verbosity=0, force=False):
59
57
  """
60
58
  Initializes the model.
61
59
 
@@ -65,9 +63,11 @@ class PointWakesCalculation(PointDataModel):
65
63
  The calculation algorithm
66
64
  verbosity: int
67
65
  The verbosity level, 0 = silent
66
+ force: bool
67
+ Overwrite existing data
68
68
 
69
69
  """
70
- super().initialize(algo, verbosity)
70
+ super().initialize(algo, verbosity, force)
71
71
  self.pvars = algo.states.output_point_vars(algo)
72
72
 
73
73
  def output_point_vars(self, algo):
@@ -120,7 +120,6 @@ class PointWakesCalculation(PointDataModel):
120
120
  algo.wake_models.values() if self.wake_models is None else self.wake_models
121
121
  )
122
122
  for wmodel in wmodels:
123
- pwake = algo.partial_wakes[wmodel.name]
124
123
  gmodel = algo.ground_models[wmodel.name]
125
124
 
126
125
  wdeltas = gmodel.new_point_wake_deltas(algo, mdata, fdata, tdata, wmodel)
@@ -79,5 +79,4 @@ class ReorderFarmOutput(FarmDataModel):
79
79
  out[v] = fdata[v][ssel, order_inv]
80
80
  else:
81
81
  out[v] = fdata[v]
82
-
83
82
  return out
@@ -25,7 +25,7 @@ class SetAmbPointResults(PointDataModel):
25
25
  self.pvars = None
26
26
  self.vars = None
27
27
 
28
- def initialize(self, algo, verbosity=0):
28
+ def initialize(self, algo, verbosity=0, force=False):
29
29
  """
30
30
  Initializes the model.
31
31
 
@@ -35,11 +35,13 @@ class SetAmbPointResults(PointDataModel):
35
35
  The calculation algorithm
36
36
  verbosity: int
37
37
  The verbosity level, 0 = silent
38
+ force: bool
39
+ Overwrite existing data
38
40
 
39
41
  """
40
42
  self.pvars = algo.states.output_point_vars(algo)
41
43
  self.vars = [v for v in self.pvars if v in FV.var2amb]
42
- super().initialize(algo, verbosity)
44
+ super().initialize(algo, verbosity, force)
43
45
 
44
46
  def output_point_vars(self, algo):
45
47
  """