foxes 0.7.2__py3-none-any.whl → 0.7.3__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.

Files changed (60) hide show
  1. foxes/VERSION +1 -1
  2. foxes/algorithms/downwind/downwind.py +57 -45
  3. foxes/algorithms/downwind/models/farm_wakes_calc.py +17 -6
  4. foxes/algorithms/downwind/models/point_wakes_calc.py +13 -45
  5. foxes/algorithms/iterative/iterative.py +1 -1
  6. foxes/algorithms/iterative/models/farm_wakes_calc.py +18 -4
  7. foxes/constants.py +5 -0
  8. foxes/core/__init__.py +2 -1
  9. foxes/core/ground_model.py +254 -0
  10. foxes/core/model.py +3 -2
  11. foxes/core/partial_wakes_model.py +19 -3
  12. foxes/core/states.py +33 -0
  13. foxes/core/wake_model.py +138 -2
  14. foxes/data/__init__.py +1 -1
  15. foxes/data/states/WRF-Timeseries-3000.nc +0 -0
  16. foxes/data/states/windio_timeseries_5000.nc +0 -0
  17. foxes/data/static_data.py +7 -0
  18. foxes/data/windio/DTU_10MW_turbine.yaml +10 -0
  19. foxes/data/windio/__init__.py +0 -0
  20. foxes/data/windio/windio_5turbines_timeseries.yaml +63 -0
  21. foxes/input/states/__init__.py +1 -0
  22. foxes/input/states/multi_height.py +225 -6
  23. foxes/input/windio/__init__.py +6 -1
  24. foxes/input/windio/get_states.py +115 -0
  25. foxes/input/windio/read_attributes.py +321 -0
  26. foxes/input/windio/read_farm.py +163 -0
  27. foxes/input/windio/read_fields.py +164 -0
  28. foxes/input/windio/runner.py +105 -0
  29. foxes/input/windio/windio.py +136 -254
  30. foxes/models/__init__.py +1 -0
  31. foxes/models/ground_models/__init__.py +2 -0
  32. foxes/models/ground_models/no_ground.py +12 -0
  33. foxes/models/ground_models/wake_mirror.py +161 -0
  34. foxes/models/model_book.py +68 -149
  35. foxes/models/partial_wakes/axiwake.py +27 -4
  36. foxes/models/partial_wakes/top_hat.py +26 -4
  37. foxes/models/turbine_types/PCt_file.py +1 -0
  38. foxes/models/turbine_types/PCt_from_two.py +92 -0
  39. foxes/models/wake_frames/yawed_wakes.py +41 -38
  40. foxes/models/wake_models/__init__.py +0 -1
  41. foxes/models/wake_models/induction/__init__.py +1 -0
  42. foxes/models/wake_models/induction/rankine_half_body.py +1 -1
  43. foxes/models/wake_models/induction/vortex_sheet.py +227 -0
  44. foxes/models/wake_models/ti/crespo_hernandez.py +26 -24
  45. foxes/models/wake_models/ti/iec_ti.py +33 -26
  46. foxes/models/wake_models/wind/bastankhah14.py +11 -32
  47. foxes/models/wake_models/wind/bastankhah16.py +30 -34
  48. foxes/models/wake_models/wind/jensen.py +13 -29
  49. foxes/models/wake_models/wind/turbopark.py +31 -61
  50. foxes/output/grids.py +6 -6
  51. foxes/output/output.py +6 -6
  52. foxes/utils/__init__.py +1 -1
  53. foxes/utils/factory.py +203 -11
  54. {foxes-0.7.2.dist-info → foxes-0.7.3.dist-info}/METADATA +8 -6
  55. {foxes-0.7.2.dist-info → foxes-0.7.3.dist-info}/RECORD +59 -45
  56. {foxes-0.7.2.dist-info → foxes-0.7.3.dist-info}/WHEEL +1 -1
  57. foxes/models/wake_models/wake_mirror.py +0 -196
  58. {foxes-0.7.2.dist-info → foxes-0.7.3.dist-info}/LICENSE +0 -0
  59. {foxes-0.7.2.dist-info → foxes-0.7.3.dist-info}/top_level.txt +0 -0
  60. {foxes-0.7.2.dist-info → foxes-0.7.3.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()
@@ -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, Algorithm
5
+ from foxes.core import WindFarm
5
6
  from foxes.models import ModelBook
6
- from foxes.input.states import StatesTable
7
- from foxes.input.farm_layout import add_from_df
8
- from foxes.models.turbine_types import CpCtFromTwo
9
- from foxes.utils import import_module
10
- import foxes.constants as FC
11
- import foxes.variables as FV
12
-
13
-
14
- def read_resource(res, fixed_vars={}, **kwargs):
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 energy resource
94
+ Reads a complete WindIO case.
17
95
 
18
- Parameters
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
- site_yaml: str
111
- Path to the yaml file
112
- kwargs: dict, optional
113
- Additional arguments for read_resource
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
- states: foxes.states.States
118
- The states object
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
- Parameters
132
- ----------
133
- farm_yaml: str
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
- Returns
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
- mbook = ModelBook() if mbook is None else mbook
153
-
154
- if isinstance(layout, str):
155
- layout = fdict["layouts"][layout]
156
- else:
157
- lname = list(fdict["layouts"].keys())[layout]
158
- layout = fdict["layouts"][lname]
159
-
160
- x = np.array(layout["coordinates"]["x"], dtype=FC.DTYPE)
161
- y = np.array(layout["coordinates"]["y"], dtype=FC.DTYPE)
162
- N = len(x)
163
- ldata = pd.DataFrame(index=range(N))
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
- models = ["windio_turbine"] + turbine_models
189
- farm = WindFarm(name=fdict["name"])
190
-
191
- add_from_df(farm, ldata, col_x="x", col_y="y", turbine_models=models, **kwargs)
192
-
193
- return mbook, farm
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
- def read_case(case_yaml, site_pars={}, farm_pars={}, ana_pars={}):
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("case_yaml", help="The case yaml file")
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
- read_case(args.case_yaml)
165
+ runner = read_windio(args.file)
166
+
167
+ runner.run()
foxes/models/__init__.py CHANGED
@@ -14,5 +14,6 @@ from . import farm_controllers
14
14
  from . import vertical_profiles
15
15
  from . import point_models
16
16
  from . import axial_induction
17
+ from . import ground_models
17
18
 
18
19
  from .model_book import ModelBook
@@ -0,0 +1,2 @@
1
+ from .no_ground import NoGround
2
+ from .wake_mirror import WakeMirror, GroundMirror