foxes 0.8.2__py3-none-any.whl → 1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of foxes might be problematic. Click here for more details.
- 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 +23 -13
- foxes/variables.py +37 -0
- {foxes-0.8.2.dist-info → foxes-1.0.dist-info}/METADATA +71 -33
- foxes-1.0.dist-info/RECORD +307 -0
- {foxes-0.8.2.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/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.0.dist-info}/LICENSE +0 -0
foxes/output/grids.py
CHANGED
|
@@ -12,7 +12,6 @@ def calc_point_results(
|
|
|
12
12
|
g_pts,
|
|
13
13
|
farm_results=None,
|
|
14
14
|
seq_iter=None,
|
|
15
|
-
runner=None,
|
|
16
15
|
verbosity=0,
|
|
17
16
|
**kwargs,
|
|
18
17
|
):
|
|
@@ -29,8 +28,6 @@ def calc_point_results(
|
|
|
29
28
|
The farm results
|
|
30
29
|
seq_iter: foxes.algorithms.sequential.SequentialIter, optional
|
|
31
30
|
The sequential itarator
|
|
32
|
-
runner: foxes.utils.runners.Runner, optional
|
|
33
|
-
The runner
|
|
34
31
|
verbosity: int
|
|
35
32
|
The verbosity level, 0 = silent
|
|
36
33
|
kwargs: dict, optional
|
|
@@ -41,11 +38,7 @@ def calc_point_results(
|
|
|
41
38
|
if averb is not None:
|
|
42
39
|
algo.verbosity = verbosity
|
|
43
40
|
fres = farm_results if seq_iter is None else seq_iter.farm_results
|
|
44
|
-
|
|
45
|
-
point_results = algo.calc_points(fres, points=g_pts, **kwargs)
|
|
46
|
-
else:
|
|
47
|
-
kwargs["points"] = g_pts
|
|
48
|
-
point_results = runner.run(algo.calc_points, args=(fres,), kwargs=kwargs)
|
|
41
|
+
point_results = algo.calc_points(fres, points=g_pts, **kwargs)
|
|
49
42
|
if averb is not None:
|
|
50
43
|
algo.verbosity = averb
|
|
51
44
|
|
|
@@ -54,7 +47,8 @@ def calc_point_results(
|
|
|
54
47
|
|
|
55
48
|
def get_grid_xy(
|
|
56
49
|
farm_results,
|
|
57
|
-
resolution,
|
|
50
|
+
resolution=None,
|
|
51
|
+
n_img_points=None,
|
|
58
52
|
xmin=None,
|
|
59
53
|
ymin=None,
|
|
60
54
|
xmax=None,
|
|
@@ -62,6 +56,8 @@ def get_grid_xy(
|
|
|
62
56
|
z=None,
|
|
63
57
|
xspace=500.0,
|
|
64
58
|
yspace=500.0,
|
|
59
|
+
states_sel=None,
|
|
60
|
+
states_isel=None,
|
|
65
61
|
verbosity=0,
|
|
66
62
|
):
|
|
67
63
|
"""
|
|
@@ -74,6 +70,8 @@ def get_grid_xy(
|
|
|
74
70
|
dimensions (state, turbine)
|
|
75
71
|
resolution: float
|
|
76
72
|
The resolution in m
|
|
73
|
+
n_img_points: tuple of int, optional
|
|
74
|
+
The number of image points (n, m) in the two directions
|
|
77
75
|
xmin: float
|
|
78
76
|
The min x coordinate, or None for automatic
|
|
79
77
|
ymin: float
|
|
@@ -88,6 +86,10 @@ def get_grid_xy(
|
|
|
88
86
|
The extra space in x direction, before and after wind farm
|
|
89
87
|
yspace: float
|
|
90
88
|
The extra space in y direction, before and after wind farm
|
|
89
|
+
states_sel: list, optional
|
|
90
|
+
Reduce to selected states
|
|
91
|
+
states_isel: list, optional
|
|
92
|
+
Reduce to the selected states indices
|
|
91
93
|
verbosity: int, optional
|
|
92
94
|
The verbosity level
|
|
93
95
|
|
|
@@ -103,8 +105,11 @@ def get_grid_xy(
|
|
|
103
105
|
The grid points, shape: (n_states, n_pts, 3)
|
|
104
106
|
|
|
105
107
|
"""
|
|
106
|
-
|
|
107
108
|
# prepare:
|
|
109
|
+
if states_isel is not None:
|
|
110
|
+
farm_results = farm_results.isel({FC.STATE: states_isel})
|
|
111
|
+
if states_sel is not None:
|
|
112
|
+
farm_results = farm_results.sel({FC.STATE: states_sel})
|
|
108
113
|
n_states = farm_results[FV.H].shape[0]
|
|
109
114
|
|
|
110
115
|
# get base rectangle:
|
|
@@ -115,10 +120,22 @@ def get_grid_xy(
|
|
|
115
120
|
y_max = ymax if ymax is not None else farm_results[FV.Y].max().to_numpy() + yspace
|
|
116
121
|
z_max = z if z is not None else farm_results[FV.H].max().to_numpy()
|
|
117
122
|
|
|
123
|
+
# compute number of points:
|
|
124
|
+
if resolution is not None and n_img_points is None:
|
|
125
|
+
nx = int((x_max - x_min) / resolution + 0.5) + 1
|
|
126
|
+
ny = int((y_max - y_min) / resolution + 0.5) + 1
|
|
127
|
+
elif resolution is None and n_img_points is not None:
|
|
128
|
+
nx, ny = n_img_points
|
|
129
|
+
else:
|
|
130
|
+
raise ValueError(
|
|
131
|
+
f"Expecting either 'resolution' or 'n_img_points', got: resolution = {resolution}, n_img_points = {n_img_points}"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# compute points:
|
|
118
135
|
x_pos, x_res = np.linspace(
|
|
119
136
|
x_min,
|
|
120
137
|
x_max,
|
|
121
|
-
num=
|
|
138
|
+
num=nx,
|
|
122
139
|
endpoint=True,
|
|
123
140
|
retstep=True,
|
|
124
141
|
dtype=None,
|
|
@@ -126,7 +143,7 @@ def get_grid_xy(
|
|
|
126
143
|
y_pos, y_res = np.linspace(
|
|
127
144
|
y_min,
|
|
128
145
|
y_max,
|
|
129
|
-
num=
|
|
146
|
+
num=ny,
|
|
130
147
|
endpoint=True,
|
|
131
148
|
retstep=True,
|
|
132
149
|
dtype=None,
|
|
@@ -158,7 +175,8 @@ def get_grid_xy(
|
|
|
158
175
|
|
|
159
176
|
def get_grid_xz(
|
|
160
177
|
farm_results,
|
|
161
|
-
resolution,
|
|
178
|
+
resolution=None,
|
|
179
|
+
n_img_points=None,
|
|
162
180
|
x_direction=270,
|
|
163
181
|
xmin=None,
|
|
164
182
|
zmin=0.0,
|
|
@@ -167,6 +185,8 @@ def get_grid_xz(
|
|
|
167
185
|
y=None,
|
|
168
186
|
xspace=500.0,
|
|
169
187
|
zspace=500.0,
|
|
188
|
+
states_sel=None,
|
|
189
|
+
states_isel=None,
|
|
170
190
|
verbosity=0,
|
|
171
191
|
):
|
|
172
192
|
"""
|
|
@@ -177,8 +197,10 @@ def get_grid_xz(
|
|
|
177
197
|
farm_results: xarray.Dataset
|
|
178
198
|
The farm results. The calculated variables have
|
|
179
199
|
dimensions (state, turbine)
|
|
180
|
-
resolution: float
|
|
200
|
+
resolution: float, optional
|
|
181
201
|
The resolution in m
|
|
202
|
+
n_img_points: tuple of int, optional
|
|
203
|
+
The number of image points (n, m) in the two directions
|
|
182
204
|
x_direction: float
|
|
183
205
|
The direction of the x axis, 0 = north
|
|
184
206
|
xmin: float
|
|
@@ -195,6 +217,10 @@ def get_grid_xz(
|
|
|
195
217
|
The extra space in x direction, before and after wind farm
|
|
196
218
|
zspace: float
|
|
197
219
|
The extra space in z direction, below and above wind farm
|
|
220
|
+
states_sel: list, optional
|
|
221
|
+
Reduce to selected states
|
|
222
|
+
states_isel: list, optional
|
|
223
|
+
Reduce to the selected states indices
|
|
198
224
|
verbosity: int, optional
|
|
199
225
|
The verbosity level
|
|
200
226
|
|
|
@@ -212,6 +238,10 @@ def get_grid_xz(
|
|
|
212
238
|
"""
|
|
213
239
|
|
|
214
240
|
# prepare:
|
|
241
|
+
if states_isel is not None:
|
|
242
|
+
farm_results = farm_results.isel({FC.STATE: states_isel})
|
|
243
|
+
if states_sel is not None:
|
|
244
|
+
farm_results = farm_results.sel({FC.STATE: states_sel})
|
|
215
245
|
n_states, n_turbines = farm_results[FV.H].shape
|
|
216
246
|
n_x = np.append(wd2uv(x_direction), [0.0], axis=0)
|
|
217
247
|
n_z = np.array([0.0, 0.0, 1.0])
|
|
@@ -236,10 +266,22 @@ def get_grid_xz(
|
|
|
236
266
|
y_max = y if y is not None else np.max(yy)
|
|
237
267
|
del xx, yy, zz
|
|
238
268
|
|
|
269
|
+
# compute number of points:
|
|
270
|
+
if resolution is not None and n_img_points is None:
|
|
271
|
+
nx = int((x_max - x_min) / resolution + 0.5) + 1
|
|
272
|
+
nz = int((z_max - z_min) / resolution + 0.5) + 1
|
|
273
|
+
elif resolution is None and n_img_points is not None:
|
|
274
|
+
nx, nz = n_img_points
|
|
275
|
+
else:
|
|
276
|
+
raise ValueError(
|
|
277
|
+
f"Expecting either 'resolution' or 'n_img_points', got: resolution = {resolution}, n_img_points = {n_img_points}"
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
# compute points:
|
|
239
281
|
x_pos, x_res = np.linspace(
|
|
240
282
|
x_min,
|
|
241
283
|
x_max,
|
|
242
|
-
num=
|
|
284
|
+
num=nx,
|
|
243
285
|
endpoint=True,
|
|
244
286
|
retstep=True,
|
|
245
287
|
dtype=None,
|
|
@@ -247,7 +289,7 @@ def get_grid_xz(
|
|
|
247
289
|
z_pos, z_res = np.linspace(
|
|
248
290
|
z_min,
|
|
249
291
|
z_max,
|
|
250
|
-
num=
|
|
292
|
+
num=nz,
|
|
251
293
|
endpoint=True,
|
|
252
294
|
retstep=True,
|
|
253
295
|
dtype=None,
|
|
@@ -279,7 +321,8 @@ def get_grid_xz(
|
|
|
279
321
|
|
|
280
322
|
def get_grid_yz(
|
|
281
323
|
farm_results,
|
|
282
|
-
resolution,
|
|
324
|
+
resolution=None,
|
|
325
|
+
n_img_points=None,
|
|
283
326
|
x_direction=270,
|
|
284
327
|
ymin=None,
|
|
285
328
|
zmin=0.0,
|
|
@@ -288,6 +331,8 @@ def get_grid_yz(
|
|
|
288
331
|
x=None,
|
|
289
332
|
yspace=500.0,
|
|
290
333
|
zspace=500.0,
|
|
334
|
+
states_sel=None,
|
|
335
|
+
states_isel=None,
|
|
291
336
|
verbosity=0,
|
|
292
337
|
):
|
|
293
338
|
"""
|
|
@@ -298,8 +343,10 @@ def get_grid_yz(
|
|
|
298
343
|
farm_results: xarray.Dataset
|
|
299
344
|
The farm results. The calculated variables have
|
|
300
345
|
dimensions (state, turbine)
|
|
301
|
-
resolution: float
|
|
346
|
+
resolution: float, optional
|
|
302
347
|
The resolution in m
|
|
348
|
+
n_img_points: tuple of int, optional
|
|
349
|
+
The number of image points (n, m) in the two directions
|
|
303
350
|
x_direction: float
|
|
304
351
|
The direction of the x axis, 0 = north
|
|
305
352
|
ymin: float
|
|
@@ -316,6 +363,10 @@ def get_grid_yz(
|
|
|
316
363
|
The extra space in y direction, before and after wind farm
|
|
317
364
|
zspace: float
|
|
318
365
|
The extra space in z direction, below and above wind farm
|
|
366
|
+
states_sel: list, optional
|
|
367
|
+
Reduce to selected states
|
|
368
|
+
states_isel: list, optional
|
|
369
|
+
Reduce to the selected states indices
|
|
319
370
|
verbosity: int, optional
|
|
320
371
|
The verbosity level
|
|
321
372
|
|
|
@@ -333,6 +384,10 @@ def get_grid_yz(
|
|
|
333
384
|
"""
|
|
334
385
|
|
|
335
386
|
# prepare:
|
|
387
|
+
if states_isel is not None:
|
|
388
|
+
farm_results = farm_results.isel({FC.STATE: states_isel})
|
|
389
|
+
if states_sel is not None:
|
|
390
|
+
farm_results = farm_results.sel({FC.STATE: states_sel})
|
|
336
391
|
n_states, n_turbines = farm_results[FV.H].shape
|
|
337
392
|
n_x = np.append(wd2uv(x_direction), [0.0], axis=0)
|
|
338
393
|
n_z = np.array([0.0, 0.0, 1.0])
|
|
@@ -357,10 +412,22 @@ def get_grid_yz(
|
|
|
357
412
|
x_max = x if x is not None else np.max(xx)
|
|
358
413
|
del xx, yy, zz
|
|
359
414
|
|
|
415
|
+
# compute number of points:
|
|
416
|
+
if resolution is not None and n_img_points is None:
|
|
417
|
+
ny = int((y_max - y_min) / resolution + 0.5) + 1
|
|
418
|
+
nz = int((z_max - z_min) / resolution + 0.5) + 1
|
|
419
|
+
elif resolution is None and n_img_points is not None:
|
|
420
|
+
ny, nz = n_img_points
|
|
421
|
+
else:
|
|
422
|
+
raise ValueError(
|
|
423
|
+
f"Expecting either 'resolution' or 'n_img_points', got: resolution = {resolution}, n_img_points = {n_img_points}"
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
# compute points:
|
|
360
427
|
y_pos, y_res = np.linspace(
|
|
361
428
|
y_min,
|
|
362
429
|
y_max,
|
|
363
|
-
num=
|
|
430
|
+
num=ny,
|
|
364
431
|
endpoint=True,
|
|
365
432
|
retstep=True,
|
|
366
433
|
dtype=None,
|
|
@@ -368,7 +435,7 @@ def get_grid_yz(
|
|
|
368
435
|
z_pos, z_res = np.linspace(
|
|
369
436
|
z_min,
|
|
370
437
|
z_max,
|
|
371
|
-
num=
|
|
438
|
+
num=nz,
|
|
372
439
|
endpoint=True,
|
|
373
440
|
retstep=True,
|
|
374
441
|
dtype=None,
|
|
@@ -614,7 +681,10 @@ def np2xr_sp(data, states, a_pos, b_pos, c_pos, ori, label_map={}):
|
|
|
614
681
|
return Dataset(
|
|
615
682
|
coords={s: states, b: b_pos, a: a_pos},
|
|
616
683
|
data_vars={
|
|
617
|
-
v
|
|
684
|
+
label_map.get(v, v): (
|
|
685
|
+
(s, b, a),
|
|
686
|
+
np.swapaxes(d.reshape(n_s, n_a, n_b), 1, 2),
|
|
687
|
+
)
|
|
618
688
|
for v, d in data.items()
|
|
619
689
|
},
|
|
620
690
|
attrs={c: float(c_pos)},
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from copy import deepcopy
|
|
2
|
+
|
|
1
3
|
from foxes.algorithms.sequential import SequentialPlugin
|
|
2
4
|
|
|
3
|
-
from .flow_plots import FlowPlots2D
|
|
5
|
+
from ..flow_plots_2d.flow_plots import FlowPlots2D
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
@@ -12,16 +14,14 @@ class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
|
12
14
|
----------
|
|
13
15
|
orientation: str
|
|
14
16
|
The orientation, either "yx", "xz" or "yz"
|
|
15
|
-
runner: foxes.utils.runners.Runner
|
|
16
|
-
The runner
|
|
17
17
|
pars: dict
|
|
18
18
|
Additional parameters for plotting
|
|
19
19
|
|
|
20
|
-
:group: output.
|
|
20
|
+
:group: output.seq_plugins
|
|
21
21
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
def __init__(self, orientation,
|
|
24
|
+
def __init__(self, orientation, **pars):
|
|
25
25
|
"""
|
|
26
26
|
Constructor.
|
|
27
27
|
|
|
@@ -29,15 +29,12 @@ class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
|
29
29
|
----------
|
|
30
30
|
orientation: str
|
|
31
31
|
The orientation, either "yx", "xz" or "yz"
|
|
32
|
-
runner: foxes.utils.runners.Runner, optional
|
|
33
|
-
The runner
|
|
34
32
|
pars: dict, optional
|
|
35
33
|
Additional parameters for plotting
|
|
36
34
|
|
|
37
35
|
"""
|
|
38
36
|
super().__init__()
|
|
39
37
|
self.orientation = orientation
|
|
40
|
-
self.runner = runner
|
|
41
38
|
self.pars = pars
|
|
42
39
|
|
|
43
40
|
if "title" in self.pars and callable(self.pars["title"]):
|
|
@@ -74,28 +71,73 @@ class SeqFlowAnimationPlugin(SequentialPlugin):
|
|
|
74
71
|
"""
|
|
75
72
|
super().update(algo, fres, pres)
|
|
76
73
|
|
|
77
|
-
o = FlowPlots2D(algo, fres
|
|
74
|
+
o = FlowPlots2D(algo, fres)
|
|
78
75
|
|
|
79
76
|
if self._tfun is not None:
|
|
80
77
|
self.pars["title"] = self._tfun(algo.states.counter, algo.states.index()[0])
|
|
81
78
|
|
|
82
79
|
if self.orientation == "xy":
|
|
83
|
-
|
|
80
|
+
d = next(o.gen_states_fig_xy(**self.pars, precalc=True))
|
|
84
81
|
elif self.orientation == "xz":
|
|
85
|
-
|
|
82
|
+
d = next(o.gen_states_fig_xz(**self.pars, precalc=True))
|
|
86
83
|
elif self.orientation == "yz":
|
|
87
|
-
|
|
84
|
+
d = next(o.gen_states_fig_yz(**self.pars, precalc=True))
|
|
88
85
|
else:
|
|
89
86
|
raise KeyError(
|
|
90
87
|
f"Unkown orientation '{self.orientation}', choises: xy, xz, yz"
|
|
91
88
|
)
|
|
92
89
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
90
|
+
# minimize stored data:
|
|
91
|
+
od = [d[0], d[1], None]
|
|
92
|
+
if len(self._data) == 0:
|
|
93
|
+
od[2] = d[2]
|
|
94
|
+
of = (
|
|
95
|
+
fres
|
|
96
|
+
if ("rotor_color" in self.pars and self.pars["rotor_color"] is not None)
|
|
97
|
+
else None
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
self._data.append((of, od))
|
|
101
|
+
|
|
102
|
+
def gen_images(self, ax):
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
Parameters
|
|
106
|
+
----------
|
|
107
|
+
ax: matplotlib.Axis
|
|
108
|
+
The plotting axis
|
|
109
|
+
|
|
110
|
+
Yields
|
|
111
|
+
------
|
|
112
|
+
imgs: tuple
|
|
113
|
+
The (figure, artists) tuple
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
fig = ax.get_figure()
|
|
117
|
+
gdata = None
|
|
118
|
+
while len(self._data):
|
|
119
|
+
|
|
120
|
+
fres, d = self._data.pop(0)
|
|
121
|
+
|
|
122
|
+
if d[2] is not None:
|
|
123
|
+
gdata = d[2]
|
|
124
|
+
|
|
125
|
+
o = FlowPlots2D(self.algo, fres)
|
|
126
|
+
|
|
127
|
+
yield next(
|
|
128
|
+
o.gen_states_fig_xy(
|
|
129
|
+
**self.pars,
|
|
130
|
+
ax=ax,
|
|
131
|
+
fig=fig,
|
|
132
|
+
ret_im=True,
|
|
133
|
+
precalc=(d[0], d[1], gdata),
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
del o, fres, d
|
|
98
138
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
139
|
+
if (
|
|
140
|
+
self.pars.get("vmin", None) is not None
|
|
141
|
+
and self.pars.get("vmax", None) is not None
|
|
142
|
+
):
|
|
143
|
+
self.pars["add_bar"] = False
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
from foxes.algorithms.sequential import SequentialPlugin
|
|
2
|
+
from foxes.models.wake_frames.seq_dynamic_wakes import SeqDynamicWakes
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class SeqWakeDebugPlugin(SequentialPlugin):
|
|
6
|
+
"""
|
|
7
|
+
Plugin for creating wake debug plots in animations
|
|
8
|
+
|
|
9
|
+
Attributes
|
|
10
|
+
----------
|
|
11
|
+
show_p: bool
|
|
12
|
+
Flag for showing wake points
|
|
13
|
+
show_v: bool
|
|
14
|
+
Flag for showing wake vectors
|
|
15
|
+
vpars: dict
|
|
16
|
+
Additional parameters for vector lines
|
|
17
|
+
ppars: dict
|
|
18
|
+
Additional parameters for point scatter
|
|
19
|
+
|
|
20
|
+
:group: output.seq_plugins
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, show_p=True, show_v=True, vpars={}, **ppars):
|
|
25
|
+
"""
|
|
26
|
+
Constructor.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
show_p: bool
|
|
31
|
+
Flag for showing wake points
|
|
32
|
+
show_v: bool
|
|
33
|
+
Flag for showing wake vectors
|
|
34
|
+
vpars: dict
|
|
35
|
+
Additional parameters for vector lines
|
|
36
|
+
ppars: dict, optional
|
|
37
|
+
Additional parameters for point scatter
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
super().__init__()
|
|
41
|
+
self.show_p = show_p
|
|
42
|
+
self.show_v = show_v
|
|
43
|
+
|
|
44
|
+
self.vpars = dict(color="blue")
|
|
45
|
+
self.vpars.update(vpars)
|
|
46
|
+
|
|
47
|
+
self.ppars = dict(color="blue")
|
|
48
|
+
self.ppars.update(ppars)
|
|
49
|
+
|
|
50
|
+
def initialize(self, algo):
|
|
51
|
+
"""
|
|
52
|
+
Initialize data based on the intial iterator
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
algo: foxes.algorithms.sequential.Sequential
|
|
57
|
+
The current sequetial algorithm
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
super().initialize(algo)
|
|
61
|
+
self._data = []
|
|
62
|
+
|
|
63
|
+
def update(self, algo, fres, pres=None):
|
|
64
|
+
"""
|
|
65
|
+
Updates data based on current iteration
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
algo: foxes.algorithms.sequential.Sequential
|
|
70
|
+
The latest sequetial algorithm
|
|
71
|
+
fres: xarray.Dataset
|
|
72
|
+
The latest farm results
|
|
73
|
+
pres: xarray.Dataset, optional
|
|
74
|
+
The latest point results
|
|
75
|
+
|
|
76
|
+
"""
|
|
77
|
+
super().update(algo, fres, pres)
|
|
78
|
+
|
|
79
|
+
wframe = algo.wake_frame
|
|
80
|
+
if not isinstance(wframe, SeqDynamicWakes):
|
|
81
|
+
raise ValueError(
|
|
82
|
+
f"Wake frame not of type SeqDynamicWakes, got {type(algo.wake_frame).__name__}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
counter = algo.counter
|
|
86
|
+
N = counter + 1
|
|
87
|
+
dt = wframe._dt[counter] if counter < len(wframe._dt) else wframe._dt[-1]
|
|
88
|
+
|
|
89
|
+
self._data.append(
|
|
90
|
+
(
|
|
91
|
+
dt,
|
|
92
|
+
wframe._traces_p[:N].copy(),
|
|
93
|
+
wframe._traces_v[:N].copy(),
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def gen_images(self, ax):
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
Parameters
|
|
101
|
+
----------
|
|
102
|
+
ax: matplotlib.Axis
|
|
103
|
+
The plotting axis
|
|
104
|
+
|
|
105
|
+
Yields
|
|
106
|
+
------
|
|
107
|
+
imgs: tuple
|
|
108
|
+
The (figure, artists) tuple
|
|
109
|
+
|
|
110
|
+
"""
|
|
111
|
+
while len(self._data):
|
|
112
|
+
|
|
113
|
+
dt, pts, v = self._data.pop(0)
|
|
114
|
+
|
|
115
|
+
N = len(pts)
|
|
116
|
+
artists = []
|
|
117
|
+
if self.show_p:
|
|
118
|
+
artists += [
|
|
119
|
+
ax.scatter(
|
|
120
|
+
pts[:, downwind_index, 0],
|
|
121
|
+
pts[:, downwind_index, 1],
|
|
122
|
+
animated=True,
|
|
123
|
+
**self.ppars,
|
|
124
|
+
)
|
|
125
|
+
for downwind_index in range(self.algo.n_turbines)
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
if self.show_v:
|
|
129
|
+
for downwind_index in range(self.algo.n_turbines):
|
|
130
|
+
for i in range(N):
|
|
131
|
+
p = pts[i, downwind_index]
|
|
132
|
+
dxy = v[i, downwind_index] * dt
|
|
133
|
+
artists.append(
|
|
134
|
+
ax.arrow(
|
|
135
|
+
p[0],
|
|
136
|
+
p[1],
|
|
137
|
+
dxy[0],
|
|
138
|
+
dxy[1],
|
|
139
|
+
length_includes_head=True,
|
|
140
|
+
animated=True,
|
|
141
|
+
**self.vpars,
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
yield ax.get_figure(), artists
|