foxes 0.8.1__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.
- docs/source/conf.py +353 -0
- examples/abl_states/run.py +160 -0
- examples/compare_rotors_pwakes/run.py +217 -0
- examples/compare_wakes/run.py +241 -0
- examples/dyn_wakes/run.py +311 -0
- examples/field_data_nc/run.py +121 -0
- examples/induction_RHB/run.py +201 -0
- examples/multi_height/run.py +113 -0
- examples/power_mask/run.py +249 -0
- examples/random_timeseries/run.py +210 -0
- examples/scan_row/run.py +193 -0
- examples/sector_management/run.py +162 -0
- examples/sequential/run.py +209 -0
- examples/single_state/run.py +201 -0
- examples/states_lookup_table/run.py +137 -0
- examples/streamline_wakes/run.py +138 -0
- examples/tab_file/run.py +142 -0
- examples/timelines/run.py +267 -0
- examples/timeseries/run.py +183 -0
- examples/timeseries_slurm/run.py +185 -0
- examples/wind_rose/run.py +141 -0
- examples/windio/run.py +29 -0
- examples/yawed_wake/run.py +196 -0
- foxes/__init__.py +4 -8
- foxes/algorithms/__init__.py +1 -1
- foxes/algorithms/downwind/downwind.py +232 -101
- foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -6
- foxes/algorithms/downwind/models/init_farm_data.py +1 -1
- foxes/algorithms/downwind/models/point_wakes_calc.py +5 -6
- foxes/algorithms/downwind/models/reorder_farm_output.py +0 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +4 -2
- foxes/algorithms/iterative/iterative.py +73 -33
- foxes/algorithms/iterative/models/farm_wakes_calc.py +11 -6
- foxes/algorithms/sequential/models/plugin.py +1 -1
- foxes/algorithms/sequential/sequential.py +126 -255
- foxes/constants.py +17 -2
- foxes/core/__init__.py +1 -0
- foxes/core/algorithm.py +631 -146
- foxes/core/data.py +252 -20
- foxes/core/data_calc_model.py +13 -289
- foxes/core/engine.py +630 -0
- foxes/core/farm_controller.py +37 -9
- foxes/core/farm_data_model.py +15 -0
- foxes/core/model.py +133 -80
- foxes/core/point_data_model.py +15 -0
- foxes/core/rotor_model.py +27 -21
- foxes/core/states.py +16 -0
- foxes/core/turbine_type.py +28 -0
- foxes/core/wake_frame.py +22 -4
- foxes/core/wake_model.py +2 -3
- foxes/data/windio/windio_5turbines_timeseries.yaml +23 -1
- foxes/engines/__init__.py +16 -0
- foxes/engines/dask.py +975 -0
- foxes/engines/default.py +75 -0
- foxes/engines/futures.py +72 -0
- foxes/engines/mpi.py +38 -0
- foxes/engines/multiprocess.py +74 -0
- foxes/engines/numpy.py +185 -0
- foxes/engines/pool.py +263 -0
- foxes/engines/single.py +139 -0
- foxes/input/farm_layout/__init__.py +1 -0
- foxes/input/farm_layout/from_csv.py +4 -0
- foxes/input/farm_layout/from_json.py +1 -1
- foxes/input/farm_layout/grid.py +2 -2
- foxes/input/farm_layout/ring.py +65 -0
- foxes/input/farm_layout/row.py +2 -2
- foxes/input/states/__init__.py +6 -0
- foxes/input/states/create/random_abl_states.py +1 -1
- foxes/input/states/field_data_nc.py +157 -32
- foxes/input/states/multi_height.py +127 -13
- foxes/input/states/one_point_flow.py +577 -0
- foxes/input/states/scan_ws.py +73 -2
- foxes/input/states/states_table.py +204 -35
- foxes/input/windio/__init__.py +1 -1
- foxes/input/windio/get_states.py +44 -23
- foxes/input/windio/read_attributes.py +41 -16
- foxes/input/windio/read_farm.py +116 -102
- foxes/input/windio/read_fields.py +13 -6
- foxes/input/windio/read_outputs.py +63 -22
- foxes/input/windio/runner.py +31 -17
- foxes/input/windio/windio.py +36 -22
- foxes/models/ground_models/wake_mirror.py +8 -4
- foxes/models/model_book.py +29 -18
- foxes/models/partial_wakes/rotor_points.py +3 -3
- foxes/models/rotor_models/centre.py +4 -0
- foxes/models/rotor_models/grid.py +22 -23
- foxes/models/rotor_models/levels.py +4 -5
- foxes/models/turbine_models/calculator.py +0 -2
- foxes/models/turbine_models/lookup_table.py +27 -2
- foxes/models/turbine_models/rotor_centre_calc.py +4 -3
- foxes/models/turbine_models/set_farm_vars.py +103 -34
- foxes/models/turbine_types/PCt_file.py +24 -0
- foxes/models/turbine_types/PCt_from_two.py +24 -0
- foxes/models/turbine_types/__init__.py +1 -0
- foxes/models/turbine_types/lookup.py +316 -0
- foxes/models/turbine_types/null_type.py +50 -0
- foxes/models/turbine_types/wsrho2PCt_from_two.py +24 -0
- foxes/models/turbine_types/wsti2PCt_from_two.py +24 -0
- foxes/models/vertical_profiles/data_profile.py +1 -1
- foxes/models/wake_frames/__init__.py +1 -0
- foxes/models/wake_frames/dynamic_wakes.py +424 -0
- foxes/models/wake_frames/farm_order.py +23 -3
- foxes/models/wake_frames/rotor_wd.py +4 -2
- foxes/models/wake_frames/seq_dynamic_wakes.py +56 -63
- foxes/models/wake_frames/streamlines.py +19 -20
- foxes/models/wake_frames/timelines.py +328 -127
- foxes/models/wake_frames/yawed_wakes.py +4 -1
- foxes/models/wake_models/dist_sliced.py +1 -3
- foxes/models/wake_models/induction/rankine_half_body.py +4 -4
- foxes/models/wake_models/induction/rathmann.py +2 -2
- foxes/models/wake_models/induction/self_similar.py +2 -2
- foxes/models/wake_models/induction/vortex_sheet.py +2 -2
- foxes/models/wake_models/ti/iec_ti.py +34 -17
- foxes/models/wake_models/top_hat.py +1 -1
- foxes/models/wake_models/wind/bastankhah14.py +2 -2
- foxes/models/wake_models/wind/bastankhah16.py +8 -7
- foxes/models/wake_models/wind/jensen.py +1 -1
- foxes/models/wake_models/wind/turbopark.py +2 -2
- foxes/output/__init__.py +4 -1
- foxes/output/farm_layout.py +2 -2
- foxes/output/flow_plots_2d/__init__.py +0 -1
- foxes/output/flow_plots_2d/flow_plots.py +70 -30
- foxes/output/grids.py +91 -21
- foxes/output/seq_plugins/__init__.py +2 -0
- foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +62 -20
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
- foxes/output/slice_data.py +131 -111
- foxes/output/state_turbine_map.py +18 -13
- foxes/output/state_turbine_table.py +19 -19
- foxes/utils/__init__.py +1 -1
- foxes/utils/dev_utils.py +42 -0
- foxes/utils/dict.py +1 -1
- foxes/utils/factory.py +147 -52
- foxes/utils/pandas_helpers.py +4 -3
- foxes/utils/wind_dir.py +0 -2
- foxes/utils/xarray_utils.py +25 -13
- foxes/variables.py +37 -0
- {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/METADATA +72 -34
- foxes-1.0.dist-info/RECORD +307 -0
- {foxes-0.8.1.dist-info → foxes-1.0.dist-info}/WHEEL +1 -1
- foxes-1.0.dist-info/top_level.txt +4 -0
- tests/0_consistency/iterative/test_iterative.py +92 -0
- tests/0_consistency/partial_wakes/test_partial_wakes.py +90 -0
- tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +103 -0
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +87 -0
- tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +82 -0
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +82 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +93 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +96 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/flappy/run.py +94 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +122 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/flappy/run.py +94 -0
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +122 -0
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/flappy/run.py +92 -0
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +93 -0
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +85 -0
- tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +130 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/flappy/run.py +96 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +116 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +93 -0
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +99 -0
- tests/3_examples/test_examples.py +34 -0
- foxes/VERSION +0 -1
- foxes/output/flow_plots_2d.py +0 -0
- foxes/utils/plotly_helpers.py +0 -19
- foxes/utils/runners/__init__.py +0 -1
- foxes/utils/runners/runners.py +0 -280
- foxes-0.8.1.dist-info/RECORD +0 -248
- foxes-0.8.1.dist-info/top_level.txt +0 -1
- foxes-0.8.1.dist-info/zip-safe +0 -1
- {foxes-0.8.1.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
|
-
|
|
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
|
-
|
|
111
|
-
|
|
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,
|
|
113
|
+
super().__init__(mbook, farm, **kwargs)
|
|
120
114
|
|
|
121
|
-
self.
|
|
115
|
+
self.__states = states
|
|
122
116
|
self.n_states = None
|
|
123
|
-
self.states_data = None
|
|
124
117
|
|
|
125
|
-
self.
|
|
118
|
+
self.__rotor_model = self.mbook.rotor_models[rotor_model]
|
|
126
119
|
self.rotor_model.name = rotor_model
|
|
127
120
|
|
|
128
|
-
self.
|
|
121
|
+
self.__wake_frame = self.mbook.wake_frames[wake_frame]
|
|
129
122
|
self.wake_frame.name = wake_frame
|
|
130
123
|
|
|
131
|
-
self.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
376
|
+
def sub_models(self):
|
|
280
377
|
"""
|
|
281
|
-
|
|
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
|
-
|
|
291
|
-
|
|
382
|
+
smdls: list of foxes.core.Model
|
|
383
|
+
All sub models
|
|
292
384
|
|
|
293
385
|
"""
|
|
294
|
-
mdls = [
|
|
295
|
-
|
|
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
|
-
|
|
315
|
-
|
|
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
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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 =
|
|
380
|
-
|
|
381
|
-
|
|
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
|
-
|
|
452
|
-
|
|
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 =
|
|
561
|
+
farm_results = super().calc_farm(
|
|
461
562
|
mlist,
|
|
462
|
-
|
|
563
|
+
model_data,
|
|
463
564
|
parameters=calc_pars,
|
|
464
565
|
outputs=outputs,
|
|
465
566
|
**kwargs,
|
|
466
567
|
)
|
|
467
|
-
|
|
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
|
-
|
|
761
|
+
model_data = self.get_models_data(sel=sel, isel=isel)
|
|
609
762
|
if persist_mdata:
|
|
610
|
-
|
|
611
|
-
self.print("\nInput data:\n\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
|
|
624
|
-
sinds =
|
|
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
|
-
|
|
639
|
-
|
|
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
|
-
|
|
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 =
|
|
61
|
-
amb_res =
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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)
|
|
@@ -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
|
"""
|