foxes 1.2.5__py3-none-any.whl → 1.4__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 -3
- examples/abl_states/run.py +2 -2
- examples/compare_rotors_pwakes/run.py +1 -1
- examples/compare_wakes/run.py +1 -2
- examples/dyn_wakes/run.py +29 -6
- examples/induction/run.py +3 -3
- examples/multi_height/run.py +1 -1
- examples/power_mask/run.py +2 -2
- examples/quickstart/run.py +16 -0
- examples/random_timeseries/run.py +3 -4
- examples/scan_row/run.py +3 -3
- examples/sequential/run.py +33 -10
- examples/single_state/run.py +3 -4
- examples/states_lookup_table/run.py +3 -3
- examples/streamline_wakes/run.py +27 -4
- examples/tab_file/run.py +3 -3
- examples/timelines/run.py +29 -5
- examples/timeseries/run.py +3 -3
- examples/timeseries_slurm/run.py +3 -3
- examples/wind_rose/run.py +3 -3
- examples/yawed_wake/run.py +16 -8
- foxes/__init__.py +22 -18
- foxes/algorithms/__init__.py +6 -6
- foxes/algorithms/downwind/__init__.py +2 -2
- foxes/algorithms/downwind/downwind.py +53 -27
- foxes/algorithms/downwind/models/__init__.py +6 -6
- foxes/algorithms/downwind/models/farm_wakes_calc.py +22 -14
- foxes/algorithms/downwind/models/init_farm_data.py +4 -5
- foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
- foxes/algorithms/downwind/models/reorder_farm_output.py +5 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +7 -7
- foxes/algorithms/iterative/__init__.py +7 -3
- foxes/algorithms/iterative/iterative.py +1 -2
- foxes/algorithms/iterative/models/__init__.py +7 -3
- foxes/algorithms/iterative/models/farm_wakes_calc.py +15 -8
- foxes/algorithms/sequential/__init__.py +3 -3
- foxes/algorithms/sequential/models/__init__.py +2 -2
- foxes/algorithms/sequential/models/seq_state.py +0 -18
- foxes/algorithms/sequential/sequential.py +8 -22
- foxes/config/__init__.py +5 -1
- foxes/constants.py +22 -0
- foxes/core/__init__.py +45 -22
- foxes/core/algorithm.py +0 -1
- foxes/core/data.py +56 -29
- foxes/core/engine.py +28 -14
- foxes/core/farm_controller.py +2 -2
- foxes/core/farm_data_model.py +1 -0
- foxes/core/ground_model.py +4 -13
- foxes/core/model.py +5 -5
- foxes/core/partial_wakes_model.py +147 -10
- foxes/core/point_data_model.py +2 -3
- foxes/core/rotor_model.py +42 -38
- foxes/core/states.py +4 -50
- foxes/core/turbine.py +2 -1
- foxes/core/wake_deflection.py +130 -0
- foxes/core/wake_model.py +222 -9
- foxes/core/wake_superposition.py +122 -4
- foxes/core/wind_farm.py +6 -6
- foxes/data/__init__.py +7 -2
- foxes/data/states/weibull_sectors_12.csv +13 -0
- foxes/data/states/weibull_sectors_12.nc +0 -0
- foxes/engines/__init__.py +14 -15
- foxes/engines/dask.py +39 -14
- foxes/engines/numpy.py +0 -3
- foxes/input/__init__.py +3 -3
- foxes/input/farm_layout/__init__.py +8 -8
- foxes/input/farm_layout/from_csv.py +1 -1
- foxes/input/farm_layout/ring.py +0 -1
- foxes/input/states/__init__.py +22 -11
- foxes/input/states/create/__init__.py +3 -2
- foxes/input/states/field_data_nc.py +48 -84
- foxes/input/states/multi_height.py +40 -60
- foxes/input/states/one_point_flow.py +22 -25
- foxes/input/states/scan.py +6 -19
- foxes/input/states/single.py +6 -18
- foxes/input/states/states_table.py +25 -44
- foxes/input/states/weibull_sectors.py +225 -0
- foxes/input/states/wrg_states.py +151 -37
- foxes/input/yaml/__init__.py +9 -3
- foxes/input/yaml/dict.py +19 -19
- foxes/input/yaml/windio/__init__.py +10 -5
- foxes/input/yaml/windio/read_attributes.py +2 -2
- foxes/input/yaml/windio/read_farm.py +5 -5
- foxes/input/yaml/windio/read_fields.py +4 -2
- foxes/input/yaml/windio/read_site.py +52 -0
- foxes/input/yaml/windio/windio.py +1 -1
- foxes/models/__init__.py +15 -14
- foxes/models/axial_induction/__init__.py +2 -2
- foxes/models/farm_controllers/__init__.py +1 -1
- foxes/models/farm_models/__init__.py +1 -1
- foxes/models/ground_models/__init__.py +3 -2
- foxes/models/ground_models/wake_mirror.py +3 -3
- foxes/models/model_book.py +175 -49
- foxes/models/partial_wakes/__init__.py +6 -6
- foxes/models/partial_wakes/axiwake.py +30 -5
- foxes/models/partial_wakes/centre.py +47 -0
- foxes/models/partial_wakes/rotor_points.py +45 -9
- foxes/models/partial_wakes/segregated.py +2 -20
- foxes/models/partial_wakes/top_hat.py +27 -2
- foxes/models/point_models/__init__.py +4 -4
- foxes/models/rotor_models/__init__.py +3 -3
- foxes/models/rotor_models/centre.py +6 -4
- foxes/models/turbine_models/__init__.py +11 -11
- foxes/models/turbine_models/set_farm_vars.py +0 -1
- foxes/models/turbine_types/PCt_file.py +0 -2
- foxes/models/turbine_types/PCt_from_two.py +0 -2
- foxes/models/turbine_types/__init__.py +9 -9
- foxes/models/vertical_profiles/__init__.py +7 -7
- foxes/models/wake_deflections/__init__.py +3 -0
- foxes/models/{wake_frames/yawed_wakes.py → wake_deflections/bastankhah2016.py} +32 -111
- foxes/models/wake_deflections/jimenez.py +277 -0
- foxes/models/wake_deflections/no_deflection.py +94 -0
- foxes/models/wake_frames/__init__.py +6 -7
- foxes/models/wake_frames/dynamic_wakes.py +12 -3
- foxes/models/wake_frames/rotor_wd.py +3 -1
- foxes/models/wake_frames/seq_dynamic_wakes.py +45 -8
- foxes/models/wake_frames/streamlines.py +8 -6
- foxes/models/wake_frames/timelines.py +19 -3
- foxes/models/wake_models/__init__.py +7 -7
- foxes/models/wake_models/dist_sliced.py +50 -84
- foxes/models/wake_models/gaussian.py +20 -0
- foxes/models/wake_models/induction/__init__.py +5 -5
- foxes/models/wake_models/induction/rankine_half_body.py +30 -71
- foxes/models/wake_models/induction/rathmann.py +65 -64
- foxes/models/wake_models/induction/self_similar.py +65 -68
- foxes/models/wake_models/induction/self_similar2020.py +0 -3
- foxes/models/wake_models/induction/vortex_sheet.py +71 -75
- foxes/models/wake_models/ti/__init__.py +2 -2
- foxes/models/wake_models/ti/crespo_hernandez.py +5 -3
- foxes/models/wake_models/ti/iec_ti.py +6 -4
- foxes/models/wake_models/top_hat.py +58 -7
- foxes/models/wake_models/wind/__init__.py +6 -4
- foxes/models/wake_models/wind/bastankhah14.py +25 -7
- foxes/models/wake_models/wind/bastankhah16.py +35 -3
- foxes/models/wake_models/wind/jensen.py +15 -2
- foxes/models/wake_models/wind/turbopark.py +28 -2
- foxes/models/wake_superpositions/__init__.py +18 -9
- foxes/models/wake_superpositions/ti_linear.py +4 -4
- foxes/models/wake_superpositions/ti_max.py +4 -4
- foxes/models/wake_superpositions/ti_pow.py +4 -4
- foxes/models/wake_superpositions/ti_quadratic.py +4 -4
- foxes/models/wake_superpositions/wind_vector.py +257 -0
- foxes/models/wake_superpositions/ws_linear.py +9 -10
- foxes/models/wake_superpositions/ws_max.py +8 -8
- foxes/models/wake_superpositions/ws_pow.py +8 -8
- foxes/models/wake_superpositions/ws_product.py +4 -4
- foxes/models/wake_superpositions/ws_quadratic.py +8 -8
- foxes/output/__init__.py +21 -19
- foxes/output/farm_layout.py +14 -6
- foxes/output/farm_results_eval.py +51 -27
- foxes/output/flow_plots_2d/__init__.py +2 -2
- foxes/output/flow_plots_2d/get_fig.py +4 -2
- foxes/output/rose_plot.py +23 -5
- foxes/output/seq_plugins/__init__.py +2 -2
- foxes/output/seq_plugins/seq_flow_ani_plugin.py +0 -3
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +0 -1
- foxes/output/slice_data.py +16 -19
- foxes/output/turbine_type_curves.py +7 -8
- foxes/utils/__init__.py +37 -19
- foxes/utils/abl/__init__.py +4 -4
- foxes/utils/cubic_roots.py +1 -1
- foxes/utils/data_book.py +4 -3
- foxes/utils/dict.py +3 -3
- foxes/utils/exec_python.py +5 -5
- foxes/utils/factory.py +1 -3
- foxes/utils/geom2d/__init__.py +7 -5
- foxes/utils/geopandas_utils.py +2 -2
- foxes/utils/pandas_utils.py +4 -3
- foxes/utils/tab_files.py +0 -1
- foxes/utils/weibull.py +28 -0
- foxes/utils/wrg_utils.py +3 -1
- foxes/utils/xarray_utils.py +9 -2
- foxes/variables.py +67 -9
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/METADATA +14 -21
- foxes-1.4.dist-info/RECORD +320 -0
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/WHEEL +1 -1
- tests/0_consistency/iterative/test_iterative.py +2 -3
- tests/0_consistency/partial_wakes/test_partial_wakes.py +2 -2
- tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +2 -3
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +48 -56
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +33 -36
- tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +0 -2
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +3 -3
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +3 -4
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +3 -4
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +3 -4
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +3 -4
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
- tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +3 -3
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +3 -3
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +3 -4
- tests/3_examples/test_examples.py +3 -2
- foxes/output/round.py +0 -10
- foxes/utils/pandas_helpers.py +0 -178
- foxes-1.2.5.dist-info/RECORD +0 -312
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/entry_points.txt +0 -0
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info/licenses}/LICENSE +0 -0
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/top_level.txt +0 -0
foxes/input/states/__init__.py
CHANGED
|
@@ -2,17 +2,28 @@
|
|
|
2
2
|
Atmospheric input states.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .single import SingleStateStates
|
|
6
|
-
from .scan import ScanStates
|
|
7
|
-
from .
|
|
8
|
-
from .
|
|
9
|
-
from .
|
|
10
|
-
|
|
5
|
+
from .single import SingleStateStates as SingleStateStates
|
|
6
|
+
from .scan import ScanStates as ScanStates
|
|
7
|
+
from .field_data_nc import FieldDataNC as FieldDataNC
|
|
8
|
+
from .wrg_states import WRGStates as WRGStates
|
|
9
|
+
from .weibull_sectors import WeibullSectors as WeibullSectors
|
|
10
|
+
|
|
11
|
+
from .states_table import StatesTable as StatesTable
|
|
12
|
+
from .states_table import Timeseries as Timeseries
|
|
13
|
+
from .states_table import TabStates as TabStates
|
|
14
|
+
|
|
15
|
+
from .multi_height import MultiHeightStates as MultiHeightStates
|
|
16
|
+
from .multi_height import MultiHeightTimeseries as MultiHeightTimeseries
|
|
17
|
+
from .multi_height import MultiHeightNCStates as MultiHeightNCStates
|
|
18
|
+
from .multi_height import MultiHeightNCTimeseries as MultiHeightNCTimeseries
|
|
19
|
+
|
|
20
|
+
from .one_point_flow import OnePointFlowStates as OnePointFlowStates
|
|
21
|
+
from .one_point_flow import OnePointFlowTimeseries as OnePointFlowTimeseries
|
|
22
|
+
from .one_point_flow import (
|
|
23
|
+
OnePointFlowMultiHeightTimeseries as OnePointFlowMultiHeightTimeseries,
|
|
24
|
+
)
|
|
11
25
|
from .one_point_flow import (
|
|
12
|
-
|
|
13
|
-
OnePointFlowTimeseries,
|
|
14
|
-
OnePointFlowMultiHeightTimeseries,
|
|
15
|
-
OnePointFlowMultiHeightNCTimeseries,
|
|
26
|
+
OnePointFlowMultiHeightNCTimeseries as OnePointFlowMultiHeightNCTimeseries,
|
|
16
27
|
)
|
|
17
28
|
|
|
18
|
-
from . import create
|
|
29
|
+
from . import create as create
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
from .random_abl_states import create_random_abl_states
|
|
2
|
-
from .
|
|
1
|
+
from .random_abl_states import create_random_abl_states as create_random_abl_states
|
|
2
|
+
from .random_abl_states import write_random_abl_states as write_random_abl_states
|
|
3
|
+
from .random_timeseries import random_timseries_data as random_timseries_data
|
|
@@ -16,7 +16,6 @@ def _read_nc_file(
|
|
|
16
16
|
fpath,
|
|
17
17
|
coords,
|
|
18
18
|
vars,
|
|
19
|
-
weight_var,
|
|
20
19
|
nc_engine,
|
|
21
20
|
sel,
|
|
22
21
|
isel,
|
|
@@ -30,18 +29,7 @@ def _read_nc_file(
|
|
|
30
29
|
f"Missing coordinate '{c}' in file {fpath}, got: {list(data.coords.keys())}"
|
|
31
30
|
)
|
|
32
31
|
if minimal:
|
|
33
|
-
|
|
34
|
-
if weight_var is not None:
|
|
35
|
-
if weight_var not in data.data_vars:
|
|
36
|
-
raise KeyError(
|
|
37
|
-
f"Missing weight var '{weight_var}' in file {fpath}, found: {list(data.data_vars.keys())}"
|
|
38
|
-
)
|
|
39
|
-
if data[weight_var].dims != (coords[0],):
|
|
40
|
-
raise ValueError(
|
|
41
|
-
f"Wrong dimensions for variable '{weight_var}' in file {fpath}. Expecting {(coords[0],)}, got {data[weight_var].dims}"
|
|
42
|
-
)
|
|
43
|
-
weights = data[weight_var].to_numpy()
|
|
44
|
-
return data[coords[0]].to_numpy(), weights
|
|
32
|
+
return data[coords[0]].to_numpy()
|
|
45
33
|
else:
|
|
46
34
|
data = data[vars]
|
|
47
35
|
data.attrs = {}
|
|
@@ -175,7 +163,7 @@ class FieldDataNC(States):
|
|
|
175
163
|
super().__init__()
|
|
176
164
|
|
|
177
165
|
self.states_coord = states_coord
|
|
178
|
-
self.ovars = output_vars
|
|
166
|
+
self.ovars = list(output_vars)
|
|
179
167
|
self.fixed_vars = fixed_vars
|
|
180
168
|
self.x_coord = x_coord
|
|
181
169
|
self.y_coord = y_coord
|
|
@@ -196,7 +184,6 @@ class FieldDataNC(States):
|
|
|
196
184
|
self._N = None
|
|
197
185
|
|
|
198
186
|
self.__data_source = data_source
|
|
199
|
-
self.__weights = None
|
|
200
187
|
self.__inds = None
|
|
201
188
|
|
|
202
189
|
@property
|
|
@@ -298,16 +285,28 @@ class FieldDataNC(States):
|
|
|
298
285
|
dtype=config.dtype_double,
|
|
299
286
|
)
|
|
300
287
|
|
|
288
|
+
weights = None
|
|
289
|
+
if self.weight_ncvar is not None:
|
|
290
|
+
if self.weight_ncvar not in ds.data_vars:
|
|
291
|
+
raise KeyError(
|
|
292
|
+
f"States '{self.name}': Missing weights variable '{self.weight_ncvar}' in data, found {sorted(list(ds.data_vars.keys()))}"
|
|
293
|
+
)
|
|
294
|
+
if ds[self.weight_ncvar].dims != (self.states_coord,):
|
|
295
|
+
raise ValueError(
|
|
296
|
+
f"States '{self.name}': Weights variable '{self.weight_ncvar}' has wrong dimensions. Expecting {(self.states_coord,)}, got {ds[self.weight_ncvar].dims}"
|
|
297
|
+
)
|
|
298
|
+
weights = ds[self.weight_ncvar].to_numpy()
|
|
299
|
+
|
|
301
300
|
if verbosity > 1:
|
|
302
301
|
print(f"\n{self.name}: Data ranges")
|
|
303
302
|
for v, i in self._dkys.items():
|
|
304
303
|
d = data[..., i]
|
|
305
304
|
nn = np.sum(np.isnan(d))
|
|
306
305
|
print(
|
|
307
|
-
f" {v}: {np.nanmin(d)} --> {np.nanmax(d)}, nans: {nn} ({100*nn/len(d.flat):.2f}%)"
|
|
306
|
+
f" {v}: {np.nanmin(d)} --> {np.nanmax(d)}, nans: {nn} ({100 * nn / len(d.flat):.2f}%)"
|
|
308
307
|
)
|
|
309
308
|
|
|
310
|
-
return sts, h, y, x, data
|
|
309
|
+
return sts, h, y, x, data, weights
|
|
311
310
|
|
|
312
311
|
def output_point_vars(self, algo):
|
|
313
312
|
"""
|
|
@@ -353,10 +352,11 @@ class FieldDataNC(States):
|
|
|
353
352
|
# pre-load file reading:
|
|
354
353
|
coords = [self.states_coord, self.h_coord, self.y_coord, self.x_coord]
|
|
355
354
|
if not isinstance(self.data_source, xr.Dataset):
|
|
356
|
-
|
|
357
355
|
# check variables:
|
|
358
356
|
for v in self.ovars:
|
|
359
|
-
if v
|
|
357
|
+
if v == FV.WEIGHT and self.weight_ncvar is None:
|
|
358
|
+
pass
|
|
359
|
+
elif v not in self.var2ncvar and v not in self.fixed_vars:
|
|
360
360
|
raise ValueError(
|
|
361
361
|
f"States '{self.name}': Variable '{v}' neither found in var2ncvar not in fixed_vars"
|
|
362
362
|
)
|
|
@@ -413,7 +413,6 @@ class FieldDataNC(States):
|
|
|
413
413
|
_read_nc_file,
|
|
414
414
|
files,
|
|
415
415
|
coords=coords,
|
|
416
|
-
weight_var=self.weight_ncvar,
|
|
417
416
|
vars=vars,
|
|
418
417
|
nc_engine=config.nc_engine,
|
|
419
418
|
isel=self.isel,
|
|
@@ -422,7 +421,6 @@ class FieldDataNC(States):
|
|
|
422
421
|
)
|
|
423
422
|
|
|
424
423
|
if self.load_mode in ["preload", "lazy"]:
|
|
425
|
-
|
|
426
424
|
if self.load_mode == "lazy":
|
|
427
425
|
try:
|
|
428
426
|
self.__data_source = [ds.chunk() for ds in self.__data_source]
|
|
@@ -440,23 +438,15 @@ class FieldDataNC(States):
|
|
|
440
438
|
)
|
|
441
439
|
if self.load_mode == "preload":
|
|
442
440
|
self.__data_source.load()
|
|
443
|
-
if self.weight_ncvar is not None:
|
|
444
|
-
self.__weights = self.__data_source[self.weight_ncvar].to_numpy()
|
|
445
441
|
self.__inds = self.__data_source[self.states_coord].to_numpy()
|
|
446
442
|
self._N = len(self.__inds)
|
|
447
443
|
|
|
448
444
|
elif self.load_mode == "fly":
|
|
449
|
-
self.__inds
|
|
445
|
+
self.__inds = self.__data_source
|
|
450
446
|
self.__data_source = fpath
|
|
451
447
|
self._files_maxi = {f: len(inds) for f, inds in zip(files, self.__inds)}
|
|
452
448
|
self.__inds = np.concatenate(self.__inds, axis=0)
|
|
453
449
|
self._N = len(self.__inds)
|
|
454
|
-
if weights[0] is not None:
|
|
455
|
-
self.__weights = np.zeros(
|
|
456
|
-
(self._N, algo.n_turbines), dtype=config.dtype_double
|
|
457
|
-
)
|
|
458
|
-
self.__weights[:] = np.concatenate(weights, axis=0)[:, None]
|
|
459
|
-
del weights
|
|
460
450
|
|
|
461
451
|
else:
|
|
462
452
|
raise KeyError(
|
|
@@ -468,10 +458,10 @@ class FieldDataNC(States):
|
|
|
468
458
|
self.__inds, format=self.time_format
|
|
469
459
|
).to_numpy()
|
|
470
460
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
461
|
+
# given data is already Dataset:
|
|
462
|
+
else:
|
|
463
|
+
self.__inds = self.data_source[self.states_coord].to_numpy()
|
|
464
|
+
self._N = len(self.__inds)
|
|
475
465
|
|
|
476
466
|
# ensure WD and WS get the first two slots of data:
|
|
477
467
|
self._dkys = {}
|
|
@@ -492,8 +482,11 @@ class FieldDataNC(States):
|
|
|
492
482
|
self.H = self.var(FV.H)
|
|
493
483
|
self.VARS = self.var("vars")
|
|
494
484
|
self.DATA = self.var("data")
|
|
485
|
+
self.WEIGHT = self.var(FV.WEIGHT)
|
|
495
486
|
|
|
496
|
-
__, h, y, x, data = self._get_data(
|
|
487
|
+
__, h, y, x, data, weights = self._get_data(
|
|
488
|
+
self.data_source, coords, verbosity
|
|
489
|
+
)
|
|
497
490
|
self._prl_coords = coords
|
|
498
491
|
|
|
499
492
|
coos = (FC.STATE, self.H, self.Y, self.X, self.VARS)
|
|
@@ -504,6 +497,8 @@ class FieldDataNC(States):
|
|
|
504
497
|
idata["coords"][self.X] = x
|
|
505
498
|
idata["coords"][self.VARS] = list(self._dkys.keys())
|
|
506
499
|
idata["data_vars"][self.DATA] = data
|
|
500
|
+
if weights is not None:
|
|
501
|
+
idata["data_vars"][self.WEIGHT] = ((FC.STATE,), weights)
|
|
507
502
|
|
|
508
503
|
return idata
|
|
509
504
|
|
|
@@ -540,10 +535,9 @@ class FieldDataNC(States):
|
|
|
540
535
|
super().set_running(algo, data_stash, sel, isel, verbosity)
|
|
541
536
|
|
|
542
537
|
data_stash[self.name] = dict(
|
|
543
|
-
weights=self.__weights,
|
|
544
538
|
inds=self.__inds,
|
|
545
539
|
)
|
|
546
|
-
del self.
|
|
540
|
+
del self.__inds
|
|
547
541
|
|
|
548
542
|
if self.load_mode == "preload":
|
|
549
543
|
data_stash[self.name]["data_source"] = self.__data_source
|
|
@@ -579,7 +573,6 @@ class FieldDataNC(States):
|
|
|
579
573
|
super().unset_running(algo, data_stash, sel, isel, verbosity)
|
|
580
574
|
|
|
581
575
|
data = data_stash[self.name]
|
|
582
|
-
self.__weights = data.pop("weights")
|
|
583
576
|
self.__inds = data.pop("inds")
|
|
584
577
|
|
|
585
578
|
if self.load_mode == "preload":
|
|
@@ -611,44 +604,6 @@ class FieldDataNC(States):
|
|
|
611
604
|
raise ValueError(f"States '{self.name}': Cannot access index while running")
|
|
612
605
|
return self.__inds
|
|
613
606
|
|
|
614
|
-
def output_point_vars(self, algo):
|
|
615
|
-
"""
|
|
616
|
-
The variables which are being modified by the model.
|
|
617
|
-
|
|
618
|
-
Parameters
|
|
619
|
-
----------
|
|
620
|
-
algo: foxes.core.Algorithm
|
|
621
|
-
The calculation algorithm
|
|
622
|
-
|
|
623
|
-
Returns
|
|
624
|
-
-------
|
|
625
|
-
output_vars: list of str
|
|
626
|
-
The output variable names
|
|
627
|
-
|
|
628
|
-
"""
|
|
629
|
-
return self.ovars
|
|
630
|
-
|
|
631
|
-
def weights(self, algo):
|
|
632
|
-
"""
|
|
633
|
-
The statistical weights of all states.
|
|
634
|
-
|
|
635
|
-
Parameters
|
|
636
|
-
----------
|
|
637
|
-
algo: foxes.core.Algorithm
|
|
638
|
-
The calculation algorithm
|
|
639
|
-
|
|
640
|
-
Returns
|
|
641
|
-
-------
|
|
642
|
-
weights: numpy.ndarray
|
|
643
|
-
The weights, shape: (n_states, n_turbines)
|
|
644
|
-
|
|
645
|
-
"""
|
|
646
|
-
if self.running:
|
|
647
|
-
raise ValueError(
|
|
648
|
-
f"States '{self.name}': Cannot access weights while running"
|
|
649
|
-
)
|
|
650
|
-
return self.__weights
|
|
651
|
-
|
|
652
607
|
def calculate(self, algo, mdata, fdata, tdata):
|
|
653
608
|
"""
|
|
654
609
|
The main model calculation.
|
|
@@ -690,6 +645,7 @@ class FieldDataNC(States):
|
|
|
690
645
|
y = mdata[self.Y]
|
|
691
646
|
h = mdata[self.H]
|
|
692
647
|
data = mdata[self.DATA].copy()
|
|
648
|
+
weights = mdata.get(self.WEIGHT, None)
|
|
693
649
|
coords = self._prl_coords
|
|
694
650
|
|
|
695
651
|
# case lazy:
|
|
@@ -697,7 +653,7 @@ class FieldDataNC(States):
|
|
|
697
653
|
i0 = mdata.states_i0(counter=True)
|
|
698
654
|
s = slice(i0, i0 + n_states)
|
|
699
655
|
ds = self.data_source.isel({self.states_coord: s}).load()
|
|
700
|
-
__, h, y, x, data = self._get_data(ds, coords, verbosity=0)
|
|
656
|
+
__, h, y, x, data, weights = self._get_data(ds, coords, verbosity=0)
|
|
701
657
|
del ds
|
|
702
658
|
|
|
703
659
|
# case fly:
|
|
@@ -725,7 +681,6 @@ class FieldDataNC(States):
|
|
|
725
681
|
_read_nc_file(
|
|
726
682
|
fpath,
|
|
727
683
|
coords=coords,
|
|
728
|
-
weight_var=self.weight_ncvar,
|
|
729
684
|
vars=vars,
|
|
730
685
|
nc_engine=config.nc_engine,
|
|
731
686
|
isel=isel,
|
|
@@ -737,12 +692,12 @@ class FieldDataNC(States):
|
|
|
737
692
|
i0 += b - a
|
|
738
693
|
j0 = j1
|
|
739
694
|
|
|
740
|
-
assert (
|
|
741
|
-
i0
|
|
742
|
-
)
|
|
695
|
+
assert i0 == i1, (
|
|
696
|
+
f"States '{self.name}': Missing states for load_mode '{self.load_mode}': (i0, i1) = {(i0, i1)}"
|
|
697
|
+
)
|
|
743
698
|
|
|
744
699
|
data = xr.concat(data, dim=self.states_coord)
|
|
745
|
-
__, h, y, x, data = self._get_data(data, coords, verbosity=0)
|
|
700
|
+
__, h, y, x, data, weights = self._get_data(data, coords, verbosity=0)
|
|
746
701
|
|
|
747
702
|
else:
|
|
748
703
|
raise KeyError(
|
|
@@ -858,12 +813,21 @@ class FieldDataNC(States):
|
|
|
858
813
|
out[FV.WD] = uv2wd(uv, axis=-1)
|
|
859
814
|
del uv
|
|
860
815
|
for v in self.ovars:
|
|
861
|
-
if v not in out:
|
|
816
|
+
if v != FV.WEIGHT and v not in out:
|
|
862
817
|
if v in self._dkys:
|
|
863
818
|
out[v] = data[..., self._dkys[v]]
|
|
864
|
-
|
|
819
|
+
elif v in self.fixed_vars:
|
|
865
820
|
out[v] = np.full(
|
|
866
821
|
(n_states, n_pts), self.fixed_vars[v], dtype=config.dtype_double
|
|
867
822
|
)
|
|
868
823
|
|
|
824
|
+
# add weights:
|
|
825
|
+
if weights is not None:
|
|
826
|
+
tdata[FV.WEIGHT] = weights[:, None, None]
|
|
827
|
+
else:
|
|
828
|
+
tdata[FV.WEIGHT] = np.full(
|
|
829
|
+
(mdata.n_states, 1, 1), 1 / self._N, dtype=config.dtype_double
|
|
830
|
+
)
|
|
831
|
+
tdata.dims[FV.WEIGHT] = (FC.STATE, FC.TARGET, FC.TPOINT)
|
|
832
|
+
|
|
869
833
|
return {v: d.reshape(n_states, n_targets, n_tpoints) for v, d in out.items()}
|
|
@@ -36,7 +36,7 @@ class MultiHeightStates(States):
|
|
|
36
36
|
fixed_vars: dict, optional
|
|
37
37
|
Fixed uniform variable values, instead of
|
|
38
38
|
reading from data
|
|
39
|
-
|
|
39
|
+
read_pars: dict, optional
|
|
40
40
|
pandas file reading parameters
|
|
41
41
|
states_sel: slice or range or list of int
|
|
42
42
|
States subset selection
|
|
@@ -58,7 +58,7 @@ class MultiHeightStates(States):
|
|
|
58
58
|
heights,
|
|
59
59
|
var2col={},
|
|
60
60
|
fixed_vars={},
|
|
61
|
-
|
|
61
|
+
read_pars={},
|
|
62
62
|
states_sel=None,
|
|
63
63
|
states_loc=None,
|
|
64
64
|
**ipars,
|
|
@@ -79,7 +79,7 @@ class MultiHeightStates(States):
|
|
|
79
79
|
fixed_vars: dict, optional
|
|
80
80
|
Fixed uniform variable values, instead of
|
|
81
81
|
reading from data
|
|
82
|
-
|
|
82
|
+
read_pars: dict, optional
|
|
83
83
|
pandas file reading parameters
|
|
84
84
|
states_sel: slice or range or list of int, optional
|
|
85
85
|
States subset selection
|
|
@@ -91,9 +91,9 @@ class MultiHeightStates(States):
|
|
|
91
91
|
"""
|
|
92
92
|
super().__init__()
|
|
93
93
|
|
|
94
|
-
self.ovars = output_vars
|
|
94
|
+
self.ovars = list(output_vars)
|
|
95
95
|
self.heights = np.array(heights, dtype=config.dtype_double)
|
|
96
|
-
self.rpars =
|
|
96
|
+
self.rpars = read_pars
|
|
97
97
|
self.var2col = var2col
|
|
98
98
|
self.fixed_vars = fixed_vars
|
|
99
99
|
self.ipars = ipars
|
|
@@ -102,7 +102,6 @@ class MultiHeightStates(States):
|
|
|
102
102
|
|
|
103
103
|
self._data_source = data_source
|
|
104
104
|
self._solo = None
|
|
105
|
-
self._weights = None
|
|
106
105
|
self._inds = None
|
|
107
106
|
self._N = None
|
|
108
107
|
|
|
@@ -213,9 +212,7 @@ class MultiHeightStates(States):
|
|
|
213
212
|
print(f"States '{self.name}': Reading file {self.data_source}")
|
|
214
213
|
rpars = dict(self.RDICT, **self.rpars)
|
|
215
214
|
data = PandasFileHelper().read_file(self.data_source, **rpars)
|
|
216
|
-
isorg = False
|
|
217
215
|
else:
|
|
218
|
-
isorg = True
|
|
219
216
|
data = self.data_source
|
|
220
217
|
|
|
221
218
|
if self.states_sel is not None:
|
|
@@ -227,34 +224,31 @@ class MultiHeightStates(States):
|
|
|
227
224
|
self._inds = data.index.to_numpy()
|
|
228
225
|
|
|
229
226
|
col_w = self.var2col.get(FV.WEIGHT, FV.WEIGHT)
|
|
230
|
-
|
|
227
|
+
weights = None
|
|
231
228
|
if col_w in data:
|
|
232
|
-
|
|
229
|
+
weights = data[col_w].to_numpy()
|
|
233
230
|
elif FV.WEIGHT in self.var2col:
|
|
234
231
|
raise KeyError(
|
|
235
232
|
f"Weight variable '{col_w}' defined in var2col, but not found in states table columns {data.columns}"
|
|
236
233
|
)
|
|
237
|
-
else:
|
|
238
|
-
self._weights[:] = 1.0 / self._N
|
|
239
|
-
if isorg:
|
|
240
|
-
data = data.copy()
|
|
241
|
-
data[col_w] = self._weights[:, 0]
|
|
242
234
|
|
|
243
235
|
cols = []
|
|
244
236
|
cmap = {}
|
|
245
237
|
self._solo = {}
|
|
246
238
|
for v in self.ovars:
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
239
|
+
if v != FV.WEIGHT:
|
|
240
|
+
vcols = self._find_cols(v, data.columns)
|
|
241
|
+
if len(vcols) == 1:
|
|
242
|
+
self._solo[v] = data[vcols[0]].to_numpy()
|
|
243
|
+
elif len(vcols) > 1:
|
|
244
|
+
cmap[v] = (len(cols), len(cols) + len(vcols))
|
|
245
|
+
cols += vcols
|
|
253
246
|
data = data[cols]
|
|
254
247
|
|
|
255
248
|
self.H = self.var(FV.H)
|
|
256
249
|
self.VARS = self.var("vars")
|
|
257
250
|
self.DATA = self.var("data")
|
|
251
|
+
self.WEIGHT = self.var(FV.WEIGHT)
|
|
258
252
|
|
|
259
253
|
idata = super().load_data(algo, verbosity)
|
|
260
254
|
|
|
@@ -268,7 +262,8 @@ class MultiHeightStates(States):
|
|
|
268
262
|
dims,
|
|
269
263
|
data.to_numpy().reshape(self._N, n_vrs, n_hts),
|
|
270
264
|
)
|
|
271
|
-
|
|
265
|
+
if weights is not None:
|
|
266
|
+
idata["data_vars"][self.WEIGHT] = ((FC.STATE,), weights)
|
|
272
267
|
for v, d in self._solo.items():
|
|
273
268
|
idata["data_vars"][self.var(v)] = ((FC.STATE,), d)
|
|
274
269
|
self._solo = list(self._solo.keys())
|
|
@@ -309,10 +304,9 @@ class MultiHeightStates(States):
|
|
|
309
304
|
|
|
310
305
|
data_stash[self.name] = dict(
|
|
311
306
|
data_source=self._data_source,
|
|
312
|
-
weights=self._weights,
|
|
313
307
|
inds=self._inds,
|
|
314
308
|
)
|
|
315
|
-
del self._data_source, self.
|
|
309
|
+
del self._data_source, self._inds
|
|
316
310
|
|
|
317
311
|
def unset_running(
|
|
318
312
|
self,
|
|
@@ -345,7 +339,6 @@ class MultiHeightStates(States):
|
|
|
345
339
|
|
|
346
340
|
data = data_stash[self.name]
|
|
347
341
|
self._data_source = data.pop("data_source")
|
|
348
|
-
self._weights = data.pop("weights")
|
|
349
342
|
self._inds = data.pop("inds")
|
|
350
343
|
|
|
351
344
|
def size(self):
|
|
@@ -391,27 +384,6 @@ class MultiHeightStates(States):
|
|
|
391
384
|
"""
|
|
392
385
|
return self.ovars
|
|
393
386
|
|
|
394
|
-
def weights(self, algo):
|
|
395
|
-
"""
|
|
396
|
-
The statistical weights of all states.
|
|
397
|
-
|
|
398
|
-
Parameters
|
|
399
|
-
----------
|
|
400
|
-
algo: foxes.core.Algorithm
|
|
401
|
-
The calculation algorithm
|
|
402
|
-
|
|
403
|
-
Returns
|
|
404
|
-
-------
|
|
405
|
-
weights: numpy.ndarray
|
|
406
|
-
The weights, shape: (n_states, n_turbines)
|
|
407
|
-
|
|
408
|
-
"""
|
|
409
|
-
if self.running:
|
|
410
|
-
raise ValueError(
|
|
411
|
-
f"States '{self.name}': Cannot access weights while running"
|
|
412
|
-
)
|
|
413
|
-
return self._weights
|
|
414
|
-
|
|
415
387
|
def calculate(self, algo, mdata, fdata, tdata):
|
|
416
388
|
"""
|
|
417
389
|
The main model calculation.
|
|
@@ -512,6 +484,15 @@ class MultiHeightStates(States):
|
|
|
512
484
|
else:
|
|
513
485
|
results[v] = ires[vrs.index(v)]
|
|
514
486
|
|
|
487
|
+
# add weights:
|
|
488
|
+
if self.WEIGHT in mdata:
|
|
489
|
+
tdata[FV.WEIGHT] = mdata[self.WEIGHT][:, None, None]
|
|
490
|
+
else:
|
|
491
|
+
tdata[FV.WEIGHT] = np.full(
|
|
492
|
+
(mdata.n_states, 1, 1), 1 / self._N, dtype=config.dtype_double
|
|
493
|
+
)
|
|
494
|
+
tdata.dims[FV.WEIGHT] = (FC.STATE, FC.TARGET, FC.TPOINT)
|
|
495
|
+
|
|
515
496
|
return results
|
|
516
497
|
|
|
517
498
|
def finalize(self, algo, verbosity=0):
|
|
@@ -528,7 +509,6 @@ class MultiHeightStates(States):
|
|
|
528
509
|
"""
|
|
529
510
|
super().finalize(algo, verbosity)
|
|
530
511
|
self._solo = None
|
|
531
|
-
self._weights = None
|
|
532
512
|
self._N = None
|
|
533
513
|
|
|
534
514
|
|
|
@@ -592,7 +572,7 @@ class MultiHeightNCStates(MultiHeightStates):
|
|
|
592
572
|
data_source,
|
|
593
573
|
*args,
|
|
594
574
|
heights=[],
|
|
595
|
-
|
|
575
|
+
read_pars=None,
|
|
596
576
|
**kwargs,
|
|
597
577
|
)
|
|
598
578
|
self.state_coord = state_coord
|
|
@@ -651,37 +631,35 @@ class MultiHeightNCStates(MultiHeightStates):
|
|
|
651
631
|
self._inds = data.coords[self.state_coord].to_numpy()
|
|
652
632
|
|
|
653
633
|
if self._format_times_func == "default":
|
|
654
|
-
|
|
634
|
+
|
|
635
|
+
def format_times_func(t):
|
|
636
|
+
"""little helper function to convert times to datetime64"""
|
|
637
|
+
return t.astype("datetime64[ns]")
|
|
655
638
|
else:
|
|
656
639
|
format_times_func = self._format_times_func
|
|
657
640
|
if format_times_func is not None:
|
|
658
641
|
self._inds = format_times_func(self._inds)
|
|
659
642
|
|
|
660
643
|
w_name = self.var2col.get(FV.WEIGHT, FV.WEIGHT)
|
|
661
|
-
|
|
644
|
+
weights = None
|
|
662
645
|
if w_name in data.data_vars:
|
|
663
646
|
if data[w_name].dims != (self.state_coord,):
|
|
664
647
|
raise ValueError(
|
|
665
648
|
f"Weights data '{w_name}': Expecting dims ({self.state_coord},), got {data[w_name]}"
|
|
666
649
|
)
|
|
667
|
-
|
|
650
|
+
weights = data.data_vars[w_name].to_numpy()
|
|
668
651
|
elif FV.WEIGHT in self.var2col:
|
|
669
652
|
raise KeyError(
|
|
670
653
|
f"Weight variable '{w_name}' defined in var2col, but not found in data_vars {list(data.data_vars.keys())}"
|
|
671
654
|
)
|
|
672
|
-
else:
|
|
673
|
-
self._weights = np.zeros(
|
|
674
|
-
(self._N, algo.n_turbines), dtype=config.dtype_double
|
|
675
|
-
)
|
|
676
|
-
self._weights[:] = 1.0 / self._N
|
|
677
655
|
|
|
678
656
|
cols = {}
|
|
679
657
|
self._solo = {}
|
|
680
658
|
for v in self.ovars:
|
|
659
|
+
if v in self.fixed_vars or v == FV.WEIGHT:
|
|
660
|
+
continue
|
|
681
661
|
c = self.var2col.get(v, v)
|
|
682
|
-
if c in
|
|
683
|
-
pass
|
|
684
|
-
elif c in data.attrs:
|
|
662
|
+
if c in data.attrs:
|
|
685
663
|
self._solo[v] = np.full(self._N, data.attrs)
|
|
686
664
|
elif c in data.data_vars:
|
|
687
665
|
if data[c].dims == (self.state_coord,):
|
|
@@ -705,6 +683,7 @@ class MultiHeightNCStates(MultiHeightStates):
|
|
|
705
683
|
self.H = self.var(FV.H)
|
|
706
684
|
self.VARS = self.var("vars")
|
|
707
685
|
self.DATA = self.var("data")
|
|
686
|
+
self.WEIGHT = self.var(FV.WEIGHT)
|
|
708
687
|
|
|
709
688
|
idata = States.load_data(self, algo, verbosity)
|
|
710
689
|
idata["coords"][self.H] = self.heights
|
|
@@ -717,7 +696,8 @@ class MultiHeightNCStates(MultiHeightStates):
|
|
|
717
696
|
[data.data_vars[c].to_numpy() for c in cols.values()], axis=1
|
|
718
697
|
).astype(config.dtype_double),
|
|
719
698
|
)
|
|
720
|
-
|
|
699
|
+
if weights is not None:
|
|
700
|
+
idata["data_vars"][self.WEIGHT] = ((FC.STATE,), weights)
|
|
721
701
|
for v, d in self._solo.items():
|
|
722
702
|
idata["data_vars"][self.var(v)] = (
|
|
723
703
|
(FC.STATE,),
|