foxes 0.8.2__py3-none-any.whl → 1.1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of foxes might be problematic. Click here for more details.

Files changed (215) 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/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 +190 -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 +247 -111
  27. foxes/algorithms/downwind/models/farm_wakes_calc.py +12 -7
  28. foxes/algorithms/downwind/models/init_farm_data.py +2 -2
  29. foxes/algorithms/downwind/models/point_wakes_calc.py +6 -7
  30. foxes/algorithms/downwind/models/reorder_farm_output.py +1 -2
  31. foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
  32. foxes/algorithms/downwind/models/set_amb_point_results.py +5 -3
  33. foxes/algorithms/iterative/iterative.py +74 -34
  34. foxes/algorithms/iterative/models/farm_wakes_calc.py +12 -7
  35. foxes/algorithms/iterative/models/urelax.py +3 -3
  36. foxes/algorithms/sequential/models/plugin.py +5 -5
  37. foxes/algorithms/sequential/models/seq_state.py +1 -1
  38. foxes/algorithms/sequential/sequential.py +126 -255
  39. foxes/constants.py +22 -7
  40. foxes/core/__init__.py +1 -0
  41. foxes/core/algorithm.py +632 -147
  42. foxes/core/data.py +252 -20
  43. foxes/core/data_calc_model.py +15 -291
  44. foxes/core/engine.py +640 -0
  45. foxes/core/farm_controller.py +38 -10
  46. foxes/core/farm_data_model.py +16 -1
  47. foxes/core/ground_model.py +2 -2
  48. foxes/core/model.py +249 -182
  49. foxes/core/partial_wakes_model.py +1 -1
  50. foxes/core/point_data_model.py +17 -2
  51. foxes/core/rotor_model.py +27 -21
  52. foxes/core/states.py +17 -1
  53. foxes/core/turbine_type.py +28 -0
  54. foxes/core/wake_frame.py +30 -34
  55. foxes/core/wake_model.py +5 -5
  56. foxes/core/wake_superposition.py +1 -1
  57. foxes/data/windio/windio_5turbines_timeseries.yaml +31 -15
  58. foxes/engines/__init__.py +17 -0
  59. foxes/engines/dask.py +982 -0
  60. foxes/engines/default.py +75 -0
  61. foxes/engines/futures.py +72 -0
  62. foxes/engines/mpi.py +38 -0
  63. foxes/engines/multiprocess.py +71 -0
  64. foxes/engines/numpy.py +167 -0
  65. foxes/engines/pool.py +249 -0
  66. foxes/engines/ray.py +79 -0
  67. foxes/engines/single.py +141 -0
  68. foxes/input/farm_layout/__init__.py +1 -0
  69. foxes/input/farm_layout/from_csv.py +4 -0
  70. foxes/input/farm_layout/from_json.py +2 -2
  71. foxes/input/farm_layout/grid.py +2 -2
  72. foxes/input/farm_layout/ring.py +65 -0
  73. foxes/input/farm_layout/row.py +2 -2
  74. foxes/input/states/__init__.py +7 -0
  75. foxes/input/states/create/random_abl_states.py +1 -1
  76. foxes/input/states/field_data_nc.py +158 -33
  77. foxes/input/states/multi_height.py +128 -14
  78. foxes/input/states/one_point_flow.py +577 -0
  79. foxes/input/states/scan_ws.py +74 -3
  80. foxes/input/states/single.py +1 -1
  81. foxes/input/states/slice_data_nc.py +681 -0
  82. foxes/input/states/states_table.py +204 -35
  83. foxes/input/windio/__init__.py +2 -2
  84. foxes/input/windio/get_states.py +44 -23
  85. foxes/input/windio/read_attributes.py +48 -17
  86. foxes/input/windio/read_farm.py +116 -102
  87. foxes/input/windio/read_fields.py +16 -6
  88. foxes/input/windio/read_outputs.py +71 -24
  89. foxes/input/windio/runner.py +31 -17
  90. foxes/input/windio/windio.py +41 -23
  91. foxes/models/farm_models/turbine2farm.py +1 -1
  92. foxes/models/ground_models/wake_mirror.py +10 -6
  93. foxes/models/model_book.py +58 -20
  94. foxes/models/partial_wakes/axiwake.py +3 -3
  95. foxes/models/partial_wakes/rotor_points.py +3 -3
  96. foxes/models/partial_wakes/top_hat.py +2 -2
  97. foxes/models/point_models/set_uniform_data.py +1 -1
  98. foxes/models/point_models/tke2ti.py +1 -1
  99. foxes/models/point_models/wake_deltas.py +1 -1
  100. foxes/models/rotor_models/centre.py +4 -0
  101. foxes/models/rotor_models/grid.py +24 -25
  102. foxes/models/rotor_models/levels.py +4 -5
  103. foxes/models/turbine_models/calculator.py +4 -6
  104. foxes/models/turbine_models/kTI_model.py +22 -6
  105. foxes/models/turbine_models/lookup_table.py +30 -4
  106. foxes/models/turbine_models/rotor_centre_calc.py +4 -3
  107. foxes/models/turbine_models/set_farm_vars.py +103 -34
  108. foxes/models/turbine_types/PCt_file.py +27 -3
  109. foxes/models/turbine_types/PCt_from_two.py +27 -3
  110. foxes/models/turbine_types/TBL_file.py +80 -0
  111. foxes/models/turbine_types/__init__.py +2 -0
  112. foxes/models/turbine_types/lookup.py +316 -0
  113. foxes/models/turbine_types/null_type.py +51 -1
  114. foxes/models/turbine_types/wsrho2PCt_from_two.py +29 -5
  115. foxes/models/turbine_types/wsti2PCt_from_two.py +31 -7
  116. foxes/models/vertical_profiles/__init__.py +1 -1
  117. foxes/models/vertical_profiles/data_profile.py +1 -1
  118. foxes/models/wake_frames/__init__.py +1 -0
  119. foxes/models/wake_frames/dynamic_wakes.py +424 -0
  120. foxes/models/wake_frames/farm_order.py +25 -5
  121. foxes/models/wake_frames/rotor_wd.py +6 -4
  122. foxes/models/wake_frames/seq_dynamic_wakes.py +61 -74
  123. foxes/models/wake_frames/streamlines.py +21 -22
  124. foxes/models/wake_frames/timelines.py +330 -129
  125. foxes/models/wake_frames/yawed_wakes.py +7 -4
  126. foxes/models/wake_models/dist_sliced.py +2 -4
  127. foxes/models/wake_models/induction/rankine_half_body.py +5 -5
  128. foxes/models/wake_models/induction/rathmann.py +78 -24
  129. foxes/models/wake_models/induction/self_similar.py +78 -28
  130. foxes/models/wake_models/induction/vortex_sheet.py +86 -48
  131. foxes/models/wake_models/ti/crespo_hernandez.py +6 -4
  132. foxes/models/wake_models/ti/iec_ti.py +40 -21
  133. foxes/models/wake_models/top_hat.py +1 -1
  134. foxes/models/wake_models/wind/bastankhah14.py +8 -6
  135. foxes/models/wake_models/wind/bastankhah16.py +17 -16
  136. foxes/models/wake_models/wind/jensen.py +4 -3
  137. foxes/models/wake_models/wind/turbopark.py +16 -13
  138. foxes/models/wake_superpositions/ti_linear.py +1 -1
  139. foxes/models/wake_superpositions/ti_max.py +1 -1
  140. foxes/models/wake_superpositions/ti_pow.py +1 -1
  141. foxes/models/wake_superpositions/ti_quadratic.py +1 -1
  142. foxes/models/wake_superpositions/ws_linear.py +8 -7
  143. foxes/models/wake_superpositions/ws_max.py +8 -7
  144. foxes/models/wake_superpositions/ws_pow.py +8 -7
  145. foxes/models/wake_superpositions/ws_product.py +5 -5
  146. foxes/models/wake_superpositions/ws_quadratic.py +8 -7
  147. foxes/output/__init__.py +4 -1
  148. foxes/output/farm_layout.py +16 -12
  149. foxes/output/farm_results_eval.py +1 -1
  150. foxes/output/flow_plots_2d/__init__.py +0 -1
  151. foxes/output/flow_plots_2d/flow_plots.py +70 -30
  152. foxes/output/grids.py +92 -22
  153. foxes/output/results_writer.py +2 -2
  154. foxes/output/rose_plot.py +3 -3
  155. foxes/output/seq_plugins/__init__.py +2 -0
  156. foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +64 -22
  157. foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
  158. foxes/output/slice_data.py +131 -111
  159. foxes/output/state_turbine_map.py +19 -14
  160. foxes/output/state_turbine_table.py +19 -19
  161. foxes/utils/__init__.py +1 -1
  162. foxes/utils/abl/neutral.py +2 -2
  163. foxes/utils/abl/stable.py +2 -2
  164. foxes/utils/abl/unstable.py +2 -2
  165. foxes/utils/data_book.py +1 -1
  166. foxes/utils/dev_utils.py +42 -0
  167. foxes/utils/dict.py +24 -1
  168. foxes/utils/exec_python.py +1 -1
  169. foxes/utils/factory.py +176 -53
  170. foxes/utils/geom2d/circle.py +1 -1
  171. foxes/utils/geom2d/polygon.py +1 -1
  172. foxes/utils/geopandas_utils.py +2 -2
  173. foxes/utils/load.py +2 -2
  174. foxes/utils/pandas_helpers.py +3 -2
  175. foxes/utils/wind_dir.py +0 -2
  176. foxes/utils/xarray_utils.py +24 -14
  177. foxes/variables.py +39 -2
  178. {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/METADATA +75 -33
  179. foxes-1.1.0.2.dist-info/RECORD +309 -0
  180. {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/WHEEL +1 -1
  181. foxes-1.1.0.2.dist-info/top_level.txt +4 -0
  182. tests/0_consistency/iterative/test_iterative.py +92 -0
  183. tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
  184. tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
  185. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
  186. tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
  187. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
  188. tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
  189. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
  190. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
  191. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
  192. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
  193. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
  194. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
  195. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
  196. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
  197. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
  198. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
  199. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
  200. tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
  201. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
  202. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
  203. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
  204. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
  205. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
  206. tests/3_examples/test_examples.py +34 -0
  207. foxes/VERSION +0 -1
  208. foxes/output/flow_plots_2d.py +0 -0
  209. foxes/utils/geopandas_helpers.py +0 -294
  210. foxes/utils/runners/__init__.py +0 -1
  211. foxes/utils/runners/runners.py +0 -280
  212. foxes-0.8.2.dist-info/RECORD +0 -247
  213. foxes-0.8.2.dist-info/top_level.txt +0 -1
  214. foxes-0.8.2.dist-info/zip-safe +0 -1
  215. {foxes-0.8.2.dist-info → foxes-1.1.0.2.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,35 +101,29 @@ 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.get_item(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.get_item(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
- m = self.mbook.wake_models[w]
126
+ m = self.mbook.wake_models.get_item(w)
134
127
  m.name = w
135
128
  self.wake_models[w] = m
136
129
 
@@ -144,10 +137,12 @@ class Downwind(Algorithm):
144
137
  try:
145
138
  pw = values
146
139
  if checkw:
147
- mbooks[pw].check_wmodel(self.wake_models[w], error=True)
140
+ mbooks.get_item(pw).check_wmodel(
141
+ self.wake_models[w], error=True
142
+ )
148
143
  except TypeError:
149
144
  pw = deffunc(self.wake_models[w])
150
- target[w] = mbooks[pw]
145
+ target[w] = mbooks.get_item(pw)
151
146
  target[w].name = pw
152
147
  elif isinstance(values, list):
153
148
  for i, w in enumerate(wake_models):
@@ -156,7 +151,7 @@ class Downwind(Algorithm):
156
151
  f"Not enough {descr} in list {values}, expecting {len(wake_models)}"
157
152
  )
158
153
  pw = values[i]
159
- target[w] = mbooks[pw]
154
+ target[w] = mbooks.get_item(pw)
160
155
  target[w].name = pw
161
156
  else:
162
157
  for w in wake_models:
@@ -164,10 +159,10 @@ class Downwind(Algorithm):
164
159
  pw = values[w]
165
160
  else:
166
161
  pw = deffunc(self.wake_models[w])
167
- target[w] = mbooks[pw]
162
+ target[w] = mbooks.get_item(pw)
168
163
  target[w].name = pw
169
164
 
170
- self.partial_wakes = {}
165
+ self.__partial_wakes = {}
171
166
  _set_wspecific(
172
167
  descr="partial wakes",
173
168
  target=self.partial_wakes,
@@ -177,7 +172,7 @@ class Downwind(Algorithm):
177
172
  checkw=True,
178
173
  )
179
174
 
180
- self.ground_models = {}
175
+ self.__ground_models = {}
181
176
  _set_wspecific(
182
177
  descr="ground models",
183
178
  target=self.ground_models,
@@ -187,9 +182,113 @@ class Downwind(Algorithm):
187
182
  checkw=False,
188
183
  )
189
184
 
190
- self.farm_controller = self.mbook.farm_controllers[farm_controller]
185
+ self.__farm_controller = self.mbook.farm_controllers.get_item(farm_controller)
191
186
  self.farm_controller.name = farm_controller
192
187
 
188
+ @property
189
+ def states(self):
190
+ """
191
+ The states
192
+
193
+ Returns
194
+ -------
195
+ m: foxes.core.States
196
+ The states
197
+
198
+ """
199
+ return self.__states
200
+
201
+ @states.setter
202
+ def states(self, value):
203
+ """Resets the states"""
204
+ if self.running:
205
+ raise ValueError(f"{self.name}: Cannot set states while running")
206
+ if self.states.initialized:
207
+ self.states.finalize(self, verbosity=self.verbosity)
208
+ self.__states = value
209
+ self.init_states()
210
+
211
+ @property
212
+ def rotor_model(self):
213
+ """
214
+ The rotor model
215
+
216
+ Returns
217
+ -------
218
+ m: foxes.core.RotorModel
219
+ The rotor model
220
+
221
+ """
222
+ return self.__rotor_model
223
+
224
+ @property
225
+ def wake_models(self):
226
+ """
227
+ The wake models
228
+
229
+ Returns
230
+ -------
231
+ m: dict
232
+ The wake models. Key: name,
233
+ value: foxes.core.WakeModel
234
+
235
+ """
236
+ return self.__wake_models
237
+
238
+ @property
239
+ def wake_frame(self):
240
+ """
241
+ The wake frame
242
+
243
+ Returns
244
+ -------
245
+ m: foxes.core.WakeFrame
246
+ The wake frame
247
+
248
+ """
249
+ return self.__wake_frame
250
+
251
+ @property
252
+ def partial_wakes(self):
253
+ """
254
+ The partial wakes models
255
+
256
+ Returns
257
+ -------
258
+ m: dict
259
+ The partial wakes models. Key: name,
260
+ value: foxes.core.PartialWakesModel
261
+
262
+ """
263
+ return self.__partial_wakes
264
+
265
+ @property
266
+ def ground_models(self):
267
+ """
268
+ The ground models
269
+
270
+ Returns
271
+ -------
272
+ m: dict
273
+ The ground models, key: name,
274
+ value: foxes.core.GroundModel
275
+
276
+ """
277
+ return self.__ground_models
278
+
279
+ @property
280
+ def farm_controller(self):
281
+ """
282
+ The farm controller
283
+
284
+ Returns
285
+ -------
286
+ m: foxes.core.FarmController
287
+ The farm controller
288
+
289
+ """
290
+ return self.__farm_controller
291
+
193
292
  @classmethod
194
293
  def get_model(cls, name):
195
294
  """
@@ -276,29 +375,25 @@ class Downwind(Algorithm):
276
375
  self.states.initialize(self, self.verbosity)
277
376
  self.n_states = self.states.size()
278
377
 
279
- def all_models(self, with_states=True):
378
+ def sub_models(self):
280
379
  """
281
- Return all models
282
-
283
- Parameters
284
- ----------
285
- with_states: bool
286
- Flag for including states
380
+ List of all sub-models
287
381
 
288
382
  Returns
289
383
  -------
290
- mdls: list of foxes.core.Model
291
- The list of models
384
+ smdls: list of foxes.core.Model
385
+ All sub models
292
386
 
293
387
  """
294
- mdls = [self.states] if with_states else []
295
- mdls += [
296
- self.rotor_model,
388
+ mdls = [
389
+ self.states,
297
390
  self.farm_controller,
391
+ self.rotor_model,
298
392
  self.wake_frame,
299
393
  ]
300
394
  mdls += list(self.wake_models.values())
301
395
  mdls += list(self.partial_wakes.values())
396
+ mdls += list(self.ground_models.values())
302
397
 
303
398
  return mdls
304
399
 
@@ -306,13 +401,10 @@ class Downwind(Algorithm):
306
401
  """
307
402
  Initializes the algorithm.
308
403
  """
309
- self.print(f"\nInitializing algorithm '{self.name}'")
310
- super().initialize()
311
-
312
404
  self.init_states()
313
405
 
314
- for m in self.all_models(with_states=False):
315
- m.initialize(self, self.verbosity)
406
+ self.print(f"\nInitializing algorithm '{self.name}'")
407
+ super().initialize()
316
408
 
317
409
  def _collect_farm_models(
318
410
  self,
@@ -370,17 +462,38 @@ class Downwind(Algorithm):
370
462
  """Helper function that gathers the farm variables"""
371
463
  self.farm_vars = sorted(list(set([FV.WEIGHT] + mlist.output_farm_vars(self))))
372
464
 
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
- )
465
+ def _launch_parallel_farm_calc(
466
+ self,
467
+ mlist,
468
+ *data,
469
+ outputs=None,
470
+ **kwargs,
471
+ ):
472
+ """
473
+ Runs the main calculation, launching parallelization
474
+
475
+ Parameters
476
+ ----------
477
+ mlist: foxes.models.FarmDataModelList
478
+ The model list
479
+ data: tuple of xarray.Dataset
480
+ The (mdata, fdata) inputs
481
+ outputs: list of str, optional
482
+ The output variables, or None for defaults
483
+ kwargs: dict, optional
484
+ Additional parameters for running
485
+
486
+ Returns
487
+ -------
488
+ farm_results: xarray.Dataset
489
+ The farm results. The calculated variables have
490
+ dimensions (state, turbine)
491
+
492
+ """
378
493
  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)
494
+ farm_results = get_engine().run_calculation(
495
+ self, mlist, *data, out_vars=out_vars, **kwargs
496
+ )
384
497
 
385
498
  return farm_results
386
499
 
@@ -388,10 +501,8 @@ class Downwind(Algorithm):
388
501
  self,
389
502
  outputs=None,
390
503
  calc_parameters={},
391
- persist=True,
392
504
  finalize=True,
393
505
  ambient=False,
394
- chunked_results=False,
395
506
  **kwargs,
396
507
  ):
397
508
  """
@@ -404,15 +515,10 @@ class Downwind(Algorithm):
404
515
  Key: model name str, value: parameter dict
405
516
  outputs: list of str, optional
406
517
  The output variables, or None for defaults
407
- persist: bool
408
- Switch for forcing dask to load all model data
409
- into memory
410
518
  finalize: bool
411
519
  Flag for finalization after calculation
412
520
  ambient: bool
413
521
  Flag for ambient instead of waked calculation
414
- chunked_results: bool
415
- Flag for chunked results
416
522
  kwargs: dict, optional
417
523
  Additional parameters for run_calculation
418
524
 
@@ -437,7 +543,7 @@ class Downwind(Algorithm):
437
543
 
438
544
  # initialize models:
439
545
  if not mlist.initialized:
440
- mlist.initialize(self, self.verbosity)
546
+ mlist.initialize(self, self.verbosity - 1)
441
547
  self._calc_farm_vars(mlist)
442
548
  self._print_model_oder(mlist, calc_pars)
443
549
 
@@ -448,37 +554,37 @@ class Downwind(Algorithm):
448
554
  outputs = sorted(list(set(outputs).intersection(self.farm_vars)))
449
555
 
450
556
  # 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")
557
+ model_data = self.get_models_data()
558
+ self.print("\nInput data:\n\n", model_data, "\n")
455
559
  self.print(f"\nFarm variables:", ", ".join(self.farm_vars))
456
560
  self.print(f"\nOutput variables:", ", ".join(outputs))
457
- self.print(f"\nChunks: {self.chunks}\n")
458
561
 
459
562
  # run main calculation:
460
- farm_results = self._run_farm_calc(
563
+ farm_results = super().calc_farm(
461
564
  mlist,
462
- models_data,
565
+ model_data,
463
566
  parameters=calc_pars,
464
567
  outputs=outputs,
465
568
  **kwargs,
466
569
  )
467
- del models_data
570
+ farm_results[FC.TNAME] = ((FC.TURBINE,), self.farm.turbine_names)
571
+ for v in [FV.ORDER, FV.ORDER_SSEL, FV.ORDER_INV]:
572
+ if v in farm_results:
573
+ farm_results[v] = farm_results[v].astype(FC.ITYPE)
574
+ del model_data
468
575
 
469
576
  # finalize models:
470
577
  if finalize:
471
578
  self.print("\n")
472
- mlist.finalize(self, self.verbosity)
579
+ mlist.finalize(self, self.verbosity - 1)
473
580
  self.finalize()
581
+ else:
582
+ self.del_model_data(mlist)
474
583
 
475
584
  if ambient:
476
585
  dvars = [v for v in farm_results.data_vars.keys() if v in FV.var2amb]
477
586
  farm_results = farm_results.drop_vars(dvars)
478
587
 
479
- if chunked_results:
480
- farm_results = self.chunked(farm_results)
481
-
482
588
  return farm_results
483
589
 
484
590
  def _collect_point_models(
@@ -534,17 +640,55 @@ class Downwind(Algorithm):
534
640
 
535
641
  return mlist, calc_pars
536
642
 
643
+ def _launch_parallel_points_calc(self, mlist, *data, outputs=None, **kwargs):
644
+ """
645
+ Runs the main points calculation, launching parallelization
646
+
647
+ Parameters
648
+ ----------
649
+ mlist: foxes.models.FarmDataModelList
650
+ The model list
651
+ data: tuple of xarray.Dataset
652
+ The (mdata, fdata) inputs
653
+ outputs: list of str, optional
654
+ The output variables, or None for defaults
655
+ kwargs: dict, optional
656
+ Additional parameters for running
657
+
658
+ Returns
659
+ -------
660
+ point_results: xarray.Dataset
661
+ The point results. The calculated variables have
662
+ dimensions (state, point)
663
+
664
+ """
665
+ return (
666
+ get_engine()
667
+ .run_calculation(
668
+ self,
669
+ mlist,
670
+ *data,
671
+ out_vars=outputs,
672
+ **kwargs,
673
+ )
674
+ .sel({FC.TPOINT: 0})
675
+ .rename({FC.TARGET: FC.POINT})
676
+ )
677
+
537
678
  def calc_points(
538
679
  self,
539
680
  farm_results,
540
681
  points,
541
682
  point_models=None,
683
+ outputs=None,
542
684
  calc_parameters={},
543
685
  persist_mdata=True,
544
686
  persist_pdata=False,
545
687
  finalize=True,
546
688
  ambient=False,
547
689
  chunked_results=False,
690
+ states_sel=None,
691
+ states_isel=None,
548
692
  **kwargs,
549
693
  ):
550
694
  """
@@ -557,6 +701,8 @@ class Downwind(Algorithm):
557
701
  dimensions (state, turbine)
558
702
  points: numpy.ndarray
559
703
  The points of interest, shape: (n_states, n_points, 3)
704
+ outputs: list of str, optional
705
+ The output variables, or None for defaults
560
706
  point_models: str or foxes.core.PointDataModel
561
707
  Additional point models to be executed
562
708
  calc_parameters: dict
@@ -574,6 +720,10 @@ class Downwind(Algorithm):
574
720
  Flag for ambient instead of waked calculation
575
721
  chunked_results: bool
576
722
  Flag for chunked results
723
+ states_sel: list, optional
724
+ Reduce to selected states
725
+ states_isel: list, optional
726
+ Reduce to the selected states indices
577
727
  kwargs: dict, optional
578
728
  Additional parameters for run_calculation
579
729
 
@@ -584,7 +734,6 @@ class Downwind(Algorithm):
584
734
  dimensions (state, point)
585
735
 
586
736
  """
587
-
588
737
  if not self.initialized:
589
738
  self.initialize()
590
739
  if not ambient and farm_results is None:
@@ -602,59 +751,61 @@ class Downwind(Algorithm):
602
751
 
603
752
  # initialize models:
604
753
  if not mlist.initialized:
605
- mlist.initialize(self, self.verbosity)
754
+ mlist.initialize(self, self.verbosity - 1)
755
+
756
+ # subset selections:
757
+ sel = {} if states_sel is None else {FC.STATE: states_sel}
758
+ isel = {} if states_isel is None else {FC.STATE: states_isel}
759
+ if states_isel is not None:
760
+ farm_results = farm_results.isel(isel)
761
+ if states_sel is not None:
762
+ farm_results = farm_results.sel(sel)
763
+ n_states = farm_results.sizes[FC.STATE]
606
764
 
607
765
  # get input model data:
608
- models_data = self.get_models_data()
766
+ model_data = self.get_models_data(sel=sel, isel=isel)
609
767
  if persist_mdata:
610
- models_data = models_data.persist()
611
- self.print("\nInput data:\n\n", models_data, "\n")
768
+ model_data = model_data.persist()
769
+ self.print("\nInput data:\n\n", model_data, "\n")
612
770
  self.print(f"\nOutput farm variables:", ", ".join(self.farm_vars))
613
- self.print(f"\nChunks: {self.chunks}\n")
614
771
 
615
772
  # chunk farm results:
616
- if self.chunks is not None:
617
- farm_results = self.chunked(farm_results)
618
773
  self.print("\nInput farm data:\n\n", farm_results, "\n")
619
774
 
620
775
  # get point data:
621
776
  if FC.STATE in farm_results.coords:
622
777
  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]
778
+ elif model_data is not None and FC.STATE in model_data.coords:
779
+ sinds = model_data.coords[FC.STATE]
625
780
  else:
626
781
  sinds = None
627
- point_data = self.new_point_data(points, sinds)
782
+ point_data = self.new_point_data(points, sinds, n_states=n_states)
628
783
  if persist_pdata:
629
784
  point_data = point_data.persist()
630
785
  self.print("\nInput point data:\n\n", point_data, "\n")
631
786
 
632
787
  # check vars:
633
- ovars = mlist.output_point_vars(self)
788
+ ovars = mlist.output_point_vars(self) if outputs is None else outputs
634
789
  self.print(f"\nOutput point variables:", ", ".join(ovars))
635
- self.print(f"\nChunks: {self.chunks}\n")
636
790
 
637
791
  # 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,
792
+ point_results = super().calc_points(
793
+ mlist,
794
+ model_data,
645
795
  farm_results,
646
796
  point_data,
647
- out_vars=ovars,
797
+ outputs=ovars,
648
798
  parameters=calc_pars,
799
+ # sel=sel,
800
+ # isel=isel,
649
801
  **kwargs,
650
802
  )
651
-
652
- del models_data, farm_results, point_data
803
+ del model_data, farm_results, point_data
653
804
 
654
805
  # finalize models:
655
806
  if finalize:
656
807
  self.print("\n")
657
- mlist.finalize(self, self.verbosity)
808
+ mlist.finalize(self, self.verbosity - 1)
658
809
  self.finalize()
659
810
 
660
811
  if ambient:
@@ -665,18 +816,3 @@ class Downwind(Algorithm):
665
816
  point_results = self.chunked(point_results)
666
817
 
667
818
  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):
@@ -33,7 +34,7 @@ class FarmWakesCalculation(FarmDataModel):
33
34
  return list(dict.fromkeys(ovars))
34
35
 
35
36
  def calculate(self, algo, mdata, fdata):
36
- """ "
37
+ """
37
38
  The main model calculation.
38
39
 
39
40
  This function is executed on a single chunk of data,
@@ -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
  )
@@ -48,7 +48,7 @@ class InitFarmData(FarmDataModel):
48
48
  ]
49
49
 
50
50
  def calculate(self, algo, mdata, fdata):
51
- """ "
51
+ """
52
52
  The main model calculation.
53
53
 
54
54
  This function is executed on a single chunk of data,
@@ -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