foxes 0.7.2__py3-none-any.whl → 0.7.3.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.
- foxes/VERSION +1 -1
- foxes/algorithms/downwind/downwind.py +57 -45
- foxes/algorithms/downwind/models/farm_wakes_calc.py +17 -6
- foxes/algorithms/downwind/models/point_wakes_calc.py +13 -45
- foxes/algorithms/iterative/iterative.py +1 -1
- foxes/algorithms/iterative/models/farm_wakes_calc.py +18 -4
- foxes/constants.py +5 -0
- foxes/core/__init__.py +2 -1
- foxes/core/ground_model.py +254 -0
- foxes/core/model.py +3 -2
- foxes/core/partial_wakes_model.py +19 -3
- foxes/core/states.py +33 -0
- foxes/core/wake_model.py +138 -2
- foxes/data/__init__.py +1 -1
- foxes/data/states/WRF-Timeseries-3000.nc +0 -0
- foxes/data/states/windio_timeseries_5000.nc +0 -0
- foxes/data/static_data.py +7 -0
- foxes/data/windio/DTU_10MW_turbine.yaml +10 -0
- foxes/data/windio/__init__.py +0 -0
- foxes/data/windio/windio_5turbines_timeseries.yaml +63 -0
- foxes/input/states/__init__.py +1 -0
- foxes/input/states/multi_height.py +225 -6
- foxes/input/windio/__init__.py +6 -1
- foxes/input/windio/get_states.py +115 -0
- foxes/input/windio/read_attributes.py +321 -0
- foxes/input/windio/read_farm.py +163 -0
- foxes/input/windio/read_fields.py +164 -0
- foxes/input/windio/runner.py +105 -0
- foxes/input/windio/windio.py +136 -254
- foxes/models/__init__.py +1 -0
- foxes/models/ground_models/__init__.py +2 -0
- foxes/models/ground_models/no_ground.py +12 -0
- foxes/models/ground_models/wake_mirror.py +161 -0
- foxes/models/model_book.py +68 -149
- foxes/models/partial_wakes/axiwake.py +27 -4
- foxes/models/partial_wakes/top_hat.py +26 -4
- foxes/models/turbine_types/PCt_file.py +1 -0
- foxes/models/turbine_types/PCt_from_two.py +92 -0
- foxes/models/wake_frames/yawed_wakes.py +41 -38
- foxes/models/wake_models/__init__.py +0 -1
- foxes/models/wake_models/induction/__init__.py +1 -0
- foxes/models/wake_models/induction/rankine_half_body.py +1 -1
- foxes/models/wake_models/induction/vortex_sheet.py +227 -0
- foxes/models/wake_models/ti/crespo_hernandez.py +26 -24
- foxes/models/wake_models/ti/iec_ti.py +33 -26
- foxes/models/wake_models/wind/bastankhah14.py +11 -32
- foxes/models/wake_models/wind/bastankhah16.py +30 -34
- foxes/models/wake_models/wind/jensen.py +13 -29
- foxes/models/wake_models/wind/turbopark.py +31 -61
- foxes/output/grids.py +6 -6
- foxes/output/output.py +6 -6
- foxes/utils/__init__.py +1 -1
- foxes/utils/factory.py +203 -11
- {foxes-0.7.2.dist-info → foxes-0.7.3.1.dist-info}/METADATA +8 -6
- {foxes-0.7.2.dist-info → foxes-0.7.3.1.dist-info}/RECORD +59 -45
- {foxes-0.7.2.dist-info → foxes-0.7.3.1.dist-info}/WHEEL +1 -1
- foxes/models/wake_models/wake_mirror.py +0 -196
- {foxes-0.7.2.dist-info → foxes-0.7.3.1.dist-info}/LICENSE +0 -0
- {foxes-0.7.2.dist-info → foxes-0.7.3.1.dist-info}/top_level.txt +0 -0
- {foxes-0.7.2.dist-info → foxes-0.7.3.1.dist-info}/zip-safe +0 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from numbers import Number
|
|
3
|
+
|
|
4
|
+
import foxes.constants as FC
|
|
5
|
+
import foxes.variables as FV
|
|
6
|
+
|
|
7
|
+
""" Mapping from windio to foxes variables
|
|
8
|
+
:group: input.windio
|
|
9
|
+
"""
|
|
10
|
+
wio2foxes = {
|
|
11
|
+
"time": FC.TIME,
|
|
12
|
+
"x": FV.X,
|
|
13
|
+
"y": FV.Y,
|
|
14
|
+
"height": FV.H,
|
|
15
|
+
"wind_turbine": FC.TURBINE,
|
|
16
|
+
"wind_direction": FV.WD,
|
|
17
|
+
"wind_speed": FV.WS,
|
|
18
|
+
"probability": FV.WEIGHT,
|
|
19
|
+
"sector_probability": "sector_probability",
|
|
20
|
+
"turbulence_intensity": FV.TI,
|
|
21
|
+
"LMO": FV.MOL,
|
|
22
|
+
"z0": FV.Z0,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
""" Mapping from foxes to windio variables
|
|
26
|
+
:group: input.windio
|
|
27
|
+
"""
|
|
28
|
+
foxes2wio = {d: k for k, d in wio2foxes.items()}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _read_nondimensional_coordinate(name, wio_data, coords, fields, dims):
|
|
32
|
+
"""read nondimensional coordinate
|
|
33
|
+
:group: input.windio
|
|
34
|
+
"""
|
|
35
|
+
if isinstance(wio_data, Number):
|
|
36
|
+
coords[wio2foxes[name]] = wio_data
|
|
37
|
+
return True
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _read_dimensional_coordinate(name, wio_data, coords, fields, dims):
|
|
42
|
+
"""read dimensional coordinate
|
|
43
|
+
:group: input.windio
|
|
44
|
+
"""
|
|
45
|
+
if isinstance(wio_data, list):
|
|
46
|
+
wio_data = np.array(wio_data)
|
|
47
|
+
if isinstance(wio_data, np.ndarray) and len(wio_data.shape) == 1:
|
|
48
|
+
coords[wio2foxes[name]] = wio_data
|
|
49
|
+
return True
|
|
50
|
+
return False
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _read_multi_dimensional_coordinate(*args, **kwargs):
|
|
54
|
+
"""Read multi dimensional coordinate
|
|
55
|
+
:group: input.windio
|
|
56
|
+
"""
|
|
57
|
+
return _read_nondimensional_coordinate(
|
|
58
|
+
*args, **kwargs
|
|
59
|
+
) or _read_dimensional_coordinate(*args, **kwargs)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _read_nondimensional_data(name, wio_data, coords, fields, dims):
|
|
63
|
+
"""read nondimensional data
|
|
64
|
+
:group: input.windio
|
|
65
|
+
"""
|
|
66
|
+
if isinstance(wio_data, Number):
|
|
67
|
+
v = wio2foxes[name]
|
|
68
|
+
fields[v] = wio_data
|
|
69
|
+
dims[v] = []
|
|
70
|
+
return True
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _read_dimensional_data(name, wio_data, coords, fields, dims):
|
|
75
|
+
"""read dimensional data
|
|
76
|
+
:group: input.windio
|
|
77
|
+
"""
|
|
78
|
+
if isinstance(wio_data, dict) and "data" in wio_data and "dims" in wio_data:
|
|
79
|
+
d = wio_data["data"]
|
|
80
|
+
v = wio2foxes[name]
|
|
81
|
+
fields[v] = d if isinstance(d, np.ndarray) else np.array(d)
|
|
82
|
+
dims[v] = tuple([wio2foxes[c] for c in wio_data["dims"]])
|
|
83
|
+
if len(dims[v]) != len(fields[v].shape):
|
|
84
|
+
raise ValueError(
|
|
85
|
+
f"Field '{name}': Dimensions {dims[v]} do not match shape {fields[v].shape}"
|
|
86
|
+
)
|
|
87
|
+
return True
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _read_multi_dimensional_data(*args, **kwargs):
|
|
92
|
+
"""Read multi dimensional data
|
|
93
|
+
:group: input.windio
|
|
94
|
+
"""
|
|
95
|
+
return _read_nondimensional_data(*args, **kwargs) or _read_dimensional_data(
|
|
96
|
+
*args, **kwargs
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def read_wind_resource_field(name, wio_data, coords, fields, dims):
|
|
101
|
+
"""
|
|
102
|
+
Reads wind resource data into fields and dims
|
|
103
|
+
|
|
104
|
+
Parameters
|
|
105
|
+
----------
|
|
106
|
+
name: str
|
|
107
|
+
The windio variable name
|
|
108
|
+
wio_data: object
|
|
109
|
+
The windio data
|
|
110
|
+
coords: dict
|
|
111
|
+
The coordinates dict, filled on the fly
|
|
112
|
+
fields: dict
|
|
113
|
+
The fields dict, filled on the fly
|
|
114
|
+
dims: dict
|
|
115
|
+
The dimensions dict, filled on the fly
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
success: bool
|
|
120
|
+
Flag for successful data extraction
|
|
121
|
+
|
|
122
|
+
:group: input.windio
|
|
123
|
+
|
|
124
|
+
"""
|
|
125
|
+
if name in [
|
|
126
|
+
"weibull_a",
|
|
127
|
+
"weibull_k",
|
|
128
|
+
"potential_temperature",
|
|
129
|
+
"friction_velocity",
|
|
130
|
+
"k",
|
|
131
|
+
"epsilon",
|
|
132
|
+
]:
|
|
133
|
+
print(f"Ignoring variable '{name}'")
|
|
134
|
+
return False
|
|
135
|
+
|
|
136
|
+
elif name in ["time", "wind_turbine"] and _read_multi_dimensional_coordinate(
|
|
137
|
+
name, wio_data, coords, fields, dims
|
|
138
|
+
):
|
|
139
|
+
return True
|
|
140
|
+
|
|
141
|
+
elif name in [
|
|
142
|
+
"wind_direction",
|
|
143
|
+
"wind_speed",
|
|
144
|
+
"x",
|
|
145
|
+
"y",
|
|
146
|
+
"height",
|
|
147
|
+
] and (
|
|
148
|
+
_read_multi_dimensional_coordinate(name, wio_data, coords, fields, dims)
|
|
149
|
+
or _read_multi_dimensional_data(name, wio_data, coords, fields, dims)
|
|
150
|
+
):
|
|
151
|
+
return True
|
|
152
|
+
|
|
153
|
+
elif name in [
|
|
154
|
+
"probability",
|
|
155
|
+
"sector_probability",
|
|
156
|
+
"turbulence_intensity",
|
|
157
|
+
"LMO",
|
|
158
|
+
"z0",
|
|
159
|
+
"k",
|
|
160
|
+
] and _read_multi_dimensional_data(name, wio_data, coords, fields, dims):
|
|
161
|
+
return True
|
|
162
|
+
|
|
163
|
+
else:
|
|
164
|
+
raise NotImplementedError(f"No reading method implemented for field '{name}'")
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from foxes.core import Algorithm
|
|
2
|
+
from foxes.output import Output
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class WindioRunner:
|
|
6
|
+
"""
|
|
7
|
+
Runner for windio input
|
|
8
|
+
|
|
9
|
+
Attributes
|
|
10
|
+
----------
|
|
11
|
+
algo: foxes.core.Algorithm
|
|
12
|
+
The algorithm object
|
|
13
|
+
output_dicts: list of dict
|
|
14
|
+
The output dictionaries
|
|
15
|
+
farm_results: xarray.Dataset
|
|
16
|
+
The farm results
|
|
17
|
+
output_results: list
|
|
18
|
+
The output results
|
|
19
|
+
verbosity: int
|
|
20
|
+
The verbosity level, 0 = silent
|
|
21
|
+
|
|
22
|
+
:group: input.windio
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, algo_dict, output_dicts=[], verbosity=1):
|
|
27
|
+
"""
|
|
28
|
+
Conbstructor
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
algo_dict: dict
|
|
33
|
+
The algorithm dictionary
|
|
34
|
+
output_dicts: list of dict
|
|
35
|
+
The output dictionaries
|
|
36
|
+
verbosity: int
|
|
37
|
+
The verbosity level, 0 = silent
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
self.algo = algo_dict
|
|
41
|
+
self.output_dicts = output_dicts
|
|
42
|
+
self.verbosity = verbosity
|
|
43
|
+
self.farm_results = None
|
|
44
|
+
self.output_results = None
|
|
45
|
+
|
|
46
|
+
self.__initialized = False
|
|
47
|
+
|
|
48
|
+
def print(self, *args, **kwargs):
|
|
49
|
+
"""Print based on verbosity"""
|
|
50
|
+
if self.verbosity > 0:
|
|
51
|
+
print(*args, **kwargs)
|
|
52
|
+
|
|
53
|
+
def initialize(self):
|
|
54
|
+
"""Initializes the runner"""
|
|
55
|
+
if isinstance(self.algo, dict):
|
|
56
|
+
self.print(f"Creating algorithm '{self.algo['algo_type']}'")
|
|
57
|
+
self.algo = Algorithm.new(**self.algo)
|
|
58
|
+
if not self.algo.initialized:
|
|
59
|
+
self.algo.initialize()
|
|
60
|
+
self.__initialized = True
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def initialized(self):
|
|
64
|
+
"""Flag for initialization"""
|
|
65
|
+
return self.__initialized
|
|
66
|
+
|
|
67
|
+
def run_farm_calc(self):
|
|
68
|
+
"""Runs the farm calculation"""
|
|
69
|
+
if not self.__initialized:
|
|
70
|
+
self.initialize()
|
|
71
|
+
print("Running farm_calc")
|
|
72
|
+
self.farm_results = self.algo.calc_farm()
|
|
73
|
+
|
|
74
|
+
def run_outputs(self):
|
|
75
|
+
"""Runs the output calculation"""
|
|
76
|
+
self.output_results = []
|
|
77
|
+
for odict in self.output_dicts:
|
|
78
|
+
self.print("Running output:", odict["output_type"])
|
|
79
|
+
run_fname = odict.pop("run_func")
|
|
80
|
+
run_args = odict.pop("run_args", ())
|
|
81
|
+
run_kwargs = odict.pop("run_kwargs", {})
|
|
82
|
+
o = Output.new(**odict)
|
|
83
|
+
f = getattr(o, run_fname)
|
|
84
|
+
self.output_results.append(f(*run_args, **run_kwargs))
|
|
85
|
+
|
|
86
|
+
def run(self):
|
|
87
|
+
"""Runs all calculations"""
|
|
88
|
+
self.run_farm_calc()
|
|
89
|
+
self.run_outputs()
|
|
90
|
+
|
|
91
|
+
def finalize(self):
|
|
92
|
+
"""Initializes the runner"""
|
|
93
|
+
if self.algo.initialized:
|
|
94
|
+
self.algo.finalize(clear_mem=True)
|
|
95
|
+
self.algo = None
|
|
96
|
+
self.farm_results = None
|
|
97
|
+
self.output_results = None
|
|
98
|
+
self.__initialized = False
|
|
99
|
+
|
|
100
|
+
def __enter__(self):
|
|
101
|
+
self.initialize()
|
|
102
|
+
return self
|
|
103
|
+
|
|
104
|
+
def __exit__(self, *args):
|
|
105
|
+
self.finalize()
|
foxes/input/windio/windio.py
CHANGED
|
@@ -1,285 +1,167 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import pandas as pd
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
|
|
4
|
-
from foxes.core import WindFarm
|
|
5
|
+
from foxes.core import WindFarm
|
|
5
6
|
from foxes.models import ModelBook
|
|
6
|
-
from foxes.
|
|
7
|
-
from foxes.
|
|
8
|
-
|
|
9
|
-
from
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
from foxes.utils import import_module, Dict
|
|
8
|
+
from foxes.data import StaticData, WINDIO
|
|
9
|
+
|
|
10
|
+
from .read_fields import read_wind_resource_field
|
|
11
|
+
from .get_states import get_states
|
|
12
|
+
from .read_farm import read_layout, read_turbine_type
|
|
13
|
+
from .read_attributes import read_attributes
|
|
14
|
+
from .runner import WindioRunner
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _read_site(wio, algo_dict, verbosity):
|
|
18
|
+
"""Reads the site information"""
|
|
19
|
+
wio_site = Dict(wio["site"], name="site")
|
|
20
|
+
if verbosity > 0:
|
|
21
|
+
print("Reading site")
|
|
22
|
+
print(" Name:", wio_site.pop("name", None))
|
|
23
|
+
print(" Contents:", [k for k in wio_site.keys()])
|
|
24
|
+
|
|
25
|
+
# ignore boundaries:
|
|
26
|
+
if verbosity > 1:
|
|
27
|
+
print(" Ignoring boundaries")
|
|
28
|
+
|
|
29
|
+
# read energy_resource:
|
|
30
|
+
energy_resource = Dict(wio_site["energy_resource"], name="energy_resource")
|
|
31
|
+
if verbosity > 1:
|
|
32
|
+
print(" Reading energy_resource")
|
|
33
|
+
print(" Name:", energy_resource.pop("name", None))
|
|
34
|
+
print(" Contents:", [k for k in energy_resource.keys()])
|
|
35
|
+
|
|
36
|
+
# read wind_resource:
|
|
37
|
+
wind_resource = Dict(energy_resource["wind_resource"], name="wind_resource")
|
|
38
|
+
if verbosity > 1:
|
|
39
|
+
print(" Reading wind_resource")
|
|
40
|
+
print(" Name:", wind_resource.pop("name", None))
|
|
41
|
+
print(" Contents:", [k for k in wind_resource.keys()])
|
|
42
|
+
|
|
43
|
+
# read fields
|
|
44
|
+
coords = Dict(name="coords")
|
|
45
|
+
fields = Dict(name="fields")
|
|
46
|
+
dims = Dict(name="dims")
|
|
47
|
+
for n, d in wind_resource.items():
|
|
48
|
+
if verbosity > 1:
|
|
49
|
+
print(" Reading", n)
|
|
50
|
+
read_wind_resource_field(n, d, coords, fields, dims)
|
|
51
|
+
if verbosity > 1:
|
|
52
|
+
print(" Coords:")
|
|
53
|
+
for c, d in coords.items():
|
|
54
|
+
print(f" {c}: Shape {d.shape}")
|
|
55
|
+
print(" Fields:")
|
|
56
|
+
for f, d in dims.items():
|
|
57
|
+
print(f" {f}: Dims {d}, shape {fields[f].shape}")
|
|
58
|
+
|
|
59
|
+
algo_dict["states"] = get_states(coords, fields, dims, verbosity)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _read_farm(wio, algo_dict, verbosity):
|
|
63
|
+
"""Reads the wind farm information"""
|
|
64
|
+
wio_farm = Dict(wio["wind_farm"], name="wind_farm")
|
|
65
|
+
if verbosity > 0:
|
|
66
|
+
print("Reading wind farm")
|
|
67
|
+
print(" Name:", wio_farm.pop("name", None))
|
|
68
|
+
print(" Contents:", [k for k in wio_farm.keys()])
|
|
69
|
+
|
|
70
|
+
# find REWS exponents:
|
|
71
|
+
try:
|
|
72
|
+
rotor_averaging = wio["attributes"]["analysis"]["rotor_averaging"]
|
|
73
|
+
ws_exp_P = rotor_averaging["wind_speed_exponent_for_power"]
|
|
74
|
+
ws_exp_ct = rotor_averaging["wind_speed_exponent_for_ct"]
|
|
75
|
+
except KeyError:
|
|
76
|
+
ws_exp_P = 1
|
|
77
|
+
ws_exp_ct = 1
|
|
78
|
+
|
|
79
|
+
# read turbine type:
|
|
80
|
+
turbines = Dict(wio_farm["turbines"], name="turbines")
|
|
81
|
+
ttype = read_turbine_type(turbines, algo_dict, ws_exp_P, ws_exp_ct, verbosity)
|
|
82
|
+
|
|
83
|
+
# read layouts:
|
|
84
|
+
layouts = Dict(wio_farm["layouts"], name="layouts")
|
|
85
|
+
if verbosity > 1:
|
|
86
|
+
print(" Reading layouts")
|
|
87
|
+
print(" Contents:", [k for k in layouts.keys()])
|
|
88
|
+
for lname, ldict in layouts.items():
|
|
89
|
+
read_layout(lname, ldict, algo_dict, ttype, verbosity)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def read_windio(windio_yaml, verbosity=1):
|
|
15
93
|
"""
|
|
16
|
-
Reads a WindIO
|
|
94
|
+
Reads a complete WindIO case.
|
|
17
95
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
res_yaml: str
|
|
21
|
-
Path to the yaml file
|
|
22
|
-
fixed_vars: dict
|
|
23
|
-
Additional fixes variables that do
|
|
24
|
-
not occur in the yaml
|
|
25
|
-
kwargs: dict, optional
|
|
26
|
-
Additional arguments for StatesTable
|
|
27
|
-
|
|
28
|
-
Returns
|
|
29
|
-
-------
|
|
30
|
-
states: foxes.states.StatesTable
|
|
31
|
-
The uniform states
|
|
32
|
-
|
|
33
|
-
"""
|
|
34
|
-
wres = res["wind_resource"]
|
|
35
|
-
|
|
36
|
-
wd = np.array(wres["wind_direction"], dtype=FC.DTYPE)
|
|
37
|
-
ws = np.array(wres["wind_speed"], dtype=FC.DTYPE)
|
|
38
|
-
n_wd = len(wd)
|
|
39
|
-
n_ws = len(ws)
|
|
40
|
-
n = n_wd * n_ws
|
|
41
|
-
|
|
42
|
-
data = np.zeros((n_wd, n_ws, 2), dtype=FC.DTYPE)
|
|
43
|
-
data[:, :, 0] = wd[:, None]
|
|
44
|
-
data[:, :, 1] = ws[None, :]
|
|
45
|
-
names = ["wind_direction", "wind_speed"]
|
|
46
|
-
sec_prob = None
|
|
47
|
-
|
|
48
|
-
def _to_data(v, d, dims):
|
|
49
|
-
nonlocal data, names, sec_prob
|
|
50
|
-
hdata = np.zeros((n_wd, n_ws, 1), dtype=FC.DTYPE)
|
|
51
|
-
if len(dims) == 0:
|
|
52
|
-
hdata[:, :, 0] = FC.DTYPE(d)
|
|
53
|
-
elif len(dims) == 1:
|
|
54
|
-
if dims[0] == "wind_direction":
|
|
55
|
-
hdata[:, :, 0] = np.array(d, dtype=FC.DTYPE)[:, None]
|
|
56
|
-
elif dims[0] == "wind_speed":
|
|
57
|
-
hdata[:, :, 0] = np.array(d, dtype=FC.DTYPE)[None, :]
|
|
58
|
-
else:
|
|
59
|
-
raise ValueError(f"Unknown dimension '{dims[0]}' for data '{v}'")
|
|
60
|
-
elif len(dims) == 2:
|
|
61
|
-
if dims[0] == "wind_direction" and dims[1] == "wind_speed":
|
|
62
|
-
hdata[:, :, 0] = np.array(d, dtype=FC.DTYPE)
|
|
63
|
-
elif dims[1] == "wind_direction" and dims[0] == "wind_speed":
|
|
64
|
-
hdata[:, :, 0] = np.swapaxes(np.array(d, dtype=FC.DTYPE), 0, 1)
|
|
65
|
-
else:
|
|
66
|
-
raise ValueError(f"Cannot handle dims = {dims} for data '{v}'")
|
|
67
|
-
else:
|
|
68
|
-
raise ValueError(
|
|
69
|
-
f"Can not accept more than two dimensions, got {dims} for data '{v}'"
|
|
70
|
-
)
|
|
71
|
-
if v == "sector_probability":
|
|
72
|
-
sec_prob = hdata[:, :, 0].copy()
|
|
73
|
-
else:
|
|
74
|
-
data = np.append(data, hdata, axis=2)
|
|
75
|
-
names.append(v)
|
|
76
|
-
|
|
77
|
-
vmap = {
|
|
78
|
-
"wind_direction": FV.WD,
|
|
79
|
-
"wind_speed": FV.WS,
|
|
80
|
-
"turbulence_intensity": FV.TI,
|
|
81
|
-
"air_density": FV.RHO,
|
|
82
|
-
"probability": FV.WEIGHT,
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
for v, d in wres.items():
|
|
86
|
-
if (v == "sector_probability" or v in vmap) and isinstance(d, dict):
|
|
87
|
-
_to_data(v, d["data"], d["dims"])
|
|
88
|
-
if sec_prob is not None and "probability" in names:
|
|
89
|
-
data[:, :, names.index("probability")] *= sec_prob
|
|
90
|
-
|
|
91
|
-
n_vars = len(names)
|
|
92
|
-
data = data.reshape(n, n_vars)
|
|
93
|
-
|
|
94
|
-
data = pd.DataFrame(index=range(n), data=data, columns=names)
|
|
95
|
-
data.index.name = "state"
|
|
96
|
-
data.rename(columns=vmap, inplace=True)
|
|
97
|
-
|
|
98
|
-
ovars = {v: v for v in data.columns if v != FV.WEIGHT}
|
|
99
|
-
ovars.update({k: v for k, v in fixed_vars.items() if k not in data.columns})
|
|
100
|
-
|
|
101
|
-
return StatesTable(data, output_vars=ovars, fixed_vars=fixed_vars, **kwargs)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def read_site(site, **kwargs):
|
|
105
|
-
"""
|
|
106
|
-
Reads a WindIO site
|
|
96
|
+
This is the main entry point for windio case
|
|
97
|
+
calculations.
|
|
107
98
|
|
|
108
99
|
Parameters
|
|
109
100
|
----------
|
|
110
|
-
|
|
111
|
-
Path to the yaml file
|
|
112
|
-
|
|
113
|
-
|
|
101
|
+
windio_yaml: str
|
|
102
|
+
Path to the windio yaml file
|
|
103
|
+
verbosity: int
|
|
104
|
+
The verbosity level, 0 = silent
|
|
114
105
|
|
|
115
106
|
Returns
|
|
116
107
|
-------
|
|
117
|
-
|
|
118
|
-
The
|
|
119
|
-
|
|
120
|
-
"""
|
|
121
|
-
res_yaml = site["energy_resource"]
|
|
122
|
-
states = read_resource(res_yaml, **kwargs)
|
|
123
|
-
|
|
124
|
-
return states
|
|
108
|
+
runner: foxes.input.windio.WindioRunner
|
|
109
|
+
The windio runner, call its run function
|
|
110
|
+
for the complete exection
|
|
125
111
|
|
|
112
|
+
:group: input.windio
|
|
126
113
|
|
|
127
|
-
def read_farm(fdict, mbook=None, layout=-1, turbine_models=[], **kwargs):
|
|
128
114
|
"""
|
|
129
|
-
Reads a WindIO wind farm
|
|
130
115
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
Path to the yaml file
|
|
135
|
-
mbook: foxes.ModelBook, optional
|
|
136
|
-
The model book to start from
|
|
137
|
-
layout: str or int
|
|
138
|
-
The layout choice
|
|
139
|
-
turbine_models: list of str
|
|
140
|
-
Additional turbine models
|
|
141
|
-
kwargs: dict, optional
|
|
142
|
-
Additional parameters for add_from_df()
|
|
116
|
+
wio_file = Path(windio_yaml)
|
|
117
|
+
if not wio_file.is_file():
|
|
118
|
+
wio_file = StaticData().get_file_path(WINDIO, wio_file, check_raw=False)
|
|
143
119
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
mbook: foxes.ModelBook
|
|
147
|
-
The model book
|
|
148
|
-
farm: foxes.WindFarm
|
|
149
|
-
The wind farm
|
|
120
|
+
if verbosity > 0:
|
|
121
|
+
print(f"Reading windio file {wio_file}")
|
|
150
122
|
|
|
151
|
-
"""
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
ldata.index.name = "index"
|
|
165
|
-
ldata["x"] = x
|
|
166
|
-
ldata["y"] = y
|
|
167
|
-
|
|
168
|
-
tdict = fdict["turbines"]
|
|
169
|
-
pdict = tdict["performance"]
|
|
170
|
-
|
|
171
|
-
ct_ws = np.array(pdict["Ct_curve"]["Ct_wind_speeds"], dtype=FC.DTYPE)
|
|
172
|
-
ct_data = pd.DataFrame(index=range(len(ct_ws)))
|
|
173
|
-
ct_data["ws"] = ct_ws
|
|
174
|
-
ct_data["ct"] = np.array(pdict["Ct_curve"]["Ct_values"], dtype=FC.DTYPE)
|
|
175
|
-
|
|
176
|
-
cp_ws = np.array(pdict["Cp_curve"]["Cp_wind_speeds"], dtype=FC.DTYPE)
|
|
177
|
-
cp_data = pd.DataFrame(index=range(len(cp_ws)))
|
|
178
|
-
cp_data["ws"] = cp_ws
|
|
179
|
-
cp_data["cp"] = np.array(pdict["Cp_curve"]["Cp_values"], dtype=FC.DTYPE)
|
|
180
|
-
|
|
181
|
-
D = float(tdict["rotor_diameter"])
|
|
182
|
-
H = float(tdict["hub_height"])
|
|
183
|
-
|
|
184
|
-
mbook.turbine_types["windio_turbine"] = CpCtFromTwo(
|
|
185
|
-
cp_data, ct_data, col_ws_cp_file="ws", col_cp="cp", D=D, H=H
|
|
123
|
+
yml_utils = import_module("windIO.utils.yml_utils", hint="pip install windio")
|
|
124
|
+
wio = yml_utils.load_yaml(wio_file)
|
|
125
|
+
|
|
126
|
+
if verbosity > 0:
|
|
127
|
+
print(" Name:", wio.pop("name", None))
|
|
128
|
+
print(" Contents:", [k for k in wio.keys()])
|
|
129
|
+
|
|
130
|
+
algo_dict = Dict(
|
|
131
|
+
algo_type="Downwind",
|
|
132
|
+
mbook=ModelBook(),
|
|
133
|
+
farm=WindFarm(),
|
|
134
|
+
wake_models=[],
|
|
135
|
+
verbosity=verbosity - 1,
|
|
186
136
|
)
|
|
187
137
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
def read_anlyses(
|
|
197
|
-
analyses, mbook, farm, states, keymap={}, algo_type="Downwind", **algo_pars
|
|
198
|
-
):
|
|
199
|
-
"""
|
|
200
|
-
Reads a WindIO wind farm
|
|
201
|
-
|
|
202
|
-
Parameters
|
|
203
|
-
----------
|
|
204
|
-
analyses: dict
|
|
205
|
-
The analyses sub-dict of the case
|
|
206
|
-
mbook: foxes.ModelBook
|
|
207
|
-
The model book
|
|
208
|
-
farm: foxes.WindFarm
|
|
209
|
-
The wind farm
|
|
210
|
-
states: foxes.states.States
|
|
211
|
-
The states object
|
|
212
|
-
keymap: dict
|
|
213
|
-
Translation from windio to foxes keywords
|
|
214
|
-
algo_type: str
|
|
215
|
-
The default algorithm class name
|
|
216
|
-
algo_pars: dict, optional
|
|
217
|
-
Additional parameters for the algorithm
|
|
218
|
-
constructor
|
|
219
|
-
|
|
220
|
-
Returns
|
|
221
|
-
-------
|
|
222
|
-
algo: foxes.core.Algorithm
|
|
223
|
-
The algorithm
|
|
224
|
-
|
|
225
|
-
"""
|
|
226
|
-
wmodel = analyses["wake_model"]["name"]
|
|
227
|
-
wmodels = [keymap.get(wmodel, wmodel)]
|
|
228
|
-
|
|
229
|
-
return Algorithm.new(
|
|
230
|
-
algo_type, mbook, farm, states, wake_models=wmodels, **algo_pars
|
|
138
|
+
_read_site(wio, algo_dict, verbosity)
|
|
139
|
+
_read_farm(wio, algo_dict, verbosity)
|
|
140
|
+
out_dicts = read_attributes(
|
|
141
|
+
wio,
|
|
142
|
+
algo_dict,
|
|
143
|
+
verbosity,
|
|
231
144
|
)
|
|
232
145
|
|
|
146
|
+
if verbosity > 0:
|
|
147
|
+
print("Creating windio runner")
|
|
148
|
+
runner = WindioRunner(algo_dict, output_dicts=out_dicts, verbosity=verbosity)
|
|
233
149
|
|
|
234
|
-
|
|
235
|
-
"""
|
|
236
|
-
Reads a WindIO case
|
|
237
|
-
|
|
238
|
-
Parameters
|
|
239
|
-
----------
|
|
240
|
-
case_yaml: str
|
|
241
|
-
Path to the yaml file
|
|
242
|
-
site_pars: dict
|
|
243
|
-
Additional arguments for read_site
|
|
244
|
-
farm_pars: dict
|
|
245
|
-
Additional arguments for read_farm
|
|
246
|
-
ana_pars: dict
|
|
247
|
-
Additional arguments for read_analyses
|
|
248
|
-
|
|
249
|
-
Returns
|
|
250
|
-
-------
|
|
251
|
-
mbook: foxes.ModelBook
|
|
252
|
-
The model book
|
|
253
|
-
farm: foxes.WindFarm
|
|
254
|
-
The wind farm
|
|
255
|
-
states: foxes.states.States
|
|
256
|
-
The states object
|
|
257
|
-
algo: foxes.core.Algorithm
|
|
258
|
-
The algorithm
|
|
259
|
-
|
|
260
|
-
:group: input.windio
|
|
261
|
-
|
|
262
|
-
"""
|
|
263
|
-
yml_utils = import_module("windIO.utils.yml_utils", hint="pip install windio")
|
|
264
|
-
case = yml_utils.load_yaml(case_yaml)
|
|
265
|
-
|
|
266
|
-
site_yaml = case["site"]
|
|
267
|
-
states = read_site(site_yaml, **site_pars)
|
|
268
|
-
|
|
269
|
-
farm_yaml = case["wind_farm"]
|
|
270
|
-
mbook, farm = read_farm(farm_yaml, **farm_pars)
|
|
271
|
-
|
|
272
|
-
attr_dict = case["attributes"]
|
|
273
|
-
algo = read_anlyses(attr_dict["analyses"], mbook, farm, states, **ana_pars)
|
|
274
|
-
|
|
275
|
-
return mbook, farm, states, algo
|
|
150
|
+
return runner
|
|
276
151
|
|
|
277
152
|
|
|
278
153
|
if __name__ == "__main__":
|
|
279
154
|
import argparse
|
|
280
155
|
|
|
281
156
|
parser = argparse.ArgumentParser()
|
|
282
|
-
parser.add_argument(
|
|
157
|
+
parser.add_argument(
|
|
158
|
+
"-f",
|
|
159
|
+
"--file",
|
|
160
|
+
help="The windio yaml file",
|
|
161
|
+
default="windio_5turbines_timeseries.yaml",
|
|
162
|
+
)
|
|
283
163
|
args = parser.parse_args()
|
|
284
164
|
|
|
285
|
-
|
|
165
|
+
runner = read_windio(args.file)
|
|
166
|
+
|
|
167
|
+
runner.run()
|
foxes/models/__init__.py
CHANGED