foxes 1.1.1__py3-none-any.whl → 1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of foxes might be problematic. Click here for more details.
- docs/source/conf.py +3 -1
- examples/dyn_wakes/run.py +2 -2
- examples/timelines/run.py +1 -1
- foxes/__init__.py +13 -2
- foxes/algorithms/downwind/downwind.py +6 -1
- foxes/algorithms/downwind/models/init_farm_data.py +5 -2
- foxes/algorithms/downwind/models/point_wakes_calc.py +0 -1
- foxes/algorithms/iterative/iterative.py +1 -1
- foxes/algorithms/sequential/sequential.py +4 -3
- foxes/config/__init__.py +1 -0
- foxes/config/config.py +134 -0
- foxes/constants.py +15 -6
- foxes/core/algorithm.py +22 -10
- foxes/core/data.py +2 -1
- foxes/core/engine.py +40 -34
- foxes/core/farm_controller.py +4 -3
- foxes/core/farm_data_model.py +6 -2
- foxes/core/model.py +2 -1
- foxes/core/point_data_model.py +4 -2
- foxes/core/rotor_model.py +8 -4
- foxes/core/turbine_type.py +1 -1
- foxes/core/wake_frame.py +7 -5
- foxes/core/wake_model.py +6 -1
- foxes/data/__init__.py +1 -1
- foxes/data/static_data.py +0 -7
- foxes/engines/dask.py +4 -3
- foxes/engines/single.py +1 -1
- foxes/input/__init__.py +1 -1
- foxes/input/farm_layout/from_csv.py +3 -1
- foxes/input/farm_layout/from_file.py +10 -10
- foxes/input/farm_layout/from_json.py +4 -3
- foxes/input/farm_layout/grid.py +3 -3
- foxes/input/states/create/random_abl_states.py +5 -3
- foxes/input/states/field_data_nc.py +22 -14
- foxes/input/states/multi_height.py +26 -15
- foxes/input/states/one_point_flow.py +6 -5
- foxes/input/states/scan_ws.py +4 -1
- foxes/input/states/single.py +15 -6
- foxes/input/states/slice_data_nc.py +18 -12
- foxes/input/states/states_table.py +17 -10
- foxes/input/yaml/__init__.py +3 -0
- foxes/input/yaml/dict.py +210 -0
- foxes/input/yaml/windio/__init__.py +4 -0
- foxes/input/{windio → yaml/windio}/get_states.py +7 -7
- foxes/input/{windio → yaml/windio}/read_attributes.py +61 -40
- foxes/input/{windio → yaml/windio}/read_farm.py +34 -43
- foxes/input/{windio → yaml/windio}/read_fields.py +11 -10
- foxes/input/yaml/windio/read_outputs.py +147 -0
- foxes/input/yaml/windio/windio.py +269 -0
- foxes/input/yaml/yaml.py +103 -0
- foxes/models/partial_wakes/axiwake.py +7 -6
- foxes/models/partial_wakes/centre.py +3 -2
- foxes/models/partial_wakes/segregated.py +5 -2
- foxes/models/point_models/set_uniform_data.py +5 -3
- foxes/models/rotor_models/centre.py +2 -2
- foxes/models/rotor_models/grid.py +5 -5
- foxes/models/rotor_models/levels.py +6 -6
- foxes/models/turbine_models/kTI_model.py +3 -1
- foxes/models/turbine_models/lookup_table.py +7 -4
- foxes/models/turbine_models/power_mask.py +14 -8
- foxes/models/turbine_models/sector_management.py +4 -2
- foxes/models/turbine_models/set_farm_vars.py +53 -23
- foxes/models/turbine_models/table_factors.py +8 -7
- foxes/models/turbine_models/yaw2yawm.py +0 -1
- foxes/models/turbine_models/yawm2yaw.py +0 -1
- foxes/models/turbine_types/CpCt_file.py +6 -3
- foxes/models/turbine_types/CpCt_from_two.py +6 -3
- foxes/models/turbine_types/PCt_file.py +7 -6
- foxes/models/turbine_types/PCt_from_two.py +11 -2
- foxes/models/turbine_types/TBL_file.py +3 -4
- foxes/models/turbine_types/wsrho2PCt_from_two.py +19 -11
- foxes/models/turbine_types/wsti2PCt_from_two.py +19 -11
- foxes/models/vertical_profiles/abl_log_neutral_ws.py +1 -1
- foxes/models/vertical_profiles/abl_log_stable_ws.py +1 -1
- foxes/models/vertical_profiles/abl_log_unstable_ws.py +1 -1
- foxes/models/vertical_profiles/abl_log_ws.py +1 -1
- foxes/models/wake_frames/dynamic_wakes.py +17 -9
- foxes/models/wake_frames/farm_order.py +4 -3
- foxes/models/wake_frames/rotor_wd.py +3 -1
- foxes/models/wake_frames/seq_dynamic_wakes.py +14 -7
- foxes/models/wake_frames/streamlines.py +9 -6
- foxes/models/wake_frames/timelines.py +21 -14
- foxes/models/wake_frames/yawed_wakes.py +3 -1
- foxes/models/wake_models/induction/vortex_sheet.py +0 -1
- foxes/models/wake_models/ti/crespo_hernandez.py +2 -1
- foxes/models/wake_models/wind/bastankhah14.py +3 -2
- foxes/models/wake_models/wind/bastankhah16.py +2 -1
- foxes/models/wake_models/wind/turbopark.py +9 -7
- foxes/models/wake_superpositions/ws_product.py +0 -1
- foxes/output/calc_points.py +7 -4
- foxes/output/farm_layout.py +30 -18
- foxes/output/farm_results_eval.py +4 -3
- foxes/output/grids.py +8 -7
- foxes/output/output.py +7 -2
- foxes/output/results_writer.py +10 -11
- foxes/output/rose_plot.py +38 -20
- foxes/output/rotor_point_plots.py +7 -3
- foxes/output/slice_data.py +1 -1
- foxes/output/state_turbine_map.py +5 -1
- foxes/output/state_turbine_table.py +7 -3
- foxes/output/turbine_type_curves.py +7 -2
- foxes/utils/dict.py +107 -3
- foxes/utils/geopandas_utils.py +3 -2
- {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/METADATA +18 -17
- {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/RECORD +122 -122
- {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/WHEEL +1 -1
- foxes-1.2.dist-info/entry_points.txt +3 -0
- tests/0_consistency/iterative/test_iterative.py +65 -67
- tests/0_consistency/partial_wakes/test_partial_wakes.py +58 -61
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +56 -53
- tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +41 -41
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +34 -34
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +50 -50
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +51 -52
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +73 -74
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +73 -74
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +51 -49
- tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +101 -103
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +61 -62
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +51 -52
- examples/windio/run.py +0 -29
- foxes/data/states/windio_timeseries_5000.nc +0 -0
- foxes/data/windio/DTU_10MW_turbine.yaml +0 -10
- foxes/data/windio/__init__.py +0 -0
- foxes/data/windio/windio_5turbines_timeseries.yaml +0 -79
- foxes/input/windio/__init__.py +0 -11
- foxes/input/windio/read_outputs.py +0 -172
- foxes/input/windio/runner.py +0 -183
- foxes/input/windio/windio.py +0 -193
- {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/LICENSE +0 -0
- {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/top_level.txt +0 -0
|
@@ -4,6 +4,7 @@ from cycler import cycler
|
|
|
4
4
|
import matplotlib.pyplot as plt
|
|
5
5
|
|
|
6
6
|
from .output import Output
|
|
7
|
+
from foxes.config import config
|
|
7
8
|
import foxes.variables as FV
|
|
8
9
|
import foxes.constants as FC
|
|
9
10
|
|
|
@@ -409,7 +410,7 @@ class FarmResultsEval(Output):
|
|
|
409
410
|
if algo is not None and P_unit_W is None:
|
|
410
411
|
P_unit_W = np.array(
|
|
411
412
|
[FC.P_UNITS[t.P_unit] for t in algo.farm_controller.turbine_types],
|
|
412
|
-
dtype=
|
|
413
|
+
dtype=config.dtype_double,
|
|
413
414
|
)[:, None]
|
|
414
415
|
elif algo is None and P_unit_W is not None:
|
|
415
416
|
pass
|
|
@@ -472,10 +473,10 @@ class FarmResultsEval(Output):
|
|
|
472
473
|
if algo is not None and P_nom is None:
|
|
473
474
|
P_nom = np.array(
|
|
474
475
|
[t.P_nominal for t in algo.farm_controller.turbine_types],
|
|
475
|
-
dtype=
|
|
476
|
+
dtype=config.dtype_double,
|
|
476
477
|
)
|
|
477
478
|
elif algo is None and P_nom is not None:
|
|
478
|
-
P_nom = np.array(P_nom, dtype=
|
|
479
|
+
P_nom = np.array(P_nom, dtype=config.dtype_double)
|
|
479
480
|
else:
|
|
480
481
|
raise KeyError("Expecting either 'algo' or 'P_nom'")
|
|
481
482
|
|
foxes/output/grids.py
CHANGED
|
@@ -3,6 +3,7 @@ import pandas as pd
|
|
|
3
3
|
from xarray import Dataset
|
|
4
4
|
|
|
5
5
|
from foxes.utils import wd2uv, write_nc
|
|
6
|
+
from foxes.config import config
|
|
6
7
|
import foxes.variables as FV
|
|
7
8
|
import foxes.constants as FC
|
|
8
9
|
|
|
@@ -151,7 +152,7 @@ def get_grid_xy(
|
|
|
151
152
|
N_x, N_y = len(x_pos), len(y_pos)
|
|
152
153
|
n_pts = len(x_pos) * len(y_pos)
|
|
153
154
|
z_pos = 0.5 * (z_min + z_max)
|
|
154
|
-
g_pts = np.zeros((n_states, N_x, N_y, 3), dtype=
|
|
155
|
+
g_pts = np.zeros((n_states, N_x, N_y, 3), dtype=config.dtype_double)
|
|
155
156
|
g_pts[:, :, :, 0] = x_pos[None, :, None]
|
|
156
157
|
g_pts[:, :, :, 1] = y_pos[None, None, :]
|
|
157
158
|
g_pts[:, :, :, 2] = z_pos
|
|
@@ -248,7 +249,7 @@ def get_grid_xz(
|
|
|
248
249
|
n_y = np.cross(n_z, n_x)
|
|
249
250
|
|
|
250
251
|
# project to axes:
|
|
251
|
-
xyz = np.zeros((n_states, n_turbines, 3), dtype=
|
|
252
|
+
xyz = np.zeros((n_states, n_turbines, 3), dtype=config.dtype_double)
|
|
252
253
|
xyz[:, :, 0] = farm_results[FV.X]
|
|
253
254
|
xyz[:, :, 1] = farm_results[FV.Y]
|
|
254
255
|
xyz[:, :, 2] = farm_results[FV.H]
|
|
@@ -297,7 +298,7 @@ def get_grid_xz(
|
|
|
297
298
|
N_x, N_z = len(x_pos), len(z_pos)
|
|
298
299
|
n_pts = len(x_pos) * len(z_pos)
|
|
299
300
|
y_pos = 0.5 * (y_min + y_max)
|
|
300
|
-
g_pts = np.zeros((n_states, N_x, N_z, 3), dtype=
|
|
301
|
+
g_pts = np.zeros((n_states, N_x, N_z, 3), dtype=config.dtype_double)
|
|
301
302
|
g_pts[:] += x_pos[None, :, None, None] * n_x[None, None, None, :]
|
|
302
303
|
g_pts[:] += y_pos * n_y[None, None, None, :]
|
|
303
304
|
g_pts[:] += z_pos[None, None, :, None] * n_z[None, None, None, :]
|
|
@@ -394,7 +395,7 @@ def get_grid_yz(
|
|
|
394
395
|
n_y = np.cross(n_z, n_x)
|
|
395
396
|
|
|
396
397
|
# project to axes:
|
|
397
|
-
xyz = np.zeros((n_states, n_turbines, 3), dtype=
|
|
398
|
+
xyz = np.zeros((n_states, n_turbines, 3), dtype=config.dtype_double)
|
|
398
399
|
xyz[:, :, 0] = farm_results[FV.X]
|
|
399
400
|
xyz[:, :, 1] = farm_results[FV.Y]
|
|
400
401
|
xyz[:, :, 2] = farm_results[FV.H]
|
|
@@ -443,7 +444,7 @@ def get_grid_yz(
|
|
|
443
444
|
N_y, N_z = len(y_pos), len(z_pos)
|
|
444
445
|
n_pts = len(y_pos) * len(z_pos)
|
|
445
446
|
x_pos = 0.5 * (x_min + x_max)
|
|
446
|
-
g_pts = np.zeros((n_states, N_y, N_z, 3), dtype=
|
|
447
|
+
g_pts = np.zeros((n_states, N_y, N_z, 3), dtype=config.dtype_double)
|
|
447
448
|
g_pts[:] += x_pos * n_x[None, None, None, :]
|
|
448
449
|
g_pts[:] += y_pos[None, :, None, None] * n_y[None, None, None, :]
|
|
449
450
|
g_pts[:] += z_pos[None, None, :, None] * n_z[None, None, None, :]
|
|
@@ -491,7 +492,7 @@ def np2np_p(data, a_pos, b_pos):
|
|
|
491
492
|
n_a = len(a_pos)
|
|
492
493
|
n_b = len(b_pos)
|
|
493
494
|
n_v = len(data)
|
|
494
|
-
out = np.zeros((n_a, n_b, n_v), dtype=
|
|
495
|
+
out = np.zeros((n_a, n_b, n_v), dtype=config.dtype_double)
|
|
495
496
|
for vi, (v, d) in enumerate(data.items()):
|
|
496
497
|
out[:, :, vi] = d.reshape(n_a, n_b)
|
|
497
498
|
return out
|
|
@@ -526,7 +527,7 @@ def np2np_sp(data, states, a_pos, b_pos):
|
|
|
526
527
|
n_a = len(a_pos)
|
|
527
528
|
n_b = len(b_pos)
|
|
528
529
|
n_v = len(data)
|
|
529
|
-
out = np.zeros((n_s, n_a, n_b, n_v), dtype=
|
|
530
|
+
out = np.zeros((n_s, n_a, n_b, n_v), dtype=config.dtype_double)
|
|
530
531
|
for vi, (v, d) in enumerate(data.items()):
|
|
531
532
|
out[:, :, :, vi] = d.reshape(n_s, n_a, n_b)
|
|
532
533
|
return out
|
foxes/output/output.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
|
+
from foxes.config import config, get_path
|
|
3
4
|
from foxes.utils import PandasFileHelper, all_subclasses
|
|
4
5
|
|
|
5
6
|
|
|
@@ -33,9 +34,13 @@ class Output:
|
|
|
33
34
|
Modifies file names by f(fname)
|
|
34
35
|
|
|
35
36
|
"""
|
|
36
|
-
self.out_dir =
|
|
37
|
+
self.out_dir = get_path(out_dir) if out_dir is not None else config.out_dir
|
|
37
38
|
self.out_fname_fun = out_fname_fun
|
|
38
39
|
|
|
40
|
+
if not self.out_dir.is_dir():
|
|
41
|
+
print(f"{type(self).__name__}: Creating output dir {self.out_dir}")
|
|
42
|
+
self.out_dir.mkdir(parents=True)
|
|
43
|
+
|
|
39
44
|
def get_fpath(self, fname):
|
|
40
45
|
"""
|
|
41
46
|
Gets the total file path
|
|
@@ -54,7 +59,7 @@ class Output:
|
|
|
54
59
|
fnm = Path(fname)
|
|
55
60
|
if self.out_fname_fun is not None:
|
|
56
61
|
fnm = self.out_fname_fun(fnm)
|
|
57
|
-
return self.out_dir / fnm if self.out_dir is not None else fnm
|
|
62
|
+
return self.out_dir / fnm if self.out_dir is not None else get_path(fnm)
|
|
58
63
|
|
|
59
64
|
def write(self, file_name, data, format_col2var={}, format_dict={}, **kwargs):
|
|
60
65
|
"""
|
foxes/output/results_writer.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
from xarray import Dataset
|
|
3
3
|
|
|
4
|
-
import foxes.constants as FC
|
|
5
4
|
from foxes.utils import write_nc
|
|
5
|
+
import foxes.constants as FC
|
|
6
6
|
|
|
7
7
|
from .output import Output
|
|
8
8
|
|
|
@@ -70,7 +70,7 @@ class ResultsWriter(Output):
|
|
|
70
70
|
|
|
71
71
|
def write_csv(
|
|
72
72
|
self,
|
|
73
|
-
|
|
73
|
+
file_name,
|
|
74
74
|
variables=None,
|
|
75
75
|
turbine_names=False,
|
|
76
76
|
state_turbine_table=False,
|
|
@@ -82,8 +82,8 @@ class ResultsWriter(Output):
|
|
|
82
82
|
|
|
83
83
|
Parameters
|
|
84
84
|
----------
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
file_name: str
|
|
86
|
+
Name of the csv file
|
|
87
87
|
variables: dict or list of str, optional
|
|
88
88
|
The variables to be written. If a dict, then
|
|
89
89
|
the keys are the foxes variables and the values
|
|
@@ -101,7 +101,7 @@ class ResultsWriter(Output):
|
|
|
101
101
|
|
|
102
102
|
"""
|
|
103
103
|
if verbosity:
|
|
104
|
-
print(f"ResultsWriter: Writing file '{
|
|
104
|
+
print(f"ResultsWriter: Writing file '{file_name}'")
|
|
105
105
|
|
|
106
106
|
data, variables = self._get_data_vars(variables)
|
|
107
107
|
data.reset_index(inplace=True)
|
|
@@ -133,12 +133,11 @@ class ResultsWriter(Output):
|
|
|
133
133
|
else:
|
|
134
134
|
data.set_index([FC.STATE, tix], inplace=True)
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
super().write(fpath, data, format_col2var=fc2v, **kwargs)
|
|
136
|
+
super().write(file_name, data, format_col2var=fc2v, **kwargs)
|
|
138
137
|
|
|
139
138
|
def write_nc(
|
|
140
139
|
self,
|
|
141
|
-
|
|
140
|
+
file_name,
|
|
142
141
|
variables=None,
|
|
143
142
|
turbine_names=False,
|
|
144
143
|
verbosity=1,
|
|
@@ -149,8 +148,8 @@ class ResultsWriter(Output):
|
|
|
149
148
|
|
|
150
149
|
Parameters
|
|
151
150
|
----------
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
file_name: str
|
|
152
|
+
The nc file name
|
|
154
153
|
variables: dict or list of str, optional
|
|
155
154
|
The variables to be written. If a dict, then
|
|
156
155
|
the keys are the foxes variables and the values
|
|
@@ -185,5 +184,5 @@ class ResultsWriter(Output):
|
|
|
185
184
|
},
|
|
186
185
|
)
|
|
187
186
|
|
|
188
|
-
fpath = self.get_fpath(
|
|
187
|
+
fpath = self.get_fpath(file_name)
|
|
189
188
|
write_nc(ds, fpath, verbosity=verbosity, **kwargs)
|
foxes/output/rose_plot.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import pandas as pd
|
|
3
3
|
|
|
4
|
-
import foxes.variables as FV
|
|
5
|
-
import foxes.constants as FC
|
|
6
4
|
from foxes.utils import wd2uv, uv2wd, TabWindroseAxes
|
|
7
5
|
from foxes.algorithms import Downwind
|
|
8
6
|
from foxes.core import WindFarm, Turbine
|
|
9
7
|
from foxes.models import ModelBook
|
|
8
|
+
import foxes.variables as FV
|
|
9
|
+
import foxes.constants as FC
|
|
10
|
+
|
|
10
11
|
from .output import Output
|
|
11
12
|
|
|
12
13
|
|
|
@@ -23,7 +24,7 @@ class RosePlotOutput(Output):
|
|
|
23
24
|
|
|
24
25
|
"""
|
|
25
26
|
|
|
26
|
-
def __init__(self, results):
|
|
27
|
+
def __init__(self, results, **kwargs):
|
|
27
28
|
"""
|
|
28
29
|
Constructor.
|
|
29
30
|
|
|
@@ -31,8 +32,11 @@ class RosePlotOutput(Output):
|
|
|
31
32
|
----------
|
|
32
33
|
results: xarray.Dataset
|
|
33
34
|
The calculation results (farm or points)
|
|
35
|
+
kwargs: dict, optional
|
|
36
|
+
Additional parameters for the base class
|
|
34
37
|
|
|
35
38
|
"""
|
|
39
|
+
super().__init__(**kwargs)
|
|
36
40
|
dims = list(results.sizes.keys())
|
|
37
41
|
if dims[1] == FC.TURBINE:
|
|
38
42
|
self._rtype = FC.TURBINE
|
|
@@ -324,7 +328,7 @@ class RosePlotOutput(Output):
|
|
|
324
328
|
Parameters
|
|
325
329
|
----------
|
|
326
330
|
file_name: str
|
|
327
|
-
|
|
331
|
+
Name of the output file
|
|
328
332
|
sectors: int
|
|
329
333
|
The number of wind direction sectors
|
|
330
334
|
var: str
|
|
@@ -350,31 +354,45 @@ class RosePlotOutput(Output):
|
|
|
350
354
|
ret_data=ret_data,
|
|
351
355
|
**kwargs,
|
|
352
356
|
)
|
|
357
|
+
fpath = self.get_fpath(file_name)
|
|
353
358
|
if ret_data:
|
|
354
|
-
r[0].write_image(
|
|
359
|
+
r[0].write_image(fpath)
|
|
355
360
|
return r[1]
|
|
356
361
|
else:
|
|
357
|
-
r.write_image(
|
|
362
|
+
r.write_image(fpath)
|
|
358
363
|
|
|
359
364
|
|
|
360
365
|
class StatesRosePlotOutput(RosePlotOutput):
|
|
361
366
|
"""
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
Parameters
|
|
365
|
-
----------
|
|
366
|
-
states: foxes.core.States
|
|
367
|
-
The states from which to compute the wind rose
|
|
368
|
-
point: numpy.ndarray
|
|
369
|
-
The evaluation point, shape: (3,)
|
|
370
|
-
mbook: foxes.models.ModelBook, optional
|
|
371
|
-
The model book
|
|
372
|
-
|
|
367
|
+
Class for rose plot creation directly from states
|
|
373
368
|
:group: output
|
|
374
|
-
|
|
375
369
|
"""
|
|
376
370
|
|
|
377
|
-
def __init__(
|
|
371
|
+
def __init__(
|
|
372
|
+
self,
|
|
373
|
+
states,
|
|
374
|
+
point,
|
|
375
|
+
mbook=None,
|
|
376
|
+
ws_var=FV.AMB_REWS,
|
|
377
|
+
**kwargs,
|
|
378
|
+
):
|
|
379
|
+
"""
|
|
380
|
+
Constructor.
|
|
381
|
+
|
|
382
|
+
Parameters
|
|
383
|
+
----------
|
|
384
|
+
states: foxes.core.States
|
|
385
|
+
The states from which to compute the wind rose
|
|
386
|
+
point: numpy.ndarray
|
|
387
|
+
The evaluation point, shape: (3,)
|
|
388
|
+
mbook: foxes.models.ModelBook, optional
|
|
389
|
+
The model book
|
|
390
|
+
ws_var: str
|
|
391
|
+
The wind speed variable name
|
|
392
|
+
kwargs: dict, optional
|
|
393
|
+
Additional parameters for the base class
|
|
394
|
+
|
|
395
|
+
"""
|
|
378
396
|
farm = WindFarm()
|
|
379
397
|
farm.add_turbine(
|
|
380
398
|
Turbine(
|
|
@@ -390,4 +408,4 @@ class StatesRosePlotOutput(RosePlotOutput):
|
|
|
390
408
|
|
|
391
409
|
results = algo.calc_farm(ambient=True).rename_vars({ws_var: FV.AMB_WS})
|
|
392
410
|
|
|
393
|
-
super().__init__(results)
|
|
411
|
+
super().__init__(results, **kwargs)
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import matplotlib.pyplot as plt
|
|
3
3
|
from matplotlib import colormaps
|
|
4
|
-
from matplotlib.colors import LinearSegmentedColormap
|
|
5
4
|
|
|
6
5
|
from foxes.input.states import SingleStateStates
|
|
7
6
|
from foxes.core import WindFarm
|
|
8
7
|
from foxes.algorithms import Downwind
|
|
9
8
|
|
|
9
|
+
from .output import Output
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
class RotorPointPlot(Output):
|
|
12
13
|
"""
|
|
13
14
|
Visualizes rotor points and their weights.
|
|
14
15
|
|
|
@@ -23,7 +24,7 @@ class RotorPointPlot:
|
|
|
23
24
|
|
|
24
25
|
"""
|
|
25
26
|
|
|
26
|
-
def __init__(self, rotor_model, algo=None):
|
|
27
|
+
def __init__(self, rotor_model, algo=None, **kwargs):
|
|
27
28
|
"""
|
|
28
29
|
Constructor.
|
|
29
30
|
|
|
@@ -33,8 +34,11 @@ class RotorPointPlot:
|
|
|
33
34
|
The rotor model
|
|
34
35
|
algo: foxes.core.Algorithm, optional
|
|
35
36
|
The algorithm
|
|
37
|
+
kwargs: dict, optional
|
|
38
|
+
Additional parameters for the base class
|
|
36
39
|
|
|
37
40
|
"""
|
|
41
|
+
super().__init__(**kwargs)
|
|
38
42
|
self.rotor_model = rotor_model
|
|
39
43
|
self.algo = algo
|
|
40
44
|
|
foxes/output/slice_data.py
CHANGED
|
@@ -2,6 +2,7 @@ import matplotlib.pyplot as plt
|
|
|
2
2
|
import numpy as np
|
|
3
3
|
|
|
4
4
|
import foxes.constants as FC
|
|
5
|
+
|
|
5
6
|
from .output import Output
|
|
6
7
|
|
|
7
8
|
|
|
@@ -19,7 +20,7 @@ class StateTurbineMap(Output):
|
|
|
19
20
|
|
|
20
21
|
"""
|
|
21
22
|
|
|
22
|
-
def __init__(self, farm_results):
|
|
23
|
+
def __init__(self, farm_results, **kwargs):
|
|
23
24
|
"""
|
|
24
25
|
Constructor.
|
|
25
26
|
|
|
@@ -27,8 +28,11 @@ class StateTurbineMap(Output):
|
|
|
27
28
|
----------
|
|
28
29
|
farm_results: xarray.Dataset
|
|
29
30
|
The farm results
|
|
31
|
+
kwargs: dict, optional
|
|
32
|
+
Additional parameters for the base class
|
|
30
33
|
|
|
31
34
|
"""
|
|
35
|
+
super().__init__(**kwargs)
|
|
32
36
|
self.results = farm_results
|
|
33
37
|
|
|
34
38
|
def plot_map(
|
|
@@ -19,7 +19,7 @@ class StateTurbineTable(Output):
|
|
|
19
19
|
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
def __init__(self, farm_results):
|
|
22
|
+
def __init__(self, farm_results, **kwargs):
|
|
23
23
|
"""
|
|
24
24
|
Constructor.
|
|
25
25
|
|
|
@@ -27,8 +27,11 @@ class StateTurbineTable(Output):
|
|
|
27
27
|
----------
|
|
28
28
|
farm_results: xarray.Dataset
|
|
29
29
|
The farm results
|
|
30
|
+
kwargs: dict, optional
|
|
31
|
+
Additional parameters for the base class
|
|
30
32
|
|
|
31
33
|
"""
|
|
34
|
+
super().__init__(**kwargs)
|
|
32
35
|
self.farm_results = farm_results
|
|
33
36
|
|
|
34
37
|
def get_dataset(
|
|
@@ -48,7 +51,7 @@ class StateTurbineTable(Output):
|
|
|
48
51
|
name_map: dict
|
|
49
52
|
Map from foxes to output names
|
|
50
53
|
to_file: str, optional
|
|
51
|
-
|
|
54
|
+
Name of the output file, if writing is desired
|
|
52
55
|
kwargs: dict, optional
|
|
53
56
|
Additional parameters for write_nc
|
|
54
57
|
|
|
@@ -73,6 +76,7 @@ class StateTurbineTable(Output):
|
|
|
73
76
|
)
|
|
74
77
|
|
|
75
78
|
if to_file is not None:
|
|
76
|
-
|
|
79
|
+
fpath = self.get_fpath(to_file)
|
|
80
|
+
write_nc(ds=ds, fpath=fpath, **kwargs)
|
|
77
81
|
|
|
78
82
|
return ds
|
|
@@ -7,8 +7,10 @@ from foxes.input.states import StatesTable
|
|
|
7
7
|
from foxes.core import WindFarm, Turbine
|
|
8
8
|
from foxes.algorithms import Downwind
|
|
9
9
|
from foxes.models.turbine_models import SetFarmVars
|
|
10
|
+
from foxes.config import config
|
|
10
11
|
import foxes.variables as FV
|
|
11
12
|
import foxes.constants as FC
|
|
13
|
+
|
|
12
14
|
from .output import Output
|
|
13
15
|
|
|
14
16
|
|
|
@@ -26,7 +28,7 @@ class TurbineTypeCurves(Output):
|
|
|
26
28
|
|
|
27
29
|
"""
|
|
28
30
|
|
|
29
|
-
def __init__(self, mbook):
|
|
31
|
+
def __init__(self, mbook, **kwargs):
|
|
30
32
|
"""
|
|
31
33
|
Constructor.
|
|
32
34
|
|
|
@@ -34,8 +36,11 @@ class TurbineTypeCurves(Output):
|
|
|
34
36
|
----------
|
|
35
37
|
mbook: foxes.models.ModelBook
|
|
36
38
|
The model book
|
|
39
|
+
kwargs: dict, optional
|
|
40
|
+
Additional parameters for the base class
|
|
37
41
|
|
|
38
42
|
"""
|
|
43
|
+
super().__init__(**kwargs)
|
|
39
44
|
self.mbook = mbook
|
|
40
45
|
|
|
41
46
|
def plot_curves(
|
|
@@ -113,7 +118,7 @@ class TurbineTypeCurves(Output):
|
|
|
113
118
|
if not isinstance(axs, (list, tuple, np.ndarray)):
|
|
114
119
|
axs = [axs]
|
|
115
120
|
|
|
116
|
-
ws = np.arange(ws_min, ws_max + ws_step, ws_step, dtype=
|
|
121
|
+
ws = np.arange(ws_min, ws_max + ws_step, ws_step, dtype=config.dtype_double)
|
|
117
122
|
n_states = len(ws)
|
|
118
123
|
sdata = pd.DataFrame(index=range(n_states))
|
|
119
124
|
sdata.index.name = FC.STATE
|
foxes/utils/dict.py
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
from yaml import safe_load
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
1
5
|
class Dict(dict):
|
|
2
6
|
"""
|
|
3
7
|
A slightly enhanced dictionary.
|
|
@@ -25,10 +29,34 @@ class Dict(dict):
|
|
|
25
29
|
Arguments passed to `dict`
|
|
26
30
|
|
|
27
31
|
"""
|
|
28
|
-
|
|
32
|
+
tmp = dict()
|
|
33
|
+
for a in args:
|
|
34
|
+
tmp.update(
|
|
35
|
+
{
|
|
36
|
+
k: (
|
|
37
|
+
Dict(d, name=f"{name}.{k}")
|
|
38
|
+
if isinstance(d, dict) and not isinstance(d, Dict)
|
|
39
|
+
else d
|
|
40
|
+
)
|
|
41
|
+
for k, d in a.items()
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
super().__init__(
|
|
46
|
+
**tmp,
|
|
47
|
+
**{
|
|
48
|
+
k: (
|
|
49
|
+
Dict(d, name=k)
|
|
50
|
+
if isinstance(d, dict) and not isinstance(d, Dict)
|
|
51
|
+
else d
|
|
52
|
+
)
|
|
53
|
+
for k, d in kwargs.items()
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
|
|
29
57
|
self.name = name if name is not None else type(self).__name__
|
|
30
58
|
|
|
31
|
-
def get_item(self, key, prnt=True):
|
|
59
|
+
def get_item(self, key, *deflt, prnt=True):
|
|
32
60
|
"""
|
|
33
61
|
Gets an item, prints readable error if not found
|
|
34
62
|
|
|
@@ -36,12 +64,25 @@ class Dict(dict):
|
|
|
36
64
|
----------
|
|
37
65
|
key: immutable object
|
|
38
66
|
The key
|
|
67
|
+
deflt: tuple, optional
|
|
68
|
+
Tuple of length 1, containing the default
|
|
39
69
|
prnt: bool
|
|
40
70
|
Flag for message printing
|
|
41
71
|
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
data: object
|
|
75
|
+
The data
|
|
76
|
+
|
|
42
77
|
"""
|
|
43
78
|
try:
|
|
44
|
-
|
|
79
|
+
if len(deflt):
|
|
80
|
+
assert (
|
|
81
|
+
len(deflt) == 1
|
|
82
|
+
), f"Expecting a single default entry, got {len(deflt)}"
|
|
83
|
+
data = self.get(key, deflt[0])
|
|
84
|
+
else:
|
|
85
|
+
data = self[key]
|
|
45
86
|
except KeyError as e:
|
|
46
87
|
if prnt:
|
|
47
88
|
print(f"\n{self.name}: Cannot find key '{key}'.\n")
|
|
@@ -51,6 +92,35 @@ class Dict(dict):
|
|
|
51
92
|
print()
|
|
52
93
|
raise e
|
|
53
94
|
|
|
95
|
+
if isinstance(data, dict) and not isinstance(data, Dict):
|
|
96
|
+
data = Dict(data, name=f"{self.name}.{key}")
|
|
97
|
+
|
|
98
|
+
return data
|
|
99
|
+
|
|
100
|
+
def pop_item(self, key, *deflt, prnt=True):
|
|
101
|
+
"""
|
|
102
|
+
Pops an item, prints readable error if not found
|
|
103
|
+
|
|
104
|
+
Parameters
|
|
105
|
+
----------
|
|
106
|
+
key: immutable object
|
|
107
|
+
The key
|
|
108
|
+
deflt: tuple, optional
|
|
109
|
+
Tuple of length 1, containing the default
|
|
110
|
+
prnt: bool
|
|
111
|
+
Flag for message printing
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
data: object
|
|
116
|
+
The data
|
|
117
|
+
|
|
118
|
+
"""
|
|
119
|
+
data = self.get_item(key, *deflt, prnt=prnt)
|
|
120
|
+
if key in self:
|
|
121
|
+
del self[key]
|
|
122
|
+
return data
|
|
123
|
+
|
|
54
124
|
def __getitem__(self, key):
|
|
55
125
|
try:
|
|
56
126
|
return super().__getitem__(key)
|
|
@@ -58,3 +128,37 @@ class Dict(dict):
|
|
|
58
128
|
k = ", ".join(sorted([f"{s}" for s in self.keys()]))
|
|
59
129
|
e = f"{self.name}: Cannot find key '{key}'. Known keys: {k}"
|
|
60
130
|
raise KeyError(e)
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def from_yaml(self, yml_file, verbosity=1):
|
|
134
|
+
"""
|
|
135
|
+
Reads a yaml file
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
yml_file: str
|
|
140
|
+
Path to the yaml file
|
|
141
|
+
verbosity: int
|
|
142
|
+
The verbosity level, 0 = silent
|
|
143
|
+
|
|
144
|
+
Returns
|
|
145
|
+
-------
|
|
146
|
+
dct: Dict
|
|
147
|
+
The data
|
|
148
|
+
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
def _print(*args, level=1, **kwargs):
|
|
152
|
+
if verbosity >= level:
|
|
153
|
+
print(*args, **kwargs)
|
|
154
|
+
|
|
155
|
+
fpath = Path(yml_file)
|
|
156
|
+
_print("Reading file", fpath)
|
|
157
|
+
with open(fpath) as stream:
|
|
158
|
+
data = safe_load(stream)
|
|
159
|
+
if data is None:
|
|
160
|
+
data = {}
|
|
161
|
+
dct = Dict(data, name=fpath.stem)
|
|
162
|
+
_print(dct, level=2)
|
|
163
|
+
|
|
164
|
+
return dct
|
foxes/utils/geopandas_utils.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import argparse
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
from foxes.config import config
|
|
5
|
+
|
|
5
6
|
from .dict import Dict
|
|
6
7
|
from .geom2d import AreaUnion, ClosedPolygon
|
|
7
8
|
|
|
@@ -212,7 +213,7 @@ def read_shp_polygons(
|
|
|
212
213
|
if not len(data):
|
|
213
214
|
return []
|
|
214
215
|
if isinstance(data[0], tuple):
|
|
215
|
-
out = np.array(data, dtype=
|
|
216
|
+
out = np.array(data, dtype=config.dtype_double)
|
|
216
217
|
return _to_utm(out) if apply_utm else out
|
|
217
218
|
return [_to_numpy(d) for d in data]
|
|
218
219
|
|