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.
- 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/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 +190 -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 +247 -111
- foxes/algorithms/downwind/models/farm_wakes_calc.py +12 -7
- foxes/algorithms/downwind/models/init_farm_data.py +2 -2
- foxes/algorithms/downwind/models/point_wakes_calc.py +6 -7
- foxes/algorithms/downwind/models/reorder_farm_output.py +1 -2
- foxes/algorithms/downwind/models/set_amb_farm_results.py +1 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +5 -3
- foxes/algorithms/iterative/iterative.py +74 -34
- foxes/algorithms/iterative/models/farm_wakes_calc.py +12 -7
- foxes/algorithms/iterative/models/urelax.py +3 -3
- foxes/algorithms/sequential/models/plugin.py +5 -5
- foxes/algorithms/sequential/models/seq_state.py +1 -1
- foxes/algorithms/sequential/sequential.py +126 -255
- foxes/constants.py +22 -7
- foxes/core/__init__.py +1 -0
- foxes/core/algorithm.py +632 -147
- foxes/core/data.py +252 -20
- foxes/core/data_calc_model.py +15 -291
- foxes/core/engine.py +640 -0
- foxes/core/farm_controller.py +38 -10
- foxes/core/farm_data_model.py +16 -1
- foxes/core/ground_model.py +2 -2
- foxes/core/model.py +249 -182
- foxes/core/partial_wakes_model.py +1 -1
- foxes/core/point_data_model.py +17 -2
- foxes/core/rotor_model.py +27 -21
- foxes/core/states.py +17 -1
- foxes/core/turbine_type.py +28 -0
- foxes/core/wake_frame.py +30 -34
- foxes/core/wake_model.py +5 -5
- foxes/core/wake_superposition.py +1 -1
- foxes/data/windio/windio_5turbines_timeseries.yaml +31 -15
- foxes/engines/__init__.py +17 -0
- foxes/engines/dask.py +982 -0
- foxes/engines/default.py +75 -0
- foxes/engines/futures.py +72 -0
- foxes/engines/mpi.py +38 -0
- foxes/engines/multiprocess.py +71 -0
- foxes/engines/numpy.py +167 -0
- foxes/engines/pool.py +249 -0
- foxes/engines/ray.py +79 -0
- foxes/engines/single.py +141 -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 +2 -2
- 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 +7 -0
- foxes/input/states/create/random_abl_states.py +1 -1
- foxes/input/states/field_data_nc.py +158 -33
- foxes/input/states/multi_height.py +128 -14
- foxes/input/states/one_point_flow.py +577 -0
- foxes/input/states/scan_ws.py +74 -3
- foxes/input/states/single.py +1 -1
- foxes/input/states/slice_data_nc.py +681 -0
- foxes/input/states/states_table.py +204 -35
- foxes/input/windio/__init__.py +2 -2
- foxes/input/windio/get_states.py +44 -23
- foxes/input/windio/read_attributes.py +48 -17
- foxes/input/windio/read_farm.py +116 -102
- foxes/input/windio/read_fields.py +16 -6
- foxes/input/windio/read_outputs.py +71 -24
- foxes/input/windio/runner.py +31 -17
- foxes/input/windio/windio.py +41 -23
- foxes/models/farm_models/turbine2farm.py +1 -1
- foxes/models/ground_models/wake_mirror.py +10 -6
- foxes/models/model_book.py +58 -20
- foxes/models/partial_wakes/axiwake.py +3 -3
- foxes/models/partial_wakes/rotor_points.py +3 -3
- foxes/models/partial_wakes/top_hat.py +2 -2
- foxes/models/point_models/set_uniform_data.py +1 -1
- foxes/models/point_models/tke2ti.py +1 -1
- foxes/models/point_models/wake_deltas.py +1 -1
- foxes/models/rotor_models/centre.py +4 -0
- foxes/models/rotor_models/grid.py +24 -25
- foxes/models/rotor_models/levels.py +4 -5
- foxes/models/turbine_models/calculator.py +4 -6
- foxes/models/turbine_models/kTI_model.py +22 -6
- foxes/models/turbine_models/lookup_table.py +30 -4
- 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 +27 -3
- foxes/models/turbine_types/PCt_from_two.py +27 -3
- foxes/models/turbine_types/TBL_file.py +80 -0
- foxes/models/turbine_types/__init__.py +2 -0
- foxes/models/turbine_types/lookup.py +316 -0
- foxes/models/turbine_types/null_type.py +51 -1
- foxes/models/turbine_types/wsrho2PCt_from_two.py +29 -5
- foxes/models/turbine_types/wsti2PCt_from_two.py +31 -7
- foxes/models/vertical_profiles/__init__.py +1 -1
- 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 +25 -5
- foxes/models/wake_frames/rotor_wd.py +6 -4
- foxes/models/wake_frames/seq_dynamic_wakes.py +61 -74
- foxes/models/wake_frames/streamlines.py +21 -22
- foxes/models/wake_frames/timelines.py +330 -129
- foxes/models/wake_frames/yawed_wakes.py +7 -4
- foxes/models/wake_models/dist_sliced.py +2 -4
- foxes/models/wake_models/induction/rankine_half_body.py +5 -5
- foxes/models/wake_models/induction/rathmann.py +78 -24
- foxes/models/wake_models/induction/self_similar.py +78 -28
- foxes/models/wake_models/induction/vortex_sheet.py +86 -48
- foxes/models/wake_models/ti/crespo_hernandez.py +6 -4
- foxes/models/wake_models/ti/iec_ti.py +40 -21
- foxes/models/wake_models/top_hat.py +1 -1
- foxes/models/wake_models/wind/bastankhah14.py +8 -6
- foxes/models/wake_models/wind/bastankhah16.py +17 -16
- foxes/models/wake_models/wind/jensen.py +4 -3
- foxes/models/wake_models/wind/turbopark.py +16 -13
- foxes/models/wake_superpositions/ti_linear.py +1 -1
- foxes/models/wake_superpositions/ti_max.py +1 -1
- foxes/models/wake_superpositions/ti_pow.py +1 -1
- foxes/models/wake_superpositions/ti_quadratic.py +1 -1
- foxes/models/wake_superpositions/ws_linear.py +8 -7
- foxes/models/wake_superpositions/ws_max.py +8 -7
- foxes/models/wake_superpositions/ws_pow.py +8 -7
- foxes/models/wake_superpositions/ws_product.py +5 -5
- foxes/models/wake_superpositions/ws_quadratic.py +8 -7
- foxes/output/__init__.py +4 -1
- foxes/output/farm_layout.py +16 -12
- foxes/output/farm_results_eval.py +1 -1
- foxes/output/flow_plots_2d/__init__.py +0 -1
- foxes/output/flow_plots_2d/flow_plots.py +70 -30
- foxes/output/grids.py +92 -22
- foxes/output/results_writer.py +2 -2
- foxes/output/rose_plot.py +3 -3
- foxes/output/seq_plugins/__init__.py +2 -0
- foxes/output/{flow_plots_2d → seq_plugins}/seq_flow_ani_plugin.py +64 -22
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +145 -0
- foxes/output/slice_data.py +131 -111
- foxes/output/state_turbine_map.py +19 -14
- foxes/output/state_turbine_table.py +19 -19
- foxes/utils/__init__.py +1 -1
- foxes/utils/abl/neutral.py +2 -2
- foxes/utils/abl/stable.py +2 -2
- foxes/utils/abl/unstable.py +2 -2
- foxes/utils/data_book.py +1 -1
- foxes/utils/dev_utils.py +42 -0
- foxes/utils/dict.py +24 -1
- foxes/utils/exec_python.py +1 -1
- foxes/utils/factory.py +176 -53
- foxes/utils/geom2d/circle.py +1 -1
- foxes/utils/geom2d/polygon.py +1 -1
- foxes/utils/geopandas_utils.py +2 -2
- foxes/utils/load.py +2 -2
- foxes/utils/pandas_helpers.py +3 -2
- foxes/utils/wind_dir.py +0 -2
- foxes/utils/xarray_utils.py +24 -14
- foxes/variables.py +39 -2
- {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/METADATA +75 -33
- foxes-1.1.0.2.dist-info/RECORD +309 -0
- {foxes-0.8.2.dist-info → foxes-1.1.0.2.dist-info}/WHEEL +1 -1
- foxes-1.1.0.2.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/geopandas_helpers.py +0 -294
- foxes/utils/runners/__init__.py +0 -1
- foxes/utils/runners/runners.py +0 -280
- foxes-0.8.2.dist-info/RECORD +0 -247
- foxes-0.8.2.dist-info/top_level.txt +0 -1
- foxes-0.8.2.dist-info/zip-safe +0 -1
- {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
|
-
|
|
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
|
-
|
|
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.get_item(rotor_model)
|
|
126
119
|
self.rotor_model.name = rotor_model
|
|
127
120
|
|
|
128
|
-
self.
|
|
121
|
+
self.__wake_frame = self.mbook.wake_frames.get_item(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
|
-
m = self.mbook.wake_models
|
|
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
|
|
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
|
|
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
|
|
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
|
|
162
|
+
target[w] = mbooks.get_item(pw)
|
|
168
163
|
target[w].name = pw
|
|
169
164
|
|
|
170
|
-
self.
|
|
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.
|
|
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.
|
|
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
|
|
378
|
+
def sub_models(self):
|
|
280
379
|
"""
|
|
281
|
-
|
|
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
|
-
|
|
291
|
-
|
|
384
|
+
smdls: list of foxes.core.Model
|
|
385
|
+
All sub models
|
|
292
386
|
|
|
293
387
|
"""
|
|
294
|
-
mdls = [
|
|
295
|
-
|
|
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
|
-
|
|
315
|
-
|
|
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
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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 =
|
|
380
|
-
|
|
381
|
-
|
|
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
|
-
|
|
452
|
-
|
|
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 =
|
|
563
|
+
farm_results = super().calc_farm(
|
|
461
564
|
mlist,
|
|
462
|
-
|
|
565
|
+
model_data,
|
|
463
566
|
parameters=calc_pars,
|
|
464
567
|
outputs=outputs,
|
|
465
568
|
**kwargs,
|
|
466
569
|
)
|
|
467
|
-
|
|
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
|
-
|
|
766
|
+
model_data = self.get_models_data(sel=sel, isel=isel)
|
|
609
767
|
if persist_mdata:
|
|
610
|
-
|
|
611
|
-
self.print("\nInput data:\n\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
|
|
624
|
-
sinds =
|
|
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
|
-
|
|
639
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
)
|
|
@@ -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
|
|