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
foxes/core/states.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
|
|
3
3
|
from .point_data_model import PointDataModel, PointDataModelList
|
|
4
|
+
from foxes.utils import all_subclasses
|
|
4
5
|
import foxes.variables as FV
|
|
5
6
|
import foxes.constants as FC
|
|
6
7
|
|
|
@@ -131,6 +132,38 @@ class States(PointDataModel):
|
|
|
131
132
|
else:
|
|
132
133
|
return ExtendedStates(self, [s])
|
|
133
134
|
|
|
135
|
+
@classmethod
|
|
136
|
+
def new(cls, states_type, *args, **kwargs):
|
|
137
|
+
"""
|
|
138
|
+
Run-time states factory.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
states_type: str
|
|
143
|
+
The selected derived class name
|
|
144
|
+
args: tuple, optional
|
|
145
|
+
Additional parameters for constructor
|
|
146
|
+
kwargs: dict, optional
|
|
147
|
+
Additional parameters for constructor
|
|
148
|
+
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
if states_type is None:
|
|
152
|
+
return None
|
|
153
|
+
|
|
154
|
+
allc = all_subclasses(cls)
|
|
155
|
+
found = states_type in [scls.__name__ for scls in allc]
|
|
156
|
+
|
|
157
|
+
if found:
|
|
158
|
+
for scls in allc:
|
|
159
|
+
if scls.__name__ == states_type:
|
|
160
|
+
return scls(*args, **kwargs)
|
|
161
|
+
else:
|
|
162
|
+
estr = "States type '{}' is not defined, available types are \n {}".format(
|
|
163
|
+
states_type, sorted([i.__name__ for i in allc])
|
|
164
|
+
)
|
|
165
|
+
raise KeyError(estr)
|
|
166
|
+
|
|
134
167
|
|
|
135
168
|
class ExtendedStates(States):
|
|
136
169
|
"""
|
foxes/core/wake_model.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
import numpy as np
|
|
3
3
|
|
|
4
|
-
from foxes.utils import all_subclasses
|
|
4
|
+
from foxes.utils import all_subclasses, Factory
|
|
5
5
|
import foxes.variables as FV
|
|
6
6
|
import foxes.constants as FC
|
|
7
7
|
|
|
@@ -49,7 +49,7 @@ class WakeModel(Model):
|
|
|
49
49
|
-------
|
|
50
50
|
wake_deltas: dict
|
|
51
51
|
Key: variable name, value: The zero filled
|
|
52
|
-
wake deltas, shape: (n_states,
|
|
52
|
+
wake deltas, shape: (n_states, n_targets, n_tpoints, ...)
|
|
53
53
|
|
|
54
54
|
"""
|
|
55
55
|
return {FV.WS: np.zeros_like(tdata[FC.TARGETS][..., 0])}
|
|
@@ -183,3 +183,139 @@ class TurbineInductionModel(WakeModel):
|
|
|
183
183
|
|
|
184
184
|
"""
|
|
185
185
|
return False
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class WakeK(Model):
|
|
189
|
+
"""
|
|
190
|
+
Handler for the wake growth parameter k
|
|
191
|
+
|
|
192
|
+
Attributes
|
|
193
|
+
----------
|
|
194
|
+
k_var: str
|
|
195
|
+
The name of the k variable
|
|
196
|
+
ti_var: str
|
|
197
|
+
The name of the TI variable
|
|
198
|
+
|
|
199
|
+
:group: core
|
|
200
|
+
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
def __init__(
|
|
204
|
+
self,
|
|
205
|
+
k=None,
|
|
206
|
+
ka=None,
|
|
207
|
+
kb=None,
|
|
208
|
+
k_var=FV.K,
|
|
209
|
+
ti_var=FV.TI,
|
|
210
|
+
):
|
|
211
|
+
"""
|
|
212
|
+
Constructor.
|
|
213
|
+
|
|
214
|
+
Parameters
|
|
215
|
+
----------
|
|
216
|
+
k: float, optional
|
|
217
|
+
The k value
|
|
218
|
+
ka: float, optional
|
|
219
|
+
The ka value in k = ka * TI + kb
|
|
220
|
+
kb: float, optional
|
|
221
|
+
The kb value in k = ka * TI + kb
|
|
222
|
+
k_var: str
|
|
223
|
+
The name of the k variable
|
|
224
|
+
ti_var: str
|
|
225
|
+
The name of the TI variable
|
|
226
|
+
|
|
227
|
+
"""
|
|
228
|
+
super().__init__()
|
|
229
|
+
self._k = k
|
|
230
|
+
self._ka = ka
|
|
231
|
+
self._kb = kb
|
|
232
|
+
self.k_var = k_var
|
|
233
|
+
self.ti_var = ti_var
|
|
234
|
+
|
|
235
|
+
if k is not None and (ka is not None or kb is not None):
|
|
236
|
+
raise ValueError("Got 'k' and also ('ka' or 'kb') as non-None parameters")
|
|
237
|
+
elif k is None and kb is not None and (ka is None or ka == 0):
|
|
238
|
+
raise ValueError(f"Got k={k}, ka={ka}, kb={kb}, use k={kb} instead")
|
|
239
|
+
|
|
240
|
+
setattr(self, self.k_var, None)
|
|
241
|
+
|
|
242
|
+
def repr(self):
|
|
243
|
+
"""
|
|
244
|
+
Provides the representative string
|
|
245
|
+
|
|
246
|
+
Returns
|
|
247
|
+
-------
|
|
248
|
+
s: str
|
|
249
|
+
The representative string
|
|
250
|
+
|
|
251
|
+
"""
|
|
252
|
+
if self._k is not None:
|
|
253
|
+
s = f"{self.k_var}={self._k}"
|
|
254
|
+
elif self._ka is not None or self._kb is not None:
|
|
255
|
+
s = f"{self.k_var}={self._ka}*{self.ti_var}"
|
|
256
|
+
if self._kb is not None and self._kb > 0:
|
|
257
|
+
s += f"+{self._kb}"
|
|
258
|
+
else:
|
|
259
|
+
s = f"k_var={self.k_var}"
|
|
260
|
+
return s
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def all_none(self):
|
|
264
|
+
"""Flag for k=ka=kb=None"""
|
|
265
|
+
return self._k is None and self._ka is None and self._kb is None
|
|
266
|
+
|
|
267
|
+
@property
|
|
268
|
+
def use_amb_ti(self):
|
|
269
|
+
"""Flag for using ambient ti"""
|
|
270
|
+
return self.ti_var in FV.amb2var
|
|
271
|
+
|
|
272
|
+
def __call__(
|
|
273
|
+
self,
|
|
274
|
+
*args,
|
|
275
|
+
lookup_ti="w",
|
|
276
|
+
lookup_k="sw",
|
|
277
|
+
ti=None,
|
|
278
|
+
amb_ti=None,
|
|
279
|
+
**kwargs,
|
|
280
|
+
):
|
|
281
|
+
"""
|
|
282
|
+
Gets the k value
|
|
283
|
+
|
|
284
|
+
Parameters
|
|
285
|
+
----------
|
|
286
|
+
args: tuple, optional
|
|
287
|
+
Arguments for get_data
|
|
288
|
+
lookup_ti: str
|
|
289
|
+
The ti lookup order for get_data
|
|
290
|
+
lookup_k: str
|
|
291
|
+
The k lookup order for get_data
|
|
292
|
+
ti: numpy.ndarray, optional
|
|
293
|
+
ti data in the requested target shape,
|
|
294
|
+
if known
|
|
295
|
+
amb_ti: numpy.ndarray, optional
|
|
296
|
+
Ambient ti data in the requested target shape,
|
|
297
|
+
if known
|
|
298
|
+
kwargs: dict, optional
|
|
299
|
+
Arguments for get_data
|
|
300
|
+
|
|
301
|
+
Returns
|
|
302
|
+
-------
|
|
303
|
+
k: numpy.ndarray
|
|
304
|
+
The k array as returned by get_data
|
|
305
|
+
|
|
306
|
+
"""
|
|
307
|
+
if self._k is not None:
|
|
308
|
+
setattr(self, self.k_var, self._k)
|
|
309
|
+
elif self._ka is not None or self._kb is not None:
|
|
310
|
+
if self.ti_var == FV.TI and ti is not None:
|
|
311
|
+
pass
|
|
312
|
+
elif self.ti_var == FV.AMB_TI and amb_ti is not None:
|
|
313
|
+
ti = amb_ti
|
|
314
|
+
else:
|
|
315
|
+
ti = self.get_data(self.ti_var, *args, lookup=lookup_ti, **kwargs)
|
|
316
|
+
kb = 0 if self._kb is None else self._kb
|
|
317
|
+
setattr(self, self.k_var, self._ka * ti + kb)
|
|
318
|
+
|
|
319
|
+
k = self.get_data(self.k_var, *args, lookup=lookup_k, **kwargs)
|
|
320
|
+
setattr(self, self.k_var, None)
|
|
321
|
+
return k
|
foxes/data/__init__.py
CHANGED
|
Binary file
|
|
Binary file
|
foxes/data/static_data.py
CHANGED
|
@@ -3,6 +3,7 @@ from foxes.utils import DataBook
|
|
|
3
3
|
from . import farms
|
|
4
4
|
from . import states
|
|
5
5
|
from . import power_ct_curves
|
|
6
|
+
from . import windio
|
|
6
7
|
|
|
7
8
|
FARM = "farm"
|
|
8
9
|
""" Static wind farm data identifier
|
|
@@ -19,6 +20,11 @@ PCTCURVE = "power_ct_curve"
|
|
|
19
20
|
:group: data
|
|
20
21
|
"""
|
|
21
22
|
|
|
23
|
+
WINDIO = "windio"
|
|
24
|
+
""" Static windio data identifier
|
|
25
|
+
:group: data
|
|
26
|
+
"""
|
|
27
|
+
|
|
22
28
|
|
|
23
29
|
class StaticData(DataBook):
|
|
24
30
|
"""
|
|
@@ -35,3 +41,4 @@ class StaticData(DataBook):
|
|
|
35
41
|
self.add_data_package(FARM, farms, ".csv")
|
|
36
42
|
self.add_data_package(STATES, states, [".csv", ".csv.gz", ".nc", ".tab"])
|
|
37
43
|
self.add_data_package(PCTCURVE, power_ct_curves, ".csv")
|
|
44
|
+
self.add_data_package(WINDIO, windio, ".yaml")
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
name: DTU 10MW Offshore Reference Turbine
|
|
2
|
+
performance:
|
|
3
|
+
power_curve:
|
|
4
|
+
power_values: [263388., 751154., 1440738., 2355734., 3506858., 4993092., 6849310., 9116402., 10000754., 10009590., 10000942., 10042678., 10003480., 10001600., 10001506., 10013632., 10007428., 10005360., 10002728., 10001130., 10004984., 9997558.]
|
|
5
|
+
power_wind_speeds: [4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,16.,17.,18.,19.,20.,21.,22.,23.,24.,25.]
|
|
6
|
+
Ct_curve:
|
|
7
|
+
Ct_values: [0.923,0.919,0.904,0.858,0.814,0.814,0.814,0.814,0.577,0.419,0.323,0.259,0.211,0.175,0.148,0.126,0.109,0.095,0.084,0.074,0.066,0.059]
|
|
8
|
+
Ct_wind_speeds: [4.,5.,6.,7.,8.,9.,10.,11.,12.,13.,14.,15.,16.,17.,18.,19.,20.,21.,22.,23.,24.,25.]
|
|
9
|
+
hub_height: 119.0
|
|
10
|
+
rotor_diameter: 178.3
|
|
File without changes
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: 5 turbines and a wind timeseries
|
|
2
|
+
|
|
3
|
+
site:
|
|
4
|
+
name: Site with wind timeseries data
|
|
5
|
+
boundaries:
|
|
6
|
+
polygons: [
|
|
7
|
+
x: [-10, -10, 1610, 1610],
|
|
8
|
+
y: [-10, 10, 10, -10]
|
|
9
|
+
]
|
|
10
|
+
energy_resource:
|
|
11
|
+
name: NetCDF timeseries with 5000 states
|
|
12
|
+
wind_resource: !include ../states/windio_timeseries_5000.nc
|
|
13
|
+
|
|
14
|
+
wind_farm:
|
|
15
|
+
name: One row with 5 turbines
|
|
16
|
+
layouts:
|
|
17
|
+
initial_layout:
|
|
18
|
+
coordinates:
|
|
19
|
+
x: [0, 0, 0, 0, 0]
|
|
20
|
+
y: [0, 600, 1150, 1730, 2400]
|
|
21
|
+
turbines: !include DTU_10MW_turbine.yaml
|
|
22
|
+
|
|
23
|
+
attributes:
|
|
24
|
+
flow_model:
|
|
25
|
+
name: foxes
|
|
26
|
+
|
|
27
|
+
analysis:
|
|
28
|
+
|
|
29
|
+
wind_deficit_model:
|
|
30
|
+
name: Bastankhah2014
|
|
31
|
+
wake_expansion_coefficient: # k = ka*ti + kb
|
|
32
|
+
k_a: 0.04
|
|
33
|
+
k_b: 0.0
|
|
34
|
+
free_stream_ti: false
|
|
35
|
+
ceps: 0.2
|
|
36
|
+
use_effective_ws: true
|
|
37
|
+
|
|
38
|
+
axial_induction_model: Madsen
|
|
39
|
+
|
|
40
|
+
deflection_model:
|
|
41
|
+
name: None
|
|
42
|
+
|
|
43
|
+
turbulence_model:
|
|
44
|
+
name: CrespoHernandez
|
|
45
|
+
|
|
46
|
+
superposition_model:
|
|
47
|
+
ws_superposition: Linear
|
|
48
|
+
ti_superposition: Quadratic
|
|
49
|
+
|
|
50
|
+
rotor_averaging:
|
|
51
|
+
grid: grid
|
|
52
|
+
n_x_grid_points: 4
|
|
53
|
+
n_y_grid_points: 4
|
|
54
|
+
background_averaging: grid
|
|
55
|
+
wake_averaging: axiwake9
|
|
56
|
+
wind_speed_exponent_for_power: 3
|
|
57
|
+
wind_speed_exponent_for_ct: 2
|
|
58
|
+
|
|
59
|
+
blockage_model:
|
|
60
|
+
name: None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
foxes/input/states/__init__.py
CHANGED
|
@@ -7,5 +7,6 @@ from .scan_ws import ScanWS
|
|
|
7
7
|
from .states_table import StatesTable, Timeseries, TabStates
|
|
8
8
|
from .field_data_nc import FieldDataNC
|
|
9
9
|
from .multi_height import MultiHeightStates, MultiHeightTimeseries
|
|
10
|
+
from .multi_height import MultiHeightNCStates, MultiHeightNCTimeseries
|
|
10
11
|
|
|
11
12
|
from . import create
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import pandas as pd
|
|
3
|
+
from xarray import Dataset, open_dataset
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from scipy.interpolate import interp1d
|
|
5
6
|
|
|
@@ -100,7 +101,6 @@ class MultiHeightStates(States):
|
|
|
100
101
|
self.states_sel = states_sel
|
|
101
102
|
self.states_loc = states_loc
|
|
102
103
|
|
|
103
|
-
self._cmap = None
|
|
104
104
|
self._solo = None
|
|
105
105
|
self._weights = None
|
|
106
106
|
self._N = None
|
|
@@ -217,14 +217,14 @@ class MultiHeightStates(States):
|
|
|
217
217
|
data[col_w] = self._weights[:, 0]
|
|
218
218
|
|
|
219
219
|
cols = []
|
|
220
|
-
|
|
220
|
+
cmap = {}
|
|
221
221
|
self._solo = {}
|
|
222
222
|
for v in self.ovars:
|
|
223
223
|
vcols = self._find_cols(v, data.columns)
|
|
224
224
|
if len(vcols) == 1:
|
|
225
225
|
self._solo[v] = data[vcols[0]].to_numpy()
|
|
226
226
|
elif len(vcols) > 1:
|
|
227
|
-
|
|
227
|
+
cmap[v] = (len(cols), len(cols) + len(vcols))
|
|
228
228
|
cols += vcols
|
|
229
229
|
data = data[cols]
|
|
230
230
|
|
|
@@ -235,7 +235,7 @@ class MultiHeightStates(States):
|
|
|
235
235
|
idata = super().load_data(algo, verbosity)
|
|
236
236
|
|
|
237
237
|
idata["coords"][self.H] = self.heights
|
|
238
|
-
idata["coords"][self.VARS] = list(
|
|
238
|
+
idata["coords"][self.VARS] = list(cmap.keys())
|
|
239
239
|
|
|
240
240
|
n_hts = len(self.heights)
|
|
241
241
|
n_vrs = int(len(data.columns) / n_hts)
|
|
@@ -247,6 +247,7 @@ class MultiHeightStates(States):
|
|
|
247
247
|
|
|
248
248
|
for v, d in self._solo.items():
|
|
249
249
|
idata["data_vars"][self.var(v)] = ((FC.STATE,), d)
|
|
250
|
+
self._solo = list(self._solo.keys())
|
|
250
251
|
|
|
251
252
|
return idata
|
|
252
253
|
|
|
@@ -387,7 +388,7 @@ class MultiHeightStates(States):
|
|
|
387
388
|
elif v in self.fixed_vars:
|
|
388
389
|
results[v] = np.zeros((n_states, n_targets, n_tpoints), dtype=FC.DTYPE)
|
|
389
390
|
results[v][:] = self.fixed_vars[v]
|
|
390
|
-
elif v in self._solo
|
|
391
|
+
elif v in self._solo:
|
|
391
392
|
results[v] = np.zeros((n_states, n_targets, n_tpoints), dtype=FC.DTYPE)
|
|
392
393
|
results[v][:] = mdata[self.var(v)][:, None, None]
|
|
393
394
|
else:
|
|
@@ -408,12 +409,200 @@ class MultiHeightStates(States):
|
|
|
408
409
|
|
|
409
410
|
"""
|
|
410
411
|
super().finalize(algo, verbosity)
|
|
411
|
-
self._cmap = None
|
|
412
412
|
self._solo = None
|
|
413
413
|
self._weights = None
|
|
414
414
|
self._N = None
|
|
415
415
|
|
|
416
416
|
|
|
417
|
+
class MultiHeightNCStates(MultiHeightStates):
|
|
418
|
+
"""
|
|
419
|
+
Multi-height states from xarray Dataset.
|
|
420
|
+
|
|
421
|
+
Attributes
|
|
422
|
+
----------
|
|
423
|
+
data_source: str or xarray.Dataset
|
|
424
|
+
Either path to a file or data
|
|
425
|
+
state_coord: str
|
|
426
|
+
Name of the state coordinate
|
|
427
|
+
h_coord: str
|
|
428
|
+
Name of the height coordinate
|
|
429
|
+
xr_read_pars: dict
|
|
430
|
+
Parameters for xarray.open_dataset
|
|
431
|
+
|
|
432
|
+
:group: input.states
|
|
433
|
+
|
|
434
|
+
"""
|
|
435
|
+
|
|
436
|
+
def __init__(
|
|
437
|
+
self,
|
|
438
|
+
data_source,
|
|
439
|
+
*args,
|
|
440
|
+
state_coord=FC.STATE,
|
|
441
|
+
h_coord=FV.H,
|
|
442
|
+
heights=None,
|
|
443
|
+
format_times_func="default",
|
|
444
|
+
xr_read_pars={},
|
|
445
|
+
**kwargs,
|
|
446
|
+
):
|
|
447
|
+
"""
|
|
448
|
+
Constructor.
|
|
449
|
+
|
|
450
|
+
Parameters
|
|
451
|
+
----------
|
|
452
|
+
data_source: str or pandas.DataFrame
|
|
453
|
+
Either path to a file or data
|
|
454
|
+
args: tuple, optional
|
|
455
|
+
Parameters for the base class
|
|
456
|
+
state_coord: str
|
|
457
|
+
Name of the state coordinate
|
|
458
|
+
h_coord: str
|
|
459
|
+
Name of the height coordinate
|
|
460
|
+
output_vars: list of str
|
|
461
|
+
The output variables
|
|
462
|
+
heights: list of float, optional
|
|
463
|
+
The heights at which to search data
|
|
464
|
+
format_times_func: Function or 'default', optional
|
|
465
|
+
The function that maps state_coord values
|
|
466
|
+
to datetime dtype format
|
|
467
|
+
xr_read_pars: dict, optional
|
|
468
|
+
Parameters for xarray.open_dataset
|
|
469
|
+
kwargs: dict, optional
|
|
470
|
+
Parameters for the base class
|
|
471
|
+
|
|
472
|
+
"""
|
|
473
|
+
super().__init__(
|
|
474
|
+
data_source,
|
|
475
|
+
*args,
|
|
476
|
+
heights=[],
|
|
477
|
+
pd_read_pars=None,
|
|
478
|
+
**kwargs,
|
|
479
|
+
)
|
|
480
|
+
self.state_coord = state_coord
|
|
481
|
+
self.heights = heights
|
|
482
|
+
self.h_coord = h_coord
|
|
483
|
+
self.xr_read_pars = xr_read_pars
|
|
484
|
+
|
|
485
|
+
if format_times_func == "default":
|
|
486
|
+
self.format_times_func = lambda t: t.astype("datetime64[ns]")
|
|
487
|
+
else:
|
|
488
|
+
self.format_times_func = format_times_func
|
|
489
|
+
|
|
490
|
+
def load_data(self, algo, verbosity=0):
|
|
491
|
+
"""
|
|
492
|
+
Load and/or create all model data that is subject to chunking.
|
|
493
|
+
|
|
494
|
+
Such data should not be stored under self, for memory reasons. The
|
|
495
|
+
data returned here will automatically be chunked and then provided
|
|
496
|
+
as part of the mdata object during calculations.
|
|
497
|
+
|
|
498
|
+
Parameters
|
|
499
|
+
----------
|
|
500
|
+
algo: foxes.core.Algorithm
|
|
501
|
+
The calculation algorithm
|
|
502
|
+
verbosity: int
|
|
503
|
+
The verbosity level, 0 = silent
|
|
504
|
+
|
|
505
|
+
Returns
|
|
506
|
+
-------
|
|
507
|
+
idata: dict
|
|
508
|
+
The dict has exactly two entries: `data_vars`,
|
|
509
|
+
a dict with entries `name_str -> (dim_tuple, data_ndarray)`;
|
|
510
|
+
and `coords`, a dict with entries `dim_name_str -> dim_array`
|
|
511
|
+
|
|
512
|
+
"""
|
|
513
|
+
if not isinstance(self.data_source, Dataset):
|
|
514
|
+
if not Path(self.data_source).is_file():
|
|
515
|
+
if verbosity:
|
|
516
|
+
print(
|
|
517
|
+
f"States '{self.name}': Reading static data '{self.data_source}' from context '{STATES}'"
|
|
518
|
+
)
|
|
519
|
+
self.data_source = algo.dbook.get_file_path(
|
|
520
|
+
STATES, self.data_source, check_raw=False
|
|
521
|
+
)
|
|
522
|
+
if verbosity:
|
|
523
|
+
print(f"Path: {self.data_source}")
|
|
524
|
+
elif verbosity:
|
|
525
|
+
print(f"States '{self.name}': Reading file {self.data_source}")
|
|
526
|
+
data = open_dataset(self.data_source, **self.xr_read_pars)
|
|
527
|
+
else:
|
|
528
|
+
data = self.data_source
|
|
529
|
+
|
|
530
|
+
if self.states_sel is not None:
|
|
531
|
+
data = data.isel({self.state_coord: self.states_sel})
|
|
532
|
+
if self.states_loc is not None:
|
|
533
|
+
data = data.sel({self.state_coord: self.states_loc})
|
|
534
|
+
|
|
535
|
+
self._N = data.sizes[self.state_coord]
|
|
536
|
+
self._inds = data.coords[self.state_coord].to_numpy()
|
|
537
|
+
if self.format_times_func is not None:
|
|
538
|
+
self._inds = self.format_times_func(self._inds)
|
|
539
|
+
|
|
540
|
+
w_name = self.var2col.get(FV.WEIGHT, FV.WEIGHT)
|
|
541
|
+
self._weights = np.zeros((self._N, algo.n_turbines), dtype=FC.DTYPE)
|
|
542
|
+
if w_name in data.data_vars:
|
|
543
|
+
if data[w_name].dims != (self.state_coord,):
|
|
544
|
+
raise ValueError(
|
|
545
|
+
f"Weights data '{w_name}': Expecting dims ({self.state_coord},), got {data[w_name]}"
|
|
546
|
+
)
|
|
547
|
+
self._weights[:] = data.data_vars[w_name].to_numpy()[:, None]
|
|
548
|
+
elif FV.WEIGHT in self.var2col:
|
|
549
|
+
raise KeyError(
|
|
550
|
+
f"Weight variable '{w_name}' defined in var2col, but not found in data_vars {list(data.data_vars.keys())}"
|
|
551
|
+
)
|
|
552
|
+
else:
|
|
553
|
+
self._weights = np.zeros((self._N, algo.n_turbines), dtype=FC.DTYPE)
|
|
554
|
+
self._weights[:] = 1.0 / self._N
|
|
555
|
+
|
|
556
|
+
cols = {}
|
|
557
|
+
self._solo = {}
|
|
558
|
+
for v in self.ovars:
|
|
559
|
+
c = self.var2col.get(v, v)
|
|
560
|
+
if c in self.fixed_vars:
|
|
561
|
+
pass
|
|
562
|
+
elif c in data.attrs:
|
|
563
|
+
self._solo[v] = np.full(self._N, data.attrs)
|
|
564
|
+
elif c in data.data_vars:
|
|
565
|
+
if data[c].dims == (self.state_coord,):
|
|
566
|
+
self._solo[v] = data.data_vars[c].to_numpy()
|
|
567
|
+
elif data[c].dims == (self.state_coord, self.h_coord):
|
|
568
|
+
cols[v] = c
|
|
569
|
+
else:
|
|
570
|
+
raise ValueError(
|
|
571
|
+
f"Variable '{c}': Expecting dims {(self.state_coord, self.h_coord)}, got {data[c].dims}"
|
|
572
|
+
)
|
|
573
|
+
else:
|
|
574
|
+
raise KeyError(
|
|
575
|
+
f"Missing variable '{c}', found data_vars {sorted(list(data.data_vars.keys()))} and attrs {sorted(list(data.attrs.keys()))}"
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
if self.heights is not None:
|
|
579
|
+
data = data.sel({self.h_coord: self.heights})
|
|
580
|
+
else:
|
|
581
|
+
self.heights = data[self.h_coord].to_numpy()
|
|
582
|
+
|
|
583
|
+
self.H = self.var(FV.H)
|
|
584
|
+
self.VARS = self.var("vars")
|
|
585
|
+
self.DATA = self.var("data")
|
|
586
|
+
|
|
587
|
+
idata = States.load_data(self, algo, verbosity)
|
|
588
|
+
idata["coords"][self.H] = self.heights
|
|
589
|
+
idata["coords"][self.VARS] = list(cols.keys())
|
|
590
|
+
|
|
591
|
+
dims = (FC.STATE, self.VARS, self.H)
|
|
592
|
+
idata["data_vars"][self.DATA] = (
|
|
593
|
+
dims,
|
|
594
|
+
np.stack(
|
|
595
|
+
[data.data_vars[c].to_numpy() for c in cols.values()], axis=1
|
|
596
|
+
).astype(FC.DTYPE),
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
for v, d in self._solo.items():
|
|
600
|
+
idata["data_vars"][self.var(v)] = ((FC.STATE,), d.astype(FC.DTYPE))
|
|
601
|
+
self._solo = list(self._solo.keys())
|
|
602
|
+
|
|
603
|
+
return idata
|
|
604
|
+
|
|
605
|
+
|
|
417
606
|
class MultiHeightTimeseries(MultiHeightStates):
|
|
418
607
|
"""
|
|
419
608
|
Multi-height timeseries states data.
|
|
@@ -423,3 +612,33 @@ class MultiHeightTimeseries(MultiHeightStates):
|
|
|
423
612
|
"""
|
|
424
613
|
|
|
425
614
|
RDICT = {"index_col": 0, "parse_dates": [0]}
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
class MultiHeightNCTimeseries(MultiHeightNCStates):
|
|
618
|
+
"""
|
|
619
|
+
Multi-height timeseries from xarray Dataset.
|
|
620
|
+
|
|
621
|
+
:group: input.states
|
|
622
|
+
|
|
623
|
+
"""
|
|
624
|
+
|
|
625
|
+
def __init__(
|
|
626
|
+
self,
|
|
627
|
+
*args,
|
|
628
|
+
time_coord=FC.TIME,
|
|
629
|
+
**kwargs,
|
|
630
|
+
):
|
|
631
|
+
"""
|
|
632
|
+
Constructor.
|
|
633
|
+
|
|
634
|
+
Parameters
|
|
635
|
+
----------
|
|
636
|
+
args: tuple, optional
|
|
637
|
+
Parameters for the base class
|
|
638
|
+
time_coord: str
|
|
639
|
+
Name of the state coordinate
|
|
640
|
+
kwargs: dict, optional
|
|
641
|
+
Parameters for the base class
|
|
642
|
+
|
|
643
|
+
"""
|
|
644
|
+
super().__init__(*args, state_coord=time_coord, **kwargs)
|
foxes/input/windio/__init__.py
CHANGED
|
@@ -2,4 +2,9 @@
|
|
|
2
2
|
Functions for usingin windIO yaml files as input.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .windio import
|
|
5
|
+
from .windio import read_windio
|
|
6
|
+
from .read_fields import wio2foxes, foxes2wio
|
|
7
|
+
from .get_states import get_states
|
|
8
|
+
from .read_farm import read_turbine_type, read_layout
|
|
9
|
+
from .read_attributes import read_attributes
|
|
10
|
+
from .runner import WindioRunner
|