foxes 1.1.1__py3-none-any.whl → 1.2.1__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 +3 -1
- examples/abl_states/run.py +5 -5
- examples/dyn_wakes/run.py +2 -2
- examples/induction/run.py +5 -5
- examples/random_timeseries/run.py +13 -13
- examples/scan_row/run.py +12 -7
- examples/sector_management/run.py +11 -7
- examples/single_state/run.py +5 -5
- examples/tab_file/run.py +1 -1
- examples/timelines/run.py +1 -1
- examples/timeseries/run.py +5 -5
- examples/timeseries_slurm/run.py +5 -5
- examples/wind_rose/run.py +1 -1
- examples/yawed_wake/run.py +5 -5
- foxes/__init__.py +13 -2
- foxes/algorithms/downwind/downwind.py +21 -6
- foxes/algorithms/downwind/models/init_farm_data.py +5 -2
- foxes/algorithms/downwind/models/point_wakes_calc.py +0 -1
- foxes/algorithms/iterative/iterative.py +1 -1
- foxes/algorithms/sequential/sequential.py +5 -4
- foxes/config/__init__.py +1 -0
- foxes/config/config.py +134 -0
- foxes/constants.py +15 -6
- foxes/core/algorithm.py +46 -30
- foxes/core/axial_induction_model.py +18 -0
- foxes/core/data.py +2 -1
- foxes/core/engine.py +43 -49
- foxes/core/farm_controller.py +22 -3
- foxes/core/farm_data_model.py +6 -2
- foxes/core/ground_model.py +19 -0
- foxes/core/model.py +2 -1
- foxes/core/partial_wakes_model.py +9 -21
- foxes/core/point_data_model.py +22 -2
- foxes/core/rotor_model.py +9 -21
- foxes/core/states.py +2 -17
- foxes/core/turbine_model.py +2 -18
- foxes/core/turbine_type.py +2 -18
- foxes/core/vertical_profile.py +8 -20
- foxes/core/wake_frame.py +9 -25
- foxes/core/wake_model.py +24 -20
- foxes/core/wake_superposition.py +19 -0
- foxes/data/__init__.py +1 -1
- foxes/data/static_data.py +0 -7
- foxes/engines/dask.py +4 -3
- foxes/engines/single.py +1 -1
- foxes/input/__init__.py +1 -1
- foxes/input/farm_layout/from_csv.py +3 -1
- foxes/input/farm_layout/from_file.py +10 -10
- foxes/input/farm_layout/from_json.py +4 -3
- foxes/input/farm_layout/grid.py +3 -3
- foxes/input/states/__init__.py +1 -1
- foxes/input/states/create/random_abl_states.py +5 -3
- foxes/input/states/field_data_nc.py +36 -15
- foxes/input/states/multi_height.py +26 -15
- foxes/input/states/one_point_flow.py +6 -5
- foxes/input/states/{scan_ws.py → scan.py} +42 -52
- foxes/input/states/single.py +15 -6
- foxes/input/states/slice_data_nc.py +18 -12
- foxes/input/states/states_table.py +17 -10
- foxes/input/yaml/__init__.py +3 -0
- foxes/input/yaml/dict.py +381 -0
- foxes/input/yaml/windio/__init__.py +4 -0
- foxes/input/{windio → yaml/windio}/get_states.py +7 -7
- foxes/input/{windio → yaml/windio}/read_attributes.py +61 -40
- foxes/input/{windio → yaml/windio}/read_farm.py +34 -43
- foxes/input/{windio → yaml/windio}/read_fields.py +11 -10
- foxes/input/yaml/windio/read_outputs.py +147 -0
- foxes/input/yaml/windio/windio.py +269 -0
- foxes/input/yaml/yaml.py +103 -0
- foxes/models/partial_wakes/axiwake.py +7 -6
- foxes/models/partial_wakes/centre.py +3 -2
- foxes/models/partial_wakes/segregated.py +5 -2
- foxes/models/point_models/set_uniform_data.py +5 -3
- foxes/models/rotor_models/centre.py +2 -2
- foxes/models/rotor_models/grid.py +5 -5
- foxes/models/rotor_models/levels.py +6 -6
- foxes/models/turbine_models/kTI_model.py +3 -1
- foxes/models/turbine_models/lookup_table.py +7 -4
- foxes/models/turbine_models/power_mask.py +14 -8
- foxes/models/turbine_models/sector_management.py +4 -2
- foxes/models/turbine_models/set_farm_vars.py +53 -23
- foxes/models/turbine_models/table_factors.py +8 -7
- foxes/models/turbine_models/yaw2yawm.py +0 -1
- foxes/models/turbine_models/yawm2yaw.py +0 -1
- foxes/models/turbine_types/CpCt_file.py +6 -3
- foxes/models/turbine_types/CpCt_from_two.py +6 -3
- foxes/models/turbine_types/PCt_file.py +7 -6
- foxes/models/turbine_types/PCt_from_two.py +11 -2
- foxes/models/turbine_types/TBL_file.py +3 -4
- foxes/models/turbine_types/wsrho2PCt_from_two.py +19 -11
- foxes/models/turbine_types/wsti2PCt_from_two.py +19 -11
- foxes/models/vertical_profiles/abl_log_neutral_ws.py +1 -1
- foxes/models/vertical_profiles/abl_log_stable_ws.py +1 -1
- foxes/models/vertical_profiles/abl_log_unstable_ws.py +1 -1
- foxes/models/vertical_profiles/abl_log_ws.py +1 -1
- foxes/models/wake_frames/dynamic_wakes.py +17 -9
- foxes/models/wake_frames/farm_order.py +4 -3
- foxes/models/wake_frames/rotor_wd.py +3 -1
- foxes/models/wake_frames/seq_dynamic_wakes.py +14 -7
- foxes/models/wake_frames/streamlines.py +9 -6
- foxes/models/wake_frames/timelines.py +21 -14
- foxes/models/wake_frames/yawed_wakes.py +3 -1
- foxes/models/wake_models/induction/vortex_sheet.py +0 -1
- foxes/models/wake_models/ti/crespo_hernandez.py +2 -1
- foxes/models/wake_models/wind/bastankhah14.py +3 -2
- foxes/models/wake_models/wind/bastankhah16.py +2 -1
- foxes/models/wake_models/wind/turbopark.py +9 -7
- foxes/models/wake_superpositions/ws_product.py +0 -1
- foxes/output/__init__.py +2 -1
- foxes/output/calc_points.py +7 -4
- foxes/output/farm_layout.py +30 -18
- foxes/output/farm_results_eval.py +61 -38
- foxes/output/grids.py +8 -7
- foxes/output/output.py +9 -20
- foxes/output/plt.py +19 -0
- foxes/output/results_writer.py +10 -11
- foxes/output/rose_plot.py +448 -224
- foxes/output/rotor_point_plots.py +7 -3
- foxes/output/slice_data.py +1 -1
- foxes/output/state_turbine_map.py +5 -1
- foxes/output/state_turbine_table.py +7 -3
- foxes/output/turbine_type_curves.py +7 -2
- foxes/utils/__init__.py +1 -2
- foxes/utils/dict.py +107 -3
- foxes/utils/geopandas_utils.py +3 -2
- foxes/utils/subclasses.py +69 -0
- {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/METADATA +18 -18
- {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/RECORD +145 -145
- {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/WHEEL +1 -1
- foxes-1.2.1.dist-info/entry_points.txt +3 -0
- tests/0_consistency/iterative/test_iterative.py +65 -67
- tests/0_consistency/partial_wakes/test_partial_wakes.py +58 -61
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +56 -53
- tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +41 -41
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +34 -34
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +57 -52
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +58 -54
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +80 -76
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +80 -76
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +58 -51
- tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +101 -103
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +67 -64
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +58 -54
- examples/windio/run.py +0 -29
- foxes/data/states/windio_timeseries_5000.nc +0 -0
- foxes/data/windio/DTU_10MW_turbine.yaml +0 -10
- foxes/data/windio/__init__.py +0 -0
- foxes/data/windio/windio_5turbines_timeseries.yaml +0 -79
- foxes/input/windio/__init__.py +0 -11
- foxes/input/windio/read_outputs.py +0 -172
- foxes/input/windio/runner.py +0 -183
- foxes/input/windio/windio.py +0 -193
- foxes/utils/windrose_plot.py +0 -152
- {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/LICENSE +0 -0
- {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/top_level.txt +0 -0
|
@@ -4,6 +4,7 @@ from cycler import cycler
|
|
|
4
4
|
import matplotlib.pyplot as plt
|
|
5
5
|
|
|
6
6
|
from .output import Output
|
|
7
|
+
from foxes.config import config
|
|
7
8
|
import foxes.variables as FV
|
|
8
9
|
import foxes.constants as FC
|
|
9
10
|
|
|
@@ -63,7 +64,12 @@ class FarmResultsEval(Output):
|
|
|
63
64
|
fields = []
|
|
64
65
|
for v in vars:
|
|
65
66
|
if isinstance(v, str):
|
|
66
|
-
|
|
67
|
+
vdata = self.results[v].to_numpy()
|
|
68
|
+
nns = np.sum(np.isnan(vdata))
|
|
69
|
+
assert (
|
|
70
|
+
nns == 0
|
|
71
|
+
), f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
72
|
+
fields.append(vdata)
|
|
67
73
|
else:
|
|
68
74
|
fields.append(v)
|
|
69
75
|
if nas is None:
|
|
@@ -98,7 +104,7 @@ class FarmResultsEval(Output):
|
|
|
98
104
|
vars_op: dict
|
|
99
105
|
The operation per variable. Key: str, the variable
|
|
100
106
|
name. Value: str, the operation, choices
|
|
101
|
-
are:
|
|
107
|
+
are: weights, mean_no_weights, sum, min, max.
|
|
102
108
|
|
|
103
109
|
Returns
|
|
104
110
|
-------
|
|
@@ -110,23 +116,27 @@ class FarmResultsEval(Output):
|
|
|
110
116
|
|
|
111
117
|
rdata = {}
|
|
112
118
|
for v, op in vars_op.items():
|
|
113
|
-
|
|
114
|
-
|
|
119
|
+
vdata = self.results[v].to_numpy()
|
|
120
|
+
nns = np.sum(np.isnan(vdata))
|
|
121
|
+
assert (
|
|
122
|
+
nns == 0
|
|
123
|
+
), f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
124
|
+
|
|
125
|
+
if op == "weights":
|
|
126
|
+
rdata[v] = self.weinsum("t", vdata)
|
|
127
|
+
elif op == "mean_no_weights":
|
|
128
|
+
rdata[v] = np.mean(vdata, axis=0)
|
|
115
129
|
elif op == "sum":
|
|
116
|
-
vdata = self.results[v].to_numpy()
|
|
117
130
|
rdata[v] = np.sum(vdata, axis=0)
|
|
118
131
|
elif op == "min":
|
|
119
|
-
vdata = self.results[v].to_numpy()
|
|
120
132
|
rdata[v] = np.min(vdata, axis=0)
|
|
121
133
|
elif op == "max":
|
|
122
|
-
vdata = self.results[v].to_numpy()
|
|
123
134
|
rdata[v] = np.max(vdata, axis=0)
|
|
124
135
|
elif op == "std":
|
|
125
|
-
vdata = self.results[v].to_numpy()
|
|
126
136
|
rdata[v] = np.std(vdata, axis=0)
|
|
127
137
|
else:
|
|
128
138
|
raise KeyError(
|
|
129
|
-
f"Unknown operation '{op}' for variable '{v}'. Please choose:
|
|
139
|
+
f"Unknown operation '{op}' for variable '{v}'. Please choose: weights, mean_no_weights, sum, min, max"
|
|
130
140
|
)
|
|
131
141
|
|
|
132
142
|
data = pd.DataFrame(index=range(n_turbines), data=rdata)
|
|
@@ -143,7 +153,7 @@ class FarmResultsEval(Output):
|
|
|
143
153
|
vars_op: dict
|
|
144
154
|
The operation per variable. Key: str, the variable
|
|
145
155
|
name. Value: str, the operation, choices
|
|
146
|
-
are:
|
|
156
|
+
are: weights, mean_no_weights, sum, min, max.
|
|
147
157
|
|
|
148
158
|
Returns
|
|
149
159
|
-------
|
|
@@ -155,20 +165,25 @@ class FarmResultsEval(Output):
|
|
|
155
165
|
|
|
156
166
|
rdata = {}
|
|
157
167
|
for v, op in vars_op.items():
|
|
158
|
-
|
|
159
|
-
|
|
168
|
+
vdata = self.results[v].to_numpy()
|
|
169
|
+
nns = np.sum(np.isnan(vdata))
|
|
170
|
+
assert (
|
|
171
|
+
nns == 0
|
|
172
|
+
), f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
173
|
+
|
|
174
|
+
if op == "weights":
|
|
175
|
+
rdata[v] = self.weinsum("s", vdata)
|
|
176
|
+
elif op == "mean_no_weights":
|
|
177
|
+
rdata[v] = np.mean(vdata, axis=1)
|
|
160
178
|
elif op == "sum":
|
|
161
|
-
vdata = self.results[v].to_numpy()
|
|
162
179
|
rdata[v] = np.sum(vdata, axis=1)
|
|
163
180
|
elif op == "min":
|
|
164
|
-
vdata = self.results[v].to_numpy()
|
|
165
181
|
rdata[v] = np.min(vdata, axis=1)
|
|
166
182
|
elif op == "max":
|
|
167
|
-
vdata = self.results[v].to_numpy()
|
|
168
183
|
rdata[v] = np.max(vdata, axis=1)
|
|
169
184
|
else:
|
|
170
185
|
raise KeyError(
|
|
171
|
-
f"Unknown operation '{op}' for variable '{v}'. Please choose:
|
|
186
|
+
f"Unknown operation '{op}' for variable '{v}'. Please choose: weights, mean_no_weights, sum, min, max"
|
|
172
187
|
)
|
|
173
188
|
|
|
174
189
|
data = pd.DataFrame(index=states, data=rdata)
|
|
@@ -204,29 +219,32 @@ class FarmResultsEval(Output):
|
|
|
204
219
|
rdata = {}
|
|
205
220
|
for v, op in turbines_op.items():
|
|
206
221
|
vdata = sdata[v].to_numpy()
|
|
207
|
-
|
|
208
|
-
|
|
222
|
+
nns = np.sum(np.isnan(vdata))
|
|
223
|
+
assert (
|
|
224
|
+
nns == 0
|
|
225
|
+
), f"Found {nns} nan values for variable '{v}' of shape {vdata.shape}"
|
|
226
|
+
|
|
227
|
+
if op == "weights":
|
|
228
|
+
if states_op[v] == "weights":
|
|
209
229
|
rdata[v] = self.weinsum("", v)
|
|
210
230
|
else:
|
|
211
|
-
vdata = sdata[v].to_numpy()
|
|
212
231
|
rdata[v] = self.weinsum("", vdata[None, :])
|
|
232
|
+
elif op == "mean_no_weights":
|
|
233
|
+
rdata[v] = np.sum(vdata)
|
|
213
234
|
elif op == "sum":
|
|
214
|
-
vdata = sdata[v].to_numpy()
|
|
215
235
|
rdata[v] = np.sum(vdata)
|
|
216
236
|
elif op == "min":
|
|
217
|
-
vdata = sdata[v].to_numpy()
|
|
218
237
|
rdata[v] = np.min(vdata)
|
|
219
238
|
elif op == "max":
|
|
220
|
-
vdata = sdata[v].to_numpy()
|
|
221
239
|
rdata[v] = np.max(vdata)
|
|
222
240
|
else:
|
|
223
241
|
raise KeyError(
|
|
224
|
-
f"Unknown operation '{op}' for variable '{v}'. Please choose: sum, mean, min, max"
|
|
242
|
+
f"Unknown operation '{op}' for variable '{v}'. Please choose: sum, mean, min, max, weights"
|
|
225
243
|
)
|
|
226
244
|
|
|
227
245
|
return rdata
|
|
228
246
|
|
|
229
|
-
def calc_states_mean(self, vars):
|
|
247
|
+
def calc_states_mean(self, vars, use_weights=True):
|
|
230
248
|
"""
|
|
231
249
|
Calculates the mean wrt states.
|
|
232
250
|
|
|
@@ -234,6 +252,8 @@ class FarmResultsEval(Output):
|
|
|
234
252
|
----------
|
|
235
253
|
vars: list of str
|
|
236
254
|
The variables
|
|
255
|
+
use_weights: bool
|
|
256
|
+
Flag for using states weights for the mean
|
|
237
257
|
|
|
238
258
|
Returns
|
|
239
259
|
-------
|
|
@@ -241,9 +261,10 @@ class FarmResultsEval(Output):
|
|
|
241
261
|
The results per turbine
|
|
242
262
|
|
|
243
263
|
"""
|
|
264
|
+
r = "weights" if use_weights else "mean_no_weights"
|
|
244
265
|
if isinstance(vars, str):
|
|
245
|
-
return self.reduce_states({vars:
|
|
246
|
-
return self.reduce_states({v:
|
|
266
|
+
return self.reduce_states({vars: r})
|
|
267
|
+
return self.reduce_states({v: r for v in vars})
|
|
247
268
|
|
|
248
269
|
def calc_states_sum(self, vars):
|
|
249
270
|
"""
|
|
@@ -290,7 +311,7 @@ class FarmResultsEval(Output):
|
|
|
290
311
|
The results per state
|
|
291
312
|
|
|
292
313
|
"""
|
|
293
|
-
return self.reduce_turbines({v: "
|
|
314
|
+
return self.reduce_turbines({v: "mean_no_weights" for v in vars})
|
|
294
315
|
|
|
295
316
|
def calc_turbine_sum(self, vars):
|
|
296
317
|
"""
|
|
@@ -324,7 +345,7 @@ class FarmResultsEval(Output):
|
|
|
324
345
|
The fully contracted results
|
|
325
346
|
|
|
326
347
|
"""
|
|
327
|
-
op = {v: "
|
|
348
|
+
op = {v: "weights" for v in vars}
|
|
328
349
|
return self.reduce_all(states_op=op, turbines_op=op)
|
|
329
350
|
|
|
330
351
|
def calc_farm_sum(self, vars):
|
|
@@ -361,7 +382,7 @@ class FarmResultsEval(Output):
|
|
|
361
382
|
|
|
362
383
|
"""
|
|
363
384
|
v = FV.P if not ambient else FV.AMB_P
|
|
364
|
-
cdata = self.reduce_all(states_op={v: "
|
|
385
|
+
cdata = self.reduce_all(states_op={v: "weights"}, turbines_op={v: "sum"})
|
|
365
386
|
return cdata[v]
|
|
366
387
|
|
|
367
388
|
def calc_turbine_yield(
|
|
@@ -409,7 +430,7 @@ class FarmResultsEval(Output):
|
|
|
409
430
|
if algo is not None and P_unit_W is None:
|
|
410
431
|
P_unit_W = np.array(
|
|
411
432
|
[FC.P_UNITS[t.P_unit] for t in algo.farm_controller.turbine_types],
|
|
412
|
-
dtype=
|
|
433
|
+
dtype=config.dtype_double,
|
|
413
434
|
)[:, None]
|
|
414
435
|
elif algo is None and P_unit_W is not None:
|
|
415
436
|
pass
|
|
@@ -472,10 +493,10 @@ class FarmResultsEval(Output):
|
|
|
472
493
|
if algo is not None and P_nom is None:
|
|
473
494
|
P_nom = np.array(
|
|
474
495
|
[t.P_nominal for t in algo.farm_controller.turbine_types],
|
|
475
|
-
dtype=
|
|
496
|
+
dtype=config.dtype_double,
|
|
476
497
|
)
|
|
477
498
|
elif algo is None and P_nom is not None:
|
|
478
|
-
P_nom = np.array(P_nom, dtype=
|
|
499
|
+
P_nom = np.array(P_nom, dtype=config.dtype_double)
|
|
479
500
|
else:
|
|
480
501
|
raise KeyError("Expecting either 'algo' or 'P_nom'")
|
|
481
502
|
|
|
@@ -535,10 +556,12 @@ class FarmResultsEval(Output):
|
|
|
535
556
|
The verbosity level, 0 = silent
|
|
536
557
|
|
|
537
558
|
"""
|
|
538
|
-
P = self.results[FV.P]
|
|
539
|
-
P0 = self.results[FV.AMB_P]
|
|
540
|
-
|
|
541
|
-
|
|
559
|
+
P = self.results[FV.P].to_numpy()
|
|
560
|
+
P0 = np.maximum(self.results[FV.AMB_P].to_numpy(), 1e-12)
|
|
561
|
+
eff = np.minimum(P / P0, 1)
|
|
562
|
+
eff[P < 1e-10] = 0
|
|
563
|
+
self.results[FV.EFF] = (self.results[FV.AMB_P].dims, eff)
|
|
564
|
+
if verbosity > 0:
|
|
542
565
|
print("Efficiency added to farm results")
|
|
543
566
|
|
|
544
567
|
def calc_farm_efficiency(self):
|
|
@@ -552,8 +575,8 @@ class FarmResultsEval(Output):
|
|
|
552
575
|
|
|
553
576
|
"""
|
|
554
577
|
P = self.calc_mean_farm_power()
|
|
555
|
-
P0 = self.calc_mean_farm_power(ambient=True)
|
|
556
|
-
return P / P0
|
|
578
|
+
P0 = np.maximum(self.calc_mean_farm_power(ambient=True), 1e-14)
|
|
579
|
+
return np.minimum(P / P0, 1)
|
|
557
580
|
|
|
558
581
|
def gen_stdata(
|
|
559
582
|
self,
|
foxes/output/grids.py
CHANGED
|
@@ -3,6 +3,7 @@ import pandas as pd
|
|
|
3
3
|
from xarray import Dataset
|
|
4
4
|
|
|
5
5
|
from foxes.utils import wd2uv, write_nc
|
|
6
|
+
from foxes.config import config
|
|
6
7
|
import foxes.variables as FV
|
|
7
8
|
import foxes.constants as FC
|
|
8
9
|
|
|
@@ -151,7 +152,7 @@ def get_grid_xy(
|
|
|
151
152
|
N_x, N_y = len(x_pos), len(y_pos)
|
|
152
153
|
n_pts = len(x_pos) * len(y_pos)
|
|
153
154
|
z_pos = 0.5 * (z_min + z_max)
|
|
154
|
-
g_pts = np.zeros((n_states, N_x, N_y, 3), dtype=
|
|
155
|
+
g_pts = np.zeros((n_states, N_x, N_y, 3), dtype=config.dtype_double)
|
|
155
156
|
g_pts[:, :, :, 0] = x_pos[None, :, None]
|
|
156
157
|
g_pts[:, :, :, 1] = y_pos[None, None, :]
|
|
157
158
|
g_pts[:, :, :, 2] = z_pos
|
|
@@ -248,7 +249,7 @@ def get_grid_xz(
|
|
|
248
249
|
n_y = np.cross(n_z, n_x)
|
|
249
250
|
|
|
250
251
|
# project to axes:
|
|
251
|
-
xyz = np.zeros((n_states, n_turbines, 3), dtype=
|
|
252
|
+
xyz = np.zeros((n_states, n_turbines, 3), dtype=config.dtype_double)
|
|
252
253
|
xyz[:, :, 0] = farm_results[FV.X]
|
|
253
254
|
xyz[:, :, 1] = farm_results[FV.Y]
|
|
254
255
|
xyz[:, :, 2] = farm_results[FV.H]
|
|
@@ -297,7 +298,7 @@ def get_grid_xz(
|
|
|
297
298
|
N_x, N_z = len(x_pos), len(z_pos)
|
|
298
299
|
n_pts = len(x_pos) * len(z_pos)
|
|
299
300
|
y_pos = 0.5 * (y_min + y_max)
|
|
300
|
-
g_pts = np.zeros((n_states, N_x, N_z, 3), dtype=
|
|
301
|
+
g_pts = np.zeros((n_states, N_x, N_z, 3), dtype=config.dtype_double)
|
|
301
302
|
g_pts[:] += x_pos[None, :, None, None] * n_x[None, None, None, :]
|
|
302
303
|
g_pts[:] += y_pos * n_y[None, None, None, :]
|
|
303
304
|
g_pts[:] += z_pos[None, None, :, None] * n_z[None, None, None, :]
|
|
@@ -394,7 +395,7 @@ def get_grid_yz(
|
|
|
394
395
|
n_y = np.cross(n_z, n_x)
|
|
395
396
|
|
|
396
397
|
# project to axes:
|
|
397
|
-
xyz = np.zeros((n_states, n_turbines, 3), dtype=
|
|
398
|
+
xyz = np.zeros((n_states, n_turbines, 3), dtype=config.dtype_double)
|
|
398
399
|
xyz[:, :, 0] = farm_results[FV.X]
|
|
399
400
|
xyz[:, :, 1] = farm_results[FV.Y]
|
|
400
401
|
xyz[:, :, 2] = farm_results[FV.H]
|
|
@@ -443,7 +444,7 @@ def get_grid_yz(
|
|
|
443
444
|
N_y, N_z = len(y_pos), len(z_pos)
|
|
444
445
|
n_pts = len(y_pos) * len(z_pos)
|
|
445
446
|
x_pos = 0.5 * (x_min + x_max)
|
|
446
|
-
g_pts = np.zeros((n_states, N_y, N_z, 3), dtype=
|
|
447
|
+
g_pts = np.zeros((n_states, N_y, N_z, 3), dtype=config.dtype_double)
|
|
447
448
|
g_pts[:] += x_pos * n_x[None, None, None, :]
|
|
448
449
|
g_pts[:] += y_pos[None, :, None, None] * n_y[None, None, None, :]
|
|
449
450
|
g_pts[:] += z_pos[None, None, :, None] * n_z[None, None, None, :]
|
|
@@ -491,7 +492,7 @@ def np2np_p(data, a_pos, b_pos):
|
|
|
491
492
|
n_a = len(a_pos)
|
|
492
493
|
n_b = len(b_pos)
|
|
493
494
|
n_v = len(data)
|
|
494
|
-
out = np.zeros((n_a, n_b, n_v), dtype=
|
|
495
|
+
out = np.zeros((n_a, n_b, n_v), dtype=config.dtype_double)
|
|
495
496
|
for vi, (v, d) in enumerate(data.items()):
|
|
496
497
|
out[:, :, vi] = d.reshape(n_a, n_b)
|
|
497
498
|
return out
|
|
@@ -526,7 +527,7 @@ def np2np_sp(data, states, a_pos, b_pos):
|
|
|
526
527
|
n_a = len(a_pos)
|
|
527
528
|
n_b = len(b_pos)
|
|
528
529
|
n_v = len(data)
|
|
529
|
-
out = np.zeros((n_s, n_a, n_b, n_v), dtype=
|
|
530
|
+
out = np.zeros((n_s, n_a, n_b, n_v), dtype=config.dtype_double)
|
|
530
531
|
for vi, (v, d) in enumerate(data.items()):
|
|
531
532
|
out[:, :, :, vi] = d.reshape(n_s, n_a, n_b)
|
|
532
533
|
return out
|
foxes/output/output.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
|
-
from foxes.
|
|
3
|
+
from foxes.config import config, get_path
|
|
4
|
+
from foxes.utils import PandasFileHelper, new_instance, all_subclasses
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class Output:
|
|
@@ -33,9 +34,13 @@ class Output:
|
|
|
33
34
|
Modifies file names by f(fname)
|
|
34
35
|
|
|
35
36
|
"""
|
|
36
|
-
self.out_dir =
|
|
37
|
+
self.out_dir = get_path(out_dir) if out_dir is not None else config.out_dir
|
|
37
38
|
self.out_fname_fun = out_fname_fun
|
|
38
39
|
|
|
40
|
+
if not self.out_dir.is_dir():
|
|
41
|
+
print(f"{type(self).__name__}: Creating output dir {self.out_dir}")
|
|
42
|
+
self.out_dir.mkdir(parents=True)
|
|
43
|
+
|
|
39
44
|
def get_fpath(self, fname):
|
|
40
45
|
"""
|
|
41
46
|
Gets the total file path
|
|
@@ -54,7 +59,7 @@ class Output:
|
|
|
54
59
|
fnm = Path(fname)
|
|
55
60
|
if self.out_fname_fun is not None:
|
|
56
61
|
fnm = self.out_fname_fun(fnm)
|
|
57
|
-
return self.out_dir / fnm if self.out_dir is not None else fnm
|
|
62
|
+
return self.out_dir / fnm if self.out_dir is not None else get_path(fnm)
|
|
58
63
|
|
|
59
64
|
def write(self, file_name, data, format_col2var={}, format_dict={}, **kwargs):
|
|
60
65
|
"""
|
|
@@ -111,20 +116,4 @@ class Output:
|
|
|
111
116
|
Additional parameters for the constructor
|
|
112
117
|
|
|
113
118
|
"""
|
|
114
|
-
|
|
115
|
-
if output_type is None:
|
|
116
|
-
return None
|
|
117
|
-
|
|
118
|
-
allc = all_subclasses(cls)
|
|
119
|
-
found = output_type in [scls.__name__ for scls in allc]
|
|
120
|
-
|
|
121
|
-
if found:
|
|
122
|
-
for scls in allc:
|
|
123
|
-
if scls.__name__ == output_type:
|
|
124
|
-
return scls(*args, **kwargs)
|
|
125
|
-
|
|
126
|
-
else:
|
|
127
|
-
estr = "Output type '{}' is not defined, available types are \n {}".format(
|
|
128
|
-
output_type, sorted([i.__name__ for i in allc])
|
|
129
|
-
)
|
|
130
|
-
raise KeyError(estr)
|
|
119
|
+
return new_instance(cls, output_type, *args, **kwargs)
|
foxes/output/plt.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from matplotlib import pyplot
|
|
2
|
+
|
|
3
|
+
from .output import Output
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class plt(Output):
|
|
7
|
+
"""
|
|
8
|
+
Class that runs plt commands
|
|
9
|
+
|
|
10
|
+
:group: output
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __getattr__(self, name):
|
|
15
|
+
return getattr(pyplot, name)
|
|
16
|
+
|
|
17
|
+
def savefig(self, fname, *args, **kwargs):
|
|
18
|
+
fpath = super().get_fpath(fname)
|
|
19
|
+
pyplot.savefig(fpath, *args, **kwargs)
|
foxes/output/results_writer.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
from xarray import Dataset
|
|
3
3
|
|
|
4
|
-
import foxes.constants as FC
|
|
5
4
|
from foxes.utils import write_nc
|
|
5
|
+
import foxes.constants as FC
|
|
6
6
|
|
|
7
7
|
from .output import Output
|
|
8
8
|
|
|
@@ -70,7 +70,7 @@ class ResultsWriter(Output):
|
|
|
70
70
|
|
|
71
71
|
def write_csv(
|
|
72
72
|
self,
|
|
73
|
-
|
|
73
|
+
file_name,
|
|
74
74
|
variables=None,
|
|
75
75
|
turbine_names=False,
|
|
76
76
|
state_turbine_table=False,
|
|
@@ -82,8 +82,8 @@ class ResultsWriter(Output):
|
|
|
82
82
|
|
|
83
83
|
Parameters
|
|
84
84
|
----------
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
file_name: str
|
|
86
|
+
Name of the csv file
|
|
87
87
|
variables: dict or list of str, optional
|
|
88
88
|
The variables to be written. If a dict, then
|
|
89
89
|
the keys are the foxes variables and the values
|
|
@@ -101,7 +101,7 @@ class ResultsWriter(Output):
|
|
|
101
101
|
|
|
102
102
|
"""
|
|
103
103
|
if verbosity:
|
|
104
|
-
print(f"ResultsWriter: Writing file '{
|
|
104
|
+
print(f"ResultsWriter: Writing file '{file_name}'")
|
|
105
105
|
|
|
106
106
|
data, variables = self._get_data_vars(variables)
|
|
107
107
|
data.reset_index(inplace=True)
|
|
@@ -133,12 +133,11 @@ class ResultsWriter(Output):
|
|
|
133
133
|
else:
|
|
134
134
|
data.set_index([FC.STATE, tix], inplace=True)
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
super().write(fpath, data, format_col2var=fc2v, **kwargs)
|
|
136
|
+
super().write(file_name, data, format_col2var=fc2v, **kwargs)
|
|
138
137
|
|
|
139
138
|
def write_nc(
|
|
140
139
|
self,
|
|
141
|
-
|
|
140
|
+
file_name,
|
|
142
141
|
variables=None,
|
|
143
142
|
turbine_names=False,
|
|
144
143
|
verbosity=1,
|
|
@@ -149,8 +148,8 @@ class ResultsWriter(Output):
|
|
|
149
148
|
|
|
150
149
|
Parameters
|
|
151
150
|
----------
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
file_name: str
|
|
152
|
+
The nc file name
|
|
154
153
|
variables: dict or list of str, optional
|
|
155
154
|
The variables to be written. If a dict, then
|
|
156
155
|
the keys are the foxes variables and the values
|
|
@@ -185,5 +184,5 @@ class ResultsWriter(Output):
|
|
|
185
184
|
},
|
|
186
185
|
)
|
|
187
186
|
|
|
188
|
-
fpath = self.get_fpath(
|
|
187
|
+
fpath = self.get_fpath(file_name)
|
|
189
188
|
write_nc(ds, fpath, verbosity=verbosity, **kwargs)
|