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
|
@@ -6,7 +6,7 @@ from foxes.core import Turbine, TurbineType
|
|
|
6
6
|
import foxes.variables as FV
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def read_turbine_types(wio_farm,
|
|
9
|
+
def read_turbine_types(wio_farm, mbook, ws_exp_P, ws_exp_ct, verbosity):
|
|
10
10
|
"""
|
|
11
11
|
Reads the turbine type from windio
|
|
12
12
|
|
|
@@ -14,8 +14,8 @@ def read_turbine_types(wio_farm, algo_dict, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
14
14
|
----------
|
|
15
15
|
wio_farm: dict
|
|
16
16
|
The windio farm data
|
|
17
|
-
|
|
18
|
-
The
|
|
17
|
+
mbook: foxes.models.ModelBook
|
|
18
|
+
The model book
|
|
19
19
|
ws_exp_P: int
|
|
20
20
|
The REWS exponent for power
|
|
21
21
|
ws_exp_ct: int
|
|
@@ -29,9 +29,14 @@ def read_turbine_types(wio_farm, algo_dict, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
29
29
|
Mapping from turbine type key to turbine
|
|
30
30
|
type name in the model book
|
|
31
31
|
|
|
32
|
-
:group: input.windio
|
|
32
|
+
:group: input.yaml.windio
|
|
33
33
|
|
|
34
34
|
"""
|
|
35
|
+
|
|
36
|
+
def _print(*args, level=1, **kwargs):
|
|
37
|
+
if verbosity >= level:
|
|
38
|
+
print(*args, **kwargs)
|
|
39
|
+
|
|
35
40
|
if "turbine_types" not in wio_farm:
|
|
36
41
|
wio_farm["turbine_types"] = {0: wio_farm["turbines"]}
|
|
37
42
|
|
|
@@ -39,29 +44,25 @@ def read_turbine_types(wio_farm, algo_dict, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
39
44
|
for k, wio_trbns in wio_farm["turbine_types"].items():
|
|
40
45
|
tname = wio_trbns.pop("name")
|
|
41
46
|
ttypes[k] = tname
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
print(" Contents:", [k for k in wio_trbns.keys()])
|
|
47
|
+
_print(" Reading turbine type", k, level=3)
|
|
48
|
+
_print(" Name:", tname, level=3)
|
|
49
|
+
_print(" Contents:", [k for k in wio_trbns.keys()], level=3)
|
|
46
50
|
|
|
47
51
|
# read performance:
|
|
48
52
|
performance = Dict(wio_trbns["performance"], name="performance")
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
print(" Contents:", [k for k in performance.keys()])
|
|
53
|
+
_print(" Reading performance", level=3)
|
|
54
|
+
_print(" Contents:", [k for k in performance.keys()], level=3)
|
|
52
55
|
|
|
53
56
|
# P, ct data:
|
|
54
57
|
if "power_curve" in performance:
|
|
55
58
|
power_curve = Dict(performance["power_curve"], name="power_curve")
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
print(" Contents:", [k for k in power_curve.keys()])
|
|
59
|
+
_print(" Reading power_curve", level=3)
|
|
60
|
+
_print(" Contents:", [k for k in power_curve.keys()], level=3)
|
|
59
61
|
P = power_curve["power_values"]
|
|
60
62
|
ws_P = power_curve["power_wind_speeds"]
|
|
61
63
|
ct_curve = Dict(performance["Ct_curve"], name="Ct_values")
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
print(" Contents:", [k for k in ct_curve.keys()])
|
|
64
|
+
_print(" Reading Ct_curve", level=3)
|
|
65
|
+
_print(" Contents:", [k for k in ct_curve.keys()], level=3)
|
|
65
66
|
ct = ct_curve["Ct_values"]
|
|
66
67
|
ws_ct = ct_curve["Ct_wind_speeds"]
|
|
67
68
|
|
|
@@ -75,10 +76,9 @@ def read_turbine_types(wio_farm, algo_dict, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
75
76
|
)
|
|
76
77
|
return FV.REWS if wse == 1 else (FV.REWS2 if wse == 2 else FV.REWS3)
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
algo_dict["mbook"].turbine_types[tname] = TurbineType.new(
|
|
79
|
+
_print(f" Creating model '{tname}'", level=3)
|
|
80
|
+
_print(f" Turbine type class: PCtFomTwo", level=3)
|
|
81
|
+
mbook.turbine_types[tname] = TurbineType.new(
|
|
82
82
|
ttype_type="PCtFromTwo",
|
|
83
83
|
data_source_P=data_P,
|
|
84
84
|
data_source_ct=data_ct,
|
|
@@ -92,31 +92,27 @@ def read_turbine_types(wio_farm, algo_dict, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
92
92
|
var_ws_P=_get_wse_var(ws_exp_P),
|
|
93
93
|
rho=1.225,
|
|
94
94
|
)
|
|
95
|
-
|
|
96
|
-
print(" ", algo_dict["mbook"].turbine_types[tname])
|
|
95
|
+
_print(" ", mbook.turbine_types[tname], level=3)
|
|
97
96
|
|
|
98
97
|
# P, ct data:
|
|
99
98
|
elif "Cp_curve" in performance:
|
|
100
99
|
cp_curve = Dict(performance["Cp_curve"], name="Cp_curve")
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
print(" Contents:", [k for k in cp_curve.keys()])
|
|
100
|
+
_print(" Reading Cp_curve", level=3)
|
|
101
|
+
_print(" Contents:", [k for k in cp_curve.keys()], level=3)
|
|
104
102
|
cp = cp_curve["Cp_values"]
|
|
105
103
|
ws_cp = cp_curve["Cp_wind_speeds"]
|
|
106
104
|
ct_curve = Dict(performance["Ct_curve"], name="Ct_values")
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
print(" Contents:", [k for k in ct_curve.keys()])
|
|
105
|
+
_print(" Reading Ct_curve", level=3)
|
|
106
|
+
_print(" Contents:", [k for k in ct_curve.keys()], level=3)
|
|
110
107
|
ct = ct_curve["Ct_values"]
|
|
111
108
|
ws_ct = ct_curve["Ct_wind_speeds"]
|
|
112
109
|
|
|
113
110
|
data_cp = pd.DataFrame(data={"ws": ws_cp, "cp": cp})
|
|
114
111
|
data_ct = pd.DataFrame(data={"ws": ws_ct, "ct": ct})
|
|
115
112
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
algo_dict["mbook"].turbine_types[tname] = TurbineType.new(
|
|
113
|
+
_print(f" Creating model '{tname}'", level=3)
|
|
114
|
+
_print(f" Turbine type class: CpCtFromTwo", level=3)
|
|
115
|
+
mbook.turbine_types[tname] = TurbineType.new(
|
|
120
116
|
ttype_type="CpCtFromTwo",
|
|
121
117
|
data_source_cp=data_cp,
|
|
122
118
|
data_source_ct=data_ct,
|
|
@@ -127,6 +123,7 @@ def read_turbine_types(wio_farm, algo_dict, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
127
123
|
H=wio_trbns["hub_height"],
|
|
128
124
|
D=wio_trbns["rotor_diameter"],
|
|
129
125
|
)
|
|
126
|
+
_print(" ", mbook.turbine_types[tname], level=3)
|
|
130
127
|
|
|
131
128
|
else:
|
|
132
129
|
raise KeyError(f"Expecting either 'power_curve' or 'Cp_curve'")
|
|
@@ -134,7 +131,7 @@ def read_turbine_types(wio_farm, algo_dict, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
134
131
|
return ttypes
|
|
135
132
|
|
|
136
133
|
|
|
137
|
-
def read_layout(lname, ldict,
|
|
134
|
+
def read_layout(lname, ldict, farm, ttypes, verbosity=1):
|
|
138
135
|
"""
|
|
139
136
|
Read wind farm layout from windio input
|
|
140
137
|
|
|
@@ -144,26 +141,20 @@ def read_layout(lname, ldict, algo_dict, ttypes, verbosity=1):
|
|
|
144
141
|
The layout name
|
|
145
142
|
ldict: dict
|
|
146
143
|
The layout data
|
|
147
|
-
|
|
148
|
-
The
|
|
144
|
+
farm: foxes.core.WindFarm
|
|
145
|
+
The wind farm
|
|
149
146
|
ttypes: dict
|
|
150
147
|
Mapping from turbine type key to turbine
|
|
151
148
|
type name in the model book
|
|
152
149
|
verbosity: int
|
|
153
150
|
The verbosity level, 0=silent
|
|
154
151
|
|
|
155
|
-
|
|
156
|
-
-------
|
|
157
|
-
states: foxes.core.States
|
|
158
|
-
The states object
|
|
159
|
-
|
|
160
|
-
:group: input.windio
|
|
152
|
+
:group: input.yaml.windio
|
|
161
153
|
|
|
162
154
|
"""
|
|
163
155
|
if verbosity > 2:
|
|
164
156
|
print(f" Reading '{lname}'")
|
|
165
157
|
cdict = Dict(ldict["coordinates"], name="coordinates")
|
|
166
|
-
farm = algo_dict["farm"]
|
|
167
158
|
tmap = ldict.get("turbine_types", None)
|
|
168
159
|
if verbosity > 2:
|
|
169
160
|
print(f" Turbine type map:", tmap)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
from numbers import Number
|
|
3
3
|
|
|
4
|
-
import foxes.constants as FC
|
|
5
4
|
import foxes.variables as FV
|
|
5
|
+
import foxes.constants as FC
|
|
6
|
+
|
|
6
7
|
|
|
7
8
|
""" Mapping from windio to foxes variables
|
|
8
|
-
:group: input.windio
|
|
9
|
+
:group: input.yaml.windio
|
|
9
10
|
"""
|
|
10
11
|
wio2foxes = {
|
|
11
12
|
"time": FC.TIME,
|
|
@@ -24,14 +25,14 @@ wio2foxes = {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
""" Mapping from foxes to windio variables
|
|
27
|
-
:group: input.windio
|
|
28
|
+
:group: input.yaml.windio
|
|
28
29
|
"""
|
|
29
30
|
foxes2wio = {d: k for k, d in wio2foxes.items()}
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
def _read_nondimensional_coordinate(name, wio_data, coords):
|
|
33
34
|
"""read nondimensional coordinate
|
|
34
|
-
:group: input.windio
|
|
35
|
+
:group: input.yaml.windio
|
|
35
36
|
"""
|
|
36
37
|
if isinstance(wio_data, Number):
|
|
37
38
|
coords[wio2foxes[name]] = wio_data
|
|
@@ -41,7 +42,7 @@ def _read_nondimensional_coordinate(name, wio_data, coords):
|
|
|
41
42
|
|
|
42
43
|
def _read_dimensional_coordinate(name, wio_data, coords):
|
|
43
44
|
"""read dimensional coordinate
|
|
44
|
-
:group: input.windio
|
|
45
|
+
:group: input.yaml.windio
|
|
45
46
|
"""
|
|
46
47
|
if isinstance(wio_data, list):
|
|
47
48
|
wio_data = np.array(wio_data)
|
|
@@ -53,7 +54,7 @@ def _read_dimensional_coordinate(name, wio_data, coords):
|
|
|
53
54
|
|
|
54
55
|
def _read_multi_dimensional_coordinate(name, wio_data, coords):
|
|
55
56
|
"""Read multi dimensional coordinate
|
|
56
|
-
:group: input.windio
|
|
57
|
+
:group: input.yaml.windio
|
|
57
58
|
"""
|
|
58
59
|
return _read_nondimensional_coordinate(
|
|
59
60
|
name, wio_data, coords
|
|
@@ -62,7 +63,7 @@ def _read_multi_dimensional_coordinate(name, wio_data, coords):
|
|
|
62
63
|
|
|
63
64
|
def _read_nondimensional_data(name, wio_data, fields, dims):
|
|
64
65
|
"""read nondimensional data
|
|
65
|
-
:group: input.windio
|
|
66
|
+
:group: input.yaml.windio
|
|
66
67
|
"""
|
|
67
68
|
if isinstance(wio_data, Number):
|
|
68
69
|
v = wio2foxes[name]
|
|
@@ -74,7 +75,7 @@ def _read_nondimensional_data(name, wio_data, fields, dims):
|
|
|
74
75
|
|
|
75
76
|
def _read_dimensional_data(name, wio_data, fields, dims):
|
|
76
77
|
"""read dimensional data
|
|
77
|
-
:group: input.windio
|
|
78
|
+
:group: input.yaml.windio
|
|
78
79
|
"""
|
|
79
80
|
if isinstance(wio_data, dict) and "data" in wio_data and "dims" in wio_data:
|
|
80
81
|
d = wio_data["data"]
|
|
@@ -91,7 +92,7 @@ def _read_dimensional_data(name, wio_data, fields, dims):
|
|
|
91
92
|
|
|
92
93
|
def _read_multi_dimensional_data(name, wio_data, fields, dims):
|
|
93
94
|
"""Read multi dimensional data
|
|
94
|
-
:group: input.windio
|
|
95
|
+
:group: input.yaml.windio
|
|
95
96
|
"""
|
|
96
97
|
return _read_nondimensional_data(
|
|
97
98
|
name, wio_data, fields, dims
|
|
@@ -129,7 +130,7 @@ def read_wind_resource_field(
|
|
|
129
130
|
success: bool
|
|
130
131
|
Flag for successful data extraction
|
|
131
132
|
|
|
132
|
-
:group: input.windio
|
|
133
|
+
:group: input.yaml.windio
|
|
133
134
|
|
|
134
135
|
"""
|
|
135
136
|
if name in [
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from foxes.utils import Dict
|
|
4
|
+
import foxes.variables as FV
|
|
5
|
+
import foxes.constants as FC
|
|
6
|
+
|
|
7
|
+
from .read_fields import foxes2wio
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _read_turbine_outputs(wio_outs, odict, verbosity):
|
|
11
|
+
"""Reads the turbine outputs request"""
|
|
12
|
+
if "turbine_outputs" in wio_outs and wio_outs["turbine_outputs"].get(
|
|
13
|
+
"report", True
|
|
14
|
+
):
|
|
15
|
+
turbine_outputs = Dict(
|
|
16
|
+
wio_outs["turbine_outputs"], name=wio_outs.name + ".turbine_outputs"
|
|
17
|
+
)
|
|
18
|
+
turbine_nc_filename = turbine_outputs.pop(
|
|
19
|
+
"turbine_nc_filename", "turbine_outputs.nc"
|
|
20
|
+
)
|
|
21
|
+
output_variables = turbine_outputs["output_variables"]
|
|
22
|
+
if verbosity > 2:
|
|
23
|
+
print(" Reading turbine_outputs")
|
|
24
|
+
print(" File name:", turbine_nc_filename)
|
|
25
|
+
print(" output_variables:", output_variables)
|
|
26
|
+
|
|
27
|
+
vmap = Dict(
|
|
28
|
+
power=FV.P,
|
|
29
|
+
rotor_effective_velocity=FV.REWS,
|
|
30
|
+
)
|
|
31
|
+
ivmap = {d: k for k, d in vmap.items()}
|
|
32
|
+
ivmap.update(
|
|
33
|
+
{
|
|
34
|
+
FC.STATE: "time",
|
|
35
|
+
FC.TURBINE: "turbine",
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
odict["StateTurbineTable"] = Dict(
|
|
40
|
+
functions=[
|
|
41
|
+
dict(
|
|
42
|
+
name="get_dataset",
|
|
43
|
+
variables=[vmap[v] for v in output_variables],
|
|
44
|
+
name_map=ivmap,
|
|
45
|
+
to_file=turbine_nc_filename,
|
|
46
|
+
round={vw: FV.get_default_digits(vf) for vw, vf in vmap.items()},
|
|
47
|
+
verbosity=verbosity,
|
|
48
|
+
)
|
|
49
|
+
],
|
|
50
|
+
name=odict.name + ".StateTurbineTable",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _read_flow_field(wio_outs, odict, verbosity):
|
|
55
|
+
"""Reads the flow field request"""
|
|
56
|
+
if "flow_field" in wio_outs and wio_outs["flow_field"].get("report", True):
|
|
57
|
+
flow_field = Dict(wio_outs["flow_field"], name=wio_outs.name + ".flow_field")
|
|
58
|
+
flow_nc_filename = flow_field.pop("flow_nc_filename", "flow_field.nc")
|
|
59
|
+
output_variables = flow_field.pop("output_variables")
|
|
60
|
+
z_planes = Dict(flow_field.pop("z_planes"), name=flow_field.name + ".z_planes")
|
|
61
|
+
z_sampling = z_planes["z_sampling"]
|
|
62
|
+
xy_sampling = z_planes["xy_sampling"]
|
|
63
|
+
cases_run = Dict(
|
|
64
|
+
flow_field.pop("cases_run", {}), name=flow_field.name + ".cases_run"
|
|
65
|
+
)
|
|
66
|
+
states_isel = cases_run.get("subset", None)
|
|
67
|
+
if "all_occurences" in cases_run and cases_run.pop("all_occurences"):
|
|
68
|
+
states_isel = None
|
|
69
|
+
if verbosity > 2:
|
|
70
|
+
print(" Reading flow_field")
|
|
71
|
+
print(" File name :", flow_nc_filename)
|
|
72
|
+
print(" output_variables:", output_variables)
|
|
73
|
+
print(" states subset :", states_isel)
|
|
74
|
+
print(" z_sampling :", z_sampling)
|
|
75
|
+
print(" xy_sampling :", xy_sampling)
|
|
76
|
+
|
|
77
|
+
vmap = Dict(
|
|
78
|
+
wind_speed=FV.WS,
|
|
79
|
+
wind_direction=FV.WD,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
if z_sampling in ["hub_height", "default"]:
|
|
83
|
+
z = None
|
|
84
|
+
elif isinstance(z_sampling, (int, float)):
|
|
85
|
+
z = z_sampling
|
|
86
|
+
else:
|
|
87
|
+
raise NotImplementedError(
|
|
88
|
+
f"z_sampling '{z_sampling}' of type '{type(z_sampling).__name__}' is not supported (yet). Please give 'hub_height', 'default' or a float."
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
if xy_sampling == "default":
|
|
92
|
+
odict["SliceData"] = Dict(
|
|
93
|
+
verbosity_delta=3,
|
|
94
|
+
functions=[
|
|
95
|
+
dict(
|
|
96
|
+
name="get_states_data_xy",
|
|
97
|
+
states_isel=states_isel,
|
|
98
|
+
n_img_points=(100, 100),
|
|
99
|
+
variables=[vmap[v] for v in output_variables],
|
|
100
|
+
z=z,
|
|
101
|
+
to_file=flow_nc_filename,
|
|
102
|
+
label_map=foxes2wio,
|
|
103
|
+
verbosity=verbosity,
|
|
104
|
+
)
|
|
105
|
+
],
|
|
106
|
+
name=odict.name + ".SliceData",
|
|
107
|
+
)
|
|
108
|
+
else:
|
|
109
|
+
raise NotImplementedError(
|
|
110
|
+
f"xy_sampling '{xy_sampling}' is not supported (yet)"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def read_outputs(wio_outs, odict, verbosity=1):
|
|
115
|
+
"""
|
|
116
|
+
Reads the windio outputs
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
wio_outs: foxes.utils.Dict
|
|
121
|
+
The windio output data dict
|
|
122
|
+
odict: foxes.utils.Dict
|
|
123
|
+
The foxes output dictionary
|
|
124
|
+
verbosity: int
|
|
125
|
+
The verbosity level, 0=silent
|
|
126
|
+
|
|
127
|
+
Returns
|
|
128
|
+
-------
|
|
129
|
+
odir: pathlib.Path
|
|
130
|
+
The output directory
|
|
131
|
+
|
|
132
|
+
:group: input.yaml.windio
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
odir = wio_outs.pop("output_folder", ".")
|
|
136
|
+
if verbosity > 2:
|
|
137
|
+
print(" Reading outputs")
|
|
138
|
+
print(" Output dir:", odir)
|
|
139
|
+
print(" Contents :", [k for k in wio_outs.keys()])
|
|
140
|
+
|
|
141
|
+
# read turbine_outputs:
|
|
142
|
+
_read_turbine_outputs(wio_outs, odict, verbosity)
|
|
143
|
+
|
|
144
|
+
# read flow field:
|
|
145
|
+
_read_flow_field(wio_outs, odict, verbosity)
|
|
146
|
+
|
|
147
|
+
return odir
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from foxes.core import WindFarm
|
|
5
|
+
from foxes.models import ModelBook
|
|
6
|
+
from foxes.utils import import_module, Dict
|
|
7
|
+
|
|
8
|
+
from .read_fields import read_wind_resource_field
|
|
9
|
+
from .get_states import get_states
|
|
10
|
+
from .read_farm import read_layout, read_turbine_types
|
|
11
|
+
from .read_attributes import read_attributes
|
|
12
|
+
from ..dict import run_dict
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _read_site(wio_dict, verbosity):
|
|
16
|
+
"""Reads the site information"""
|
|
17
|
+
|
|
18
|
+
def _print(*args, level=1, **kwargs):
|
|
19
|
+
if verbosity >= level:
|
|
20
|
+
print(*args, **kwargs)
|
|
21
|
+
|
|
22
|
+
wio_site = Dict(wio_dict["site"], name=wio_dict.name + ".site")
|
|
23
|
+
_print("Reading site")
|
|
24
|
+
_print(" Name:", wio_site.pop("name", None))
|
|
25
|
+
_print(" Contents:", [k for k in wio_site.keys()])
|
|
26
|
+
_print(" Ignoring boundaries", level=2)
|
|
27
|
+
|
|
28
|
+
# read energy_resource:
|
|
29
|
+
energy_resource = Dict(
|
|
30
|
+
wio_site["energy_resource"], name=wio_site.name + ".energy_resource"
|
|
31
|
+
)
|
|
32
|
+
_print(" Reading energy_resource", level=2)
|
|
33
|
+
_print(" Name:", energy_resource.pop("name", None), level=2)
|
|
34
|
+
_print(" Contents:", [k for k in energy_resource.keys()], level=2)
|
|
35
|
+
|
|
36
|
+
# read wind_resource:
|
|
37
|
+
wind_resource = Dict(
|
|
38
|
+
energy_resource["wind_resource"], name=energy_resource.name + ".wind_resource"
|
|
39
|
+
)
|
|
40
|
+
_print(" Reading wind_resource", level=3)
|
|
41
|
+
_print(" Name:", wind_resource.pop("name", None), level=3)
|
|
42
|
+
_print(" Contents:", [k for k in wind_resource.keys()], level=3)
|
|
43
|
+
|
|
44
|
+
# read fields
|
|
45
|
+
coords = Dict(name="coords")
|
|
46
|
+
fields = Dict(name="fields")
|
|
47
|
+
dims = Dict(name="dims")
|
|
48
|
+
for n, d in wind_resource.items():
|
|
49
|
+
read_wind_resource_field(n, d, coords, fields, dims, verbosity)
|
|
50
|
+
if verbosity > 2:
|
|
51
|
+
print(" Coords:")
|
|
52
|
+
for c, d in coords.items():
|
|
53
|
+
print(f" {c}: Shape {d.shape}")
|
|
54
|
+
print(" Fields:")
|
|
55
|
+
for f, d in dims.items():
|
|
56
|
+
if len(d):
|
|
57
|
+
print(f" {f}: Dims {d}, shape {fields[f].shape}")
|
|
58
|
+
else:
|
|
59
|
+
print(f" {f} = {fields[f]}")
|
|
60
|
+
|
|
61
|
+
return get_states(coords, fields, dims, verbosity)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _read_farm(wio_dict, mbook, verbosity):
|
|
65
|
+
"""Reads the wind farm information"""
|
|
66
|
+
wio_farm = Dict(wio_dict["wind_farm"], name=wio_dict.name + ".wind_farm")
|
|
67
|
+
if verbosity > 1:
|
|
68
|
+
print("Reading wind farm")
|
|
69
|
+
print(" Name:", wio_farm.pop("name", None))
|
|
70
|
+
print(" Contents:", [k for k in wio_farm.keys()])
|
|
71
|
+
|
|
72
|
+
# find REWS exponents:
|
|
73
|
+
try:
|
|
74
|
+
rotor_averaging = wio_dict["attributes"]["analysis"]["rotor_averaging"]
|
|
75
|
+
ws_exp_P = rotor_averaging["wind_speed_exponent_for_power"]
|
|
76
|
+
ws_exp_ct = rotor_averaging["wind_speed_exponent_for_ct"]
|
|
77
|
+
except KeyError:
|
|
78
|
+
ws_exp_P = 1
|
|
79
|
+
ws_exp_ct = 1
|
|
80
|
+
|
|
81
|
+
# read turbine type:
|
|
82
|
+
ttypes = read_turbine_types(wio_farm, mbook, ws_exp_P, ws_exp_ct, verbosity)
|
|
83
|
+
|
|
84
|
+
# read layouts and create wind farm:
|
|
85
|
+
farm = WindFarm()
|
|
86
|
+
wfarm = wio_farm["layouts"]
|
|
87
|
+
if isinstance(wfarm, dict):
|
|
88
|
+
layouts = Dict(wfarm, name=wio_farm.name + ".layouts")
|
|
89
|
+
else:
|
|
90
|
+
layouts = {str(i): l for i, l in enumerate(wfarm)}
|
|
91
|
+
layouts = Dict(layouts, name=wio_farm.name + ".layouts")
|
|
92
|
+
if verbosity > 2:
|
|
93
|
+
print(" Reading layouts")
|
|
94
|
+
print(" Contents:", [k for k in layouts.keys()])
|
|
95
|
+
for lname, ldict in layouts.items():
|
|
96
|
+
read_layout(lname, ldict, farm, ttypes, verbosity)
|
|
97
|
+
|
|
98
|
+
return farm
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def read_windio(wio_dict, verbosity=1):
|
|
102
|
+
"""
|
|
103
|
+
Translate windio data to foxes input data
|
|
104
|
+
|
|
105
|
+
Parameters
|
|
106
|
+
----------
|
|
107
|
+
wio_dict: foxes.utils.Dict
|
|
108
|
+
The windio data
|
|
109
|
+
verbosity: int
|
|
110
|
+
The verbosity level, 0 = silent
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
idict: foxes.utils.Dict
|
|
115
|
+
The foxes input data dictionary
|
|
116
|
+
states: foxes.core.States
|
|
117
|
+
The states object
|
|
118
|
+
farm: foxes.core.WindFarm
|
|
119
|
+
The wind farm
|
|
120
|
+
mbook: foxes.models.ModelBook
|
|
121
|
+
The model book
|
|
122
|
+
|
|
123
|
+
:group: input.yaml.windio
|
|
124
|
+
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
def _print(*args, level=1, **kwargs):
|
|
128
|
+
if verbosity >= level:
|
|
129
|
+
print(*args, **kwargs)
|
|
130
|
+
|
|
131
|
+
_print(f"Reading windio data")
|
|
132
|
+
_print(" Name:", wio_dict.pop("name", None))
|
|
133
|
+
_print(" Contents:", [k for k in wio_dict.keys()])
|
|
134
|
+
|
|
135
|
+
idict = Dict(
|
|
136
|
+
wind_farm=Dict(name="wio2fxs.farm"),
|
|
137
|
+
algorithm=Dict(
|
|
138
|
+
algo_type="Downwind",
|
|
139
|
+
wake_models=[],
|
|
140
|
+
name="wio2fxs.algorithm",
|
|
141
|
+
verbosity=verbosity - 3,
|
|
142
|
+
),
|
|
143
|
+
calc_farm=Dict(run=True, name="wio2fxs.calc_farm"),
|
|
144
|
+
outputs=Dict(name="wio2fxs.outputs"),
|
|
145
|
+
name="wio2fxs",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
mbook = ModelBook()
|
|
149
|
+
states = _read_site(wio_dict, verbosity)
|
|
150
|
+
farm = _read_farm(wio_dict, mbook, verbosity)
|
|
151
|
+
|
|
152
|
+
odir = read_attributes(wio_dict, idict, mbook, verbosity=verbosity)
|
|
153
|
+
|
|
154
|
+
return idict, states, farm, mbook, odir
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def foxes_windio():
|
|
158
|
+
"""
|
|
159
|
+
Command line tool for running foxes from windio yaml file input.
|
|
160
|
+
|
|
161
|
+
Examples
|
|
162
|
+
--------
|
|
163
|
+
>>> foxes_windio input.yaml
|
|
164
|
+
|
|
165
|
+
:group: input.yaml.windio
|
|
166
|
+
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
parser = argparse.ArgumentParser()
|
|
170
|
+
parser.add_argument(
|
|
171
|
+
"yml_file",
|
|
172
|
+
help="The windio yaml file",
|
|
173
|
+
)
|
|
174
|
+
parser.add_argument("-o", "--out_dir", help="The output directory", default=None)
|
|
175
|
+
parser.add_argument("-r", "--rotor", help="The rotor model", default="centre")
|
|
176
|
+
parser.add_argument(
|
|
177
|
+
"-p", "--pwakes", help="The partial wakes models", default="centre", nargs="+"
|
|
178
|
+
)
|
|
179
|
+
parser.add_argument(
|
|
180
|
+
"-w",
|
|
181
|
+
"--wakes",
|
|
182
|
+
help="The wake models",
|
|
183
|
+
default=["Jensen_linear_k007"],
|
|
184
|
+
nargs="+",
|
|
185
|
+
)
|
|
186
|
+
parser.add_argument("-f", "--frame", help="The wake frame", default="rotor_wd")
|
|
187
|
+
parser.add_argument("-e", "--engine", help="The engine", default=None)
|
|
188
|
+
parser.add_argument(
|
|
189
|
+
"-n", "--n_procs", help="The number of processes", default=None, type=int
|
|
190
|
+
)
|
|
191
|
+
parser.add_argument(
|
|
192
|
+
"-c",
|
|
193
|
+
"--chunksize_states",
|
|
194
|
+
help="The chunk size for states",
|
|
195
|
+
default=None,
|
|
196
|
+
type=int,
|
|
197
|
+
)
|
|
198
|
+
parser.add_argument(
|
|
199
|
+
"-C",
|
|
200
|
+
"--chunksize_points",
|
|
201
|
+
help="The chunk size for points",
|
|
202
|
+
default=5000,
|
|
203
|
+
type=int,
|
|
204
|
+
)
|
|
205
|
+
parser.add_argument(
|
|
206
|
+
"-it", "--iterative", help="Use iterative algorithm", action="store_true"
|
|
207
|
+
)
|
|
208
|
+
parser.add_argument(
|
|
209
|
+
"-nf", "--nofig", help="Do not show figures", action="store_true"
|
|
210
|
+
)
|
|
211
|
+
parser.add_argument(
|
|
212
|
+
"-v",
|
|
213
|
+
"--verbosity",
|
|
214
|
+
help="The verbosity level, 0 = silent",
|
|
215
|
+
type=int,
|
|
216
|
+
default=None,
|
|
217
|
+
)
|
|
218
|
+
args = parser.parse_args()
|
|
219
|
+
|
|
220
|
+
v = 1 if args.verbosity is None else args.verbosity
|
|
221
|
+
|
|
222
|
+
def _print(*args, level=1, **kwargs):
|
|
223
|
+
if v >= level:
|
|
224
|
+
print(*args, **kwargs)
|
|
225
|
+
|
|
226
|
+
if (
|
|
227
|
+
args.engine is not None
|
|
228
|
+
or args.n_procs is not None
|
|
229
|
+
or args.chunksize_states is not None
|
|
230
|
+
or args.chunksize_points is not None
|
|
231
|
+
):
|
|
232
|
+
epars = dict(
|
|
233
|
+
engine_type=args.engine,
|
|
234
|
+
n_procs=args.n_procs,
|
|
235
|
+
chunk_size_states=args.chunksize_states,
|
|
236
|
+
chunk_size_points=args.chunksize_points,
|
|
237
|
+
verbosity=v,
|
|
238
|
+
)
|
|
239
|
+
else:
|
|
240
|
+
epars = None
|
|
241
|
+
|
|
242
|
+
wio_file = Path(args.yml_file)
|
|
243
|
+
_print(f"Reading windio file {wio_file}")
|
|
244
|
+
yml_utils = import_module(
|
|
245
|
+
"windIO.utils.yml_utils",
|
|
246
|
+
hint="pip install git+https://github.com/kilojoules/windIO@master#egg=windIO",
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
wio = Dict(yml_utils.load_yaml(wio_file), name="windio")
|
|
250
|
+
idict, states, farm, mbook, odir = read_windio(wio, verbosity=v)
|
|
251
|
+
|
|
252
|
+
if args.out_dir is not None:
|
|
253
|
+
odir = args.odir
|
|
254
|
+
|
|
255
|
+
run_dict(
|
|
256
|
+
idict,
|
|
257
|
+
farm=farm,
|
|
258
|
+
states=states,
|
|
259
|
+
mbook=mbook,
|
|
260
|
+
rotor_model=args.rotor,
|
|
261
|
+
partial_wakes=args.pwakes,
|
|
262
|
+
wake_models=args.wakes,
|
|
263
|
+
wake_frame=args.frame,
|
|
264
|
+
engine_pars=epars,
|
|
265
|
+
iterative=args.iterative,
|
|
266
|
+
work_dir=wio_file.parent,
|
|
267
|
+
out_dir=odir,
|
|
268
|
+
verbosity=args.verbosity,
|
|
269
|
+
)
|