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 scipy.spatial.distance import cdist
|
|
|
4
4
|
from foxes.core import WakeFrame, TData
|
|
5
5
|
from foxes.utils import wd2uv
|
|
6
6
|
from foxes.algorithms.iterative import Iterative
|
|
7
|
+
from foxes.config import config
|
|
7
8
|
import foxes.variables as FV
|
|
8
9
|
import foxes.constants as FC
|
|
9
10
|
|
|
@@ -98,12 +99,14 @@ class DynamicWakes(WakeFrame):
|
|
|
98
99
|
f"{self.name}: Expecting 'dt_min' for single step timeseries"
|
|
99
100
|
)
|
|
100
101
|
self._dt = (
|
|
101
|
-
(times[1:] - times[:-1])
|
|
102
|
+
(times[1:] - times[:-1])
|
|
103
|
+
.astype("timedelta64[s]")
|
|
104
|
+
.astype(config.dtype_int)
|
|
102
105
|
)
|
|
103
106
|
else:
|
|
104
107
|
n = max(len(times) - 1, 1)
|
|
105
108
|
self._dt = np.full(n, self.dt_min * 60, dtype="timedelta64[s]").astype(
|
|
106
|
-
|
|
109
|
+
config.dtype_int
|
|
107
110
|
)
|
|
108
111
|
self._dt = np.append(self._dt, self._dt[-1, None], axis=0)
|
|
109
112
|
|
|
@@ -141,7 +144,7 @@ class DynamicWakes(WakeFrame):
|
|
|
141
144
|
The turbine order, shape: (n_states, n_turbines)
|
|
142
145
|
|
|
143
146
|
"""
|
|
144
|
-
order = np.zeros((fdata.n_states, fdata.n_turbines), dtype=
|
|
147
|
+
order = np.zeros((fdata.n_states, fdata.n_turbines), dtype=config.dtype_int)
|
|
145
148
|
order[:] = np.arange(fdata.n_turbines)[None, :]
|
|
146
149
|
return order
|
|
147
150
|
|
|
@@ -163,10 +166,15 @@ class DynamicWakes(WakeFrame):
|
|
|
163
166
|
# compute wakes that start within this chunk: x, y, z, length
|
|
164
167
|
data = algo.get_from_chunk_store(name=key, mdata=mdata, error=False)
|
|
165
168
|
if data is None:
|
|
166
|
-
data = np.full(
|
|
169
|
+
data = np.full(
|
|
170
|
+
(n_states, self.max_age, 4), np.nan, dtype=config.dtype_double
|
|
171
|
+
)
|
|
167
172
|
data[:, 0, :3] = rxyh
|
|
168
173
|
data[:, 0, 3] = 0
|
|
169
|
-
tdt = {
|
|
174
|
+
tdt = {
|
|
175
|
+
v: np.zeros((n_states, 1, 1), dtype=config.dtype_double)
|
|
176
|
+
for v in tdi.keys()
|
|
177
|
+
}
|
|
170
178
|
pts = data[:, 0, :3].copy()
|
|
171
179
|
for age in range(self.max_age - 1):
|
|
172
180
|
if age == n_states:
|
|
@@ -259,7 +267,7 @@ class DynamicWakes(WakeFrame):
|
|
|
259
267
|
n_pts = len(pts)
|
|
260
268
|
|
|
261
269
|
tdt = {
|
|
262
|
-
v: np.zeros((n_states, n_pts, 1), dtype=
|
|
270
|
+
v: np.zeros((n_states, n_pts, 1), dtype=config.dtype_double)
|
|
263
271
|
for v in algo.states.output_point_vars(algo)
|
|
264
272
|
}
|
|
265
273
|
|
|
@@ -368,9 +376,9 @@ class DynamicWakes(WakeFrame):
|
|
|
368
376
|
i0 = mdata.states_i0(counter=True)
|
|
369
377
|
|
|
370
378
|
# initialize:
|
|
371
|
-
wcoos = np.full((n_states, n_points, 3), 1e20, dtype=
|
|
379
|
+
wcoos = np.full((n_states, n_points, 3), 1e20, dtype=config.dtype_double)
|
|
372
380
|
wcoos[:, :, 2] = points[:, :, 2] - rxyh[:, None, 2]
|
|
373
|
-
wake_si = np.zeros((n_states, n_points), dtype=
|
|
381
|
+
wake_si = np.zeros((n_states, n_points), dtype=config.dtype_int)
|
|
374
382
|
wake_si[:] = i0 + np.arange(n_states)[:, None]
|
|
375
383
|
|
|
376
384
|
# find nearest wake point:
|
|
@@ -400,7 +408,7 @@ class DynamicWakes(WakeFrame):
|
|
|
400
408
|
if np.any(~sel):
|
|
401
409
|
nx[~sel] -= wdata[sts[~sel], ags[~sel] - 1, :2]
|
|
402
410
|
dx = np.linalg.norm(nx, axis=-1)
|
|
403
|
-
nx /= dx[:, None]
|
|
411
|
+
nx /= dx[:, None] + 1e-14
|
|
404
412
|
|
|
405
413
|
projx = np.einsum("sd,sd->s", dp, nx)
|
|
406
414
|
sel = (projx > -dx) & (projx < dx)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
from .rotor_wd import RotorWD
|
|
3
|
+
from foxes.config import config
|
|
5
4
|
from foxes.core import WakeFrame
|
|
6
5
|
|
|
6
|
+
from .rotor_wd import RotorWD
|
|
7
|
+
|
|
7
8
|
|
|
8
9
|
class FarmOrder(WakeFrame):
|
|
9
10
|
"""
|
|
@@ -90,7 +91,7 @@ class FarmOrder(WakeFrame):
|
|
|
90
91
|
The turbine order, shape: (n_states, n_turbines)
|
|
91
92
|
|
|
92
93
|
"""
|
|
93
|
-
order = np.zeros((fdata.n_states, fdata.n_turbines), dtype=
|
|
94
|
+
order = np.zeros((fdata.n_states, fdata.n_turbines), dtype=config.dtype_int)
|
|
94
95
|
order[:] = np.arange(fdata.n_turbines)[None, :]
|
|
95
96
|
|
|
96
97
|
return order
|
|
@@ -2,6 +2,8 @@ import numpy as np
|
|
|
2
2
|
|
|
3
3
|
from foxes.core import WakeFrame
|
|
4
4
|
from foxes.utils import wd2uv
|
|
5
|
+
from foxes.config import config
|
|
6
|
+
|
|
5
7
|
import foxes.variables as FV
|
|
6
8
|
import foxes.constants as FC
|
|
7
9
|
|
|
@@ -104,7 +106,7 @@ class RotorWD(WakeFrame):
|
|
|
104
106
|
|
|
105
107
|
wd = fdata[self.var_wd][:, downwind_index]
|
|
106
108
|
|
|
107
|
-
nax = np.zeros((n_states, 3, 3), dtype=
|
|
109
|
+
nax = np.zeros((n_states, 3, 3), dtype=config.dtype_double)
|
|
108
110
|
n = nax[:, 0, :2]
|
|
109
111
|
n[:] = wd2uv(wd, axis=-1)
|
|
110
112
|
m = nax[:, 1, :2]
|
|
@@ -3,9 +3,10 @@ from scipy.spatial.distance import cdist
|
|
|
3
3
|
|
|
4
4
|
from foxes.utils import wd2uv
|
|
5
5
|
from foxes.core.data import TData
|
|
6
|
+
from foxes.config import config
|
|
7
|
+
from foxes.algorithms.sequential import Sequential
|
|
6
8
|
import foxes.variables as FV
|
|
7
9
|
import foxes.constants as FC
|
|
8
|
-
from foxes.algorithms.sequential import Sequential
|
|
9
10
|
|
|
10
11
|
from .farm_order import FarmOrder
|
|
11
12
|
|
|
@@ -80,19 +81,25 @@ class SeqDynamicWakes(FarmOrder):
|
|
|
80
81
|
f"{self.name}: Expecting 'dt_min' for single step timeseries"
|
|
81
82
|
)
|
|
82
83
|
self._dt = (
|
|
83
|
-
(times[1:] - times[:-1])
|
|
84
|
+
(times[1:] - times[:-1])
|
|
85
|
+
.astype("timedelta64[s]")
|
|
86
|
+
.astype(config.dtype_int)
|
|
84
87
|
)
|
|
85
88
|
else:
|
|
86
89
|
n = max(len(times) - 1, 1)
|
|
87
90
|
self._dt = np.full(n, self.dt_min * 60, dtype="timedelta64[s]").astype(
|
|
88
|
-
|
|
91
|
+
config.dtype_int
|
|
89
92
|
)
|
|
90
93
|
|
|
91
94
|
# init wake traces data:
|
|
92
|
-
self._traces_p = np.zeros(
|
|
93
|
-
|
|
95
|
+
self._traces_p = np.zeros(
|
|
96
|
+
(algo.n_states, algo.n_turbines, 3), dtype=config.dtype_double
|
|
97
|
+
)
|
|
98
|
+
self._traces_v = np.zeros(
|
|
99
|
+
(algo.n_states, algo.n_turbines, 3), dtype=config.dtype_double
|
|
100
|
+
)
|
|
94
101
|
self._traces_l = np.full(
|
|
95
|
-
(algo.n_states, algo.n_turbines), np.nan, dtype=
|
|
102
|
+
(algo.n_states, algo.n_turbines), np.nan, dtype=config.dtype_double
|
|
96
103
|
)
|
|
97
104
|
|
|
98
105
|
def calc_order(self, algo, mdata, fdata):
|
|
@@ -192,7 +199,7 @@ class SeqDynamicWakes(FarmOrder):
|
|
|
192
199
|
del dists
|
|
193
200
|
|
|
194
201
|
# project:
|
|
195
|
-
wcoos = np.full((n_states, n_points, 3), 1e20, dtype=
|
|
202
|
+
wcoos = np.full((n_states, n_points, 3), 1e20, dtype=config.dtype_double)
|
|
196
203
|
wcoos[0, :, 2] = points[0, :, 2] - fdata[FV.TXYH][0, downwind_index, None, 2]
|
|
197
204
|
nx = self._traces_v[tri, downwind_index, :2]
|
|
198
205
|
mv = np.linalg.norm(nx, axis=-1)
|
|
@@ -4,6 +4,7 @@ from scipy.interpolate import interpn
|
|
|
4
4
|
from foxes.core import WakeFrame
|
|
5
5
|
from foxes.utils import wd2uv
|
|
6
6
|
from foxes.core.data import TData
|
|
7
|
+
from foxes.config import config
|
|
7
8
|
import foxes.variables as FV
|
|
8
9
|
import foxes.constants as FC
|
|
9
10
|
|
|
@@ -64,7 +65,7 @@ class Streamlines2D(WakeFrame):
|
|
|
64
65
|
N = int(self.max_length_km * 1e3 / self.step)
|
|
65
66
|
|
|
66
67
|
# calc data: x, y, z, wd
|
|
67
|
-
data = np.zeros((n_states, n_turbines, N, 4), dtype=
|
|
68
|
+
data = np.zeros((n_states, n_turbines, N, 4), dtype=config.dtype_double)
|
|
68
69
|
for i in range(N):
|
|
69
70
|
|
|
70
71
|
# set streamline start point data (rotor centre):
|
|
@@ -86,7 +87,9 @@ class Streamlines2D(WakeFrame):
|
|
|
86
87
|
tdata = TData.from_points(
|
|
87
88
|
data[:, :, i, :3],
|
|
88
89
|
data={
|
|
89
|
-
v: np.full(
|
|
90
|
+
v: np.full(
|
|
91
|
+
(n_states, n_turbines, 1), np.nan, dtype=config.dtype_double
|
|
92
|
+
)
|
|
90
93
|
for v in svars
|
|
91
94
|
},
|
|
92
95
|
dims={v: (FC.STATE, FC.TARGET, FC.TPOINT) for v in svars},
|
|
@@ -151,7 +154,7 @@ class Streamlines2D(WakeFrame):
|
|
|
151
154
|
del dists, selp
|
|
152
155
|
|
|
153
156
|
# calculate coordinates:
|
|
154
|
-
coos = np.full((n_states, n_points, 3), np.nan, dtype=
|
|
157
|
+
coos = np.full((n_states, n_points, 3), np.nan, dtype=config.dtype_double)
|
|
155
158
|
coos[:, :, 2] = points[:, :, 2] - data[:, :, 2]
|
|
156
159
|
delta = points[:, :, :2] - data[:, :, :2]
|
|
157
160
|
nx = wd2uv(data[:, :, 3])
|
|
@@ -193,7 +196,7 @@ class Streamlines2D(WakeFrame):
|
|
|
193
196
|
|
|
194
197
|
# calculate streamline x coordinates for turbines rotor centre points:
|
|
195
198
|
# n_states, n_turbines_source, n_turbines_target
|
|
196
|
-
coosx = np.zeros((n_states, n_turbines, n_turbines), dtype=
|
|
199
|
+
coosx = np.zeros((n_states, n_turbines, n_turbines), dtype=config.dtype_double)
|
|
197
200
|
for ti in range(n_turbines):
|
|
198
201
|
coosx[:, ti, :] = self.get_wake_coos(algo, mdata, fdata, tdata, ti)[
|
|
199
202
|
:, :, 0, 0
|
|
@@ -201,7 +204,7 @@ class Streamlines2D(WakeFrame):
|
|
|
201
204
|
|
|
202
205
|
# derive turbine order:
|
|
203
206
|
# TODO: Remove loop over states
|
|
204
|
-
order = np.zeros((n_states, n_turbines), dtype=
|
|
207
|
+
order = np.zeros((n_states, n_turbines), dtype=config.dtype_int)
|
|
205
208
|
for si in range(n_states):
|
|
206
209
|
order[si] = np.lexsort(keys=coosx[si])
|
|
207
210
|
|
|
@@ -273,7 +276,7 @@ class Streamlines2D(WakeFrame):
|
|
|
273
276
|
xs = self.step * np.arange(n_spts)
|
|
274
277
|
|
|
275
278
|
# interpolate to x of interest:
|
|
276
|
-
qts = np.zeros((n_states, n_points, 2), dtype=
|
|
279
|
+
qts = np.zeros((n_states, n_points, 2), dtype=config.dtype_double)
|
|
277
280
|
qts[:, :, 0] = np.arange(n_states)[:, None]
|
|
278
281
|
qts[:, :, 1] = np.minimum(x, xs[-1])
|
|
279
282
|
qts = qts.reshape(n_states * n_points, 2)
|
|
@@ -4,6 +4,7 @@ from xarray import Dataset
|
|
|
4
4
|
from foxes.core import WakeFrame, MData, FData, TData
|
|
5
5
|
from foxes.utils import wd2uv
|
|
6
6
|
from foxes.algorithms.iterative import Iterative
|
|
7
|
+
from foxes.config import config
|
|
7
8
|
import foxes.variables as FV
|
|
8
9
|
import foxes.constants as FC
|
|
9
10
|
|
|
@@ -69,10 +70,16 @@ class Timelines(WakeFrame):
|
|
|
69
70
|
raise KeyError(
|
|
70
71
|
f"{self.name}: Expecting 'dt_min' for single step timeseries"
|
|
71
72
|
)
|
|
72
|
-
dt = (
|
|
73
|
+
dt = (
|
|
74
|
+
(times[1:] - times[:-1])
|
|
75
|
+
.astype("timedelta64[s]")
|
|
76
|
+
.astype(config.dtype_int)
|
|
77
|
+
)
|
|
73
78
|
else:
|
|
74
79
|
n = max(len(times) - 1, 1)
|
|
75
|
-
dt = np.full(n, self.dt_min * 60, dtype="timedelta64[s]").astype(
|
|
80
|
+
dt = np.full(n, self.dt_min * 60, dtype="timedelta64[s]").astype(
|
|
81
|
+
config.dtype_int
|
|
82
|
+
)
|
|
76
83
|
|
|
77
84
|
# prepare mdata:
|
|
78
85
|
data = algo.get_model_data(states)["coords"]
|
|
@@ -90,11 +97,11 @@ class Timelines(WakeFrame):
|
|
|
90
97
|
# prepare tdata:
|
|
91
98
|
n_states = states.size()
|
|
92
99
|
data = {
|
|
93
|
-
v: np.zeros((n_states, 1, 1), dtype=
|
|
100
|
+
v: np.zeros((n_states, 1, 1), dtype=config.dtype_double)
|
|
94
101
|
for v in states.output_point_vars(algo)
|
|
95
102
|
}
|
|
96
103
|
pdims = {v: (FC.STATE, FC.TARGET, FC.TPOINT) for v in data.keys()}
|
|
97
|
-
points = np.zeros((n_states, 1, 3), dtype=
|
|
104
|
+
points = np.zeros((n_states, 1, 3), dtype=config.dtype_double)
|
|
98
105
|
|
|
99
106
|
# calculate all heights:
|
|
100
107
|
self.timelines_data = {"dxy": (("height", FC.STATE, "dir"), [])}
|
|
@@ -175,7 +182,7 @@ class Timelines(WakeFrame):
|
|
|
175
182
|
super().initialize(algo, verbosity)
|
|
176
183
|
|
|
177
184
|
# find turbine hub heights:
|
|
178
|
-
t2h = np.zeros(algo.n_turbines, dtype=
|
|
185
|
+
t2h = np.zeros(algo.n_turbines, dtype=config.dtype_double)
|
|
179
186
|
for ti, t in enumerate(algo.farm.turbines):
|
|
180
187
|
t2h[ti] = (
|
|
181
188
|
t.H if t.H is not None else algo.farm_controller.turbine_types[ti].H
|
|
@@ -285,7 +292,7 @@ class Timelines(WakeFrame):
|
|
|
285
292
|
The turbine order, shape: (n_states, n_turbines)
|
|
286
293
|
|
|
287
294
|
"""
|
|
288
|
-
order = np.zeros((fdata.n_states, fdata.n_turbines), dtype=
|
|
295
|
+
order = np.zeros((fdata.n_states, fdata.n_turbines), dtype=config.dtype_int)
|
|
289
296
|
order[:] = np.arange(fdata.n_turbines)[None, :]
|
|
290
297
|
return order
|
|
291
298
|
|
|
@@ -331,26 +338,26 @@ class Timelines(WakeFrame):
|
|
|
331
338
|
heights = self.timelines_data["height"].to_numpy()
|
|
332
339
|
data_dxy = self.timelines_data["dxy"].to_numpy()
|
|
333
340
|
|
|
334
|
-
D = np.zeros((n_states, n_points), dtype=
|
|
341
|
+
D = np.zeros((n_states, n_points), dtype=config.dtype_double)
|
|
335
342
|
D[:] = fdata[FV.D][:, downwind_index, None]
|
|
336
343
|
|
|
337
|
-
wcoos = np.full((n_states, n_points, 3), 1e20, dtype=
|
|
344
|
+
wcoos = np.full((n_states, n_points, 3), 1e20, dtype=config.dtype_double)
|
|
338
345
|
wcoosx = wcoos[:, :, 0]
|
|
339
346
|
wcoosy = wcoos[:, :, 1]
|
|
340
347
|
wcoos[:, :, 2] = points[:, :, 2] - rxyz[:, None, 2]
|
|
341
348
|
|
|
342
349
|
i0 = mdata.states_i0(counter=True)
|
|
343
350
|
i1 = i0 + mdata.n_states
|
|
344
|
-
trace_si = np.zeros((n_states, n_points), dtype=
|
|
351
|
+
trace_si = np.zeros((n_states, n_points), dtype=config.dtype_int)
|
|
345
352
|
trace_si[:] = i0 + np.arange(n_states)[:, None]
|
|
346
353
|
for hi, h in enumerate(heights):
|
|
347
354
|
dxy = data_dxy[hi][:i1]
|
|
348
355
|
precond = theights[:, None] == h
|
|
349
356
|
|
|
350
|
-
trace_p = np.zeros((n_states, n_points, 2), dtype=
|
|
357
|
+
trace_p = np.zeros((n_states, n_points, 2), dtype=config.dtype_double)
|
|
351
358
|
trace_p[:] = points[:, :, :2] - rxyz[:, None, :2]
|
|
352
|
-
trace_l = np.zeros((n_states, n_points), dtype=
|
|
353
|
-
trace_d = np.full((n_states, n_points), np.inf, dtype=
|
|
359
|
+
trace_l = np.zeros((n_states, n_points), dtype=config.dtype_double)
|
|
360
|
+
trace_d = np.full((n_states, n_points), np.inf, dtype=config.dtype_double)
|
|
354
361
|
h_trace_si = trace_si.copy()
|
|
355
362
|
|
|
356
363
|
# flake8: noqa: F821
|
|
@@ -446,12 +453,12 @@ class Timelines(WakeFrame):
|
|
|
446
453
|
heights = self.timelines_data["height"].to_numpy()
|
|
447
454
|
data_dxy = self.timelines_data["dxy"].to_numpy()
|
|
448
455
|
|
|
449
|
-
points = np.zeros((n_states, n_points, 3), dtype=
|
|
456
|
+
points = np.zeros((n_states, n_points, 3), dtype=config.dtype_double)
|
|
450
457
|
points[:] = rxyz[:, None, :]
|
|
451
458
|
|
|
452
459
|
trace_dp = np.zeros_like(points[..., :2])
|
|
453
460
|
trace_l = x.copy()
|
|
454
|
-
trace_si = np.zeros((n_states, n_points), dtype=
|
|
461
|
+
trace_si = np.zeros((n_states, n_points), dtype=config.dtype_int)
|
|
455
462
|
trace_si[:] = np.arange(n_states)[:, None]
|
|
456
463
|
|
|
457
464
|
for hi, h in enumerate(heights):
|
|
@@ -5,8 +5,10 @@ from foxes.models.wake_models.wind.bastankhah16 import (
|
|
|
5
5
|
Bastankhah2016Model,
|
|
6
6
|
Bastankhah2016,
|
|
7
7
|
)
|
|
8
|
+
from foxes.config import config
|
|
8
9
|
import foxes.variables as FV
|
|
9
10
|
import foxes.constants as FC
|
|
11
|
+
|
|
10
12
|
from .rotor_wd import RotorWD
|
|
11
13
|
|
|
12
14
|
|
|
@@ -200,7 +202,7 @@ class YawedWakes(WakeFrame):
|
|
|
200
202
|
if np.any(st_sel):
|
|
201
203
|
# prepare:
|
|
202
204
|
n_st_sel = np.sum(st_sel)
|
|
203
|
-
ydef = np.zeros((n_st_sel,), dtype=
|
|
205
|
+
ydef = np.zeros((n_st_sel,), dtype=config.dtype_double)
|
|
204
206
|
|
|
205
207
|
# collect data:
|
|
206
208
|
near = self.model.get_data(Bastankhah2016Model.NEAR, mdata)
|
|
@@ -2,6 +2,7 @@ import numpy as np
|
|
|
2
2
|
|
|
3
3
|
from foxes.core import WakeK
|
|
4
4
|
from foxes.models.wake_models.top_hat import TopHatWakeModel
|
|
5
|
+
from foxes.config import config
|
|
5
6
|
import foxes.variables as FV
|
|
6
7
|
import foxes.constants as FC
|
|
7
8
|
|
|
@@ -299,7 +300,7 @@ class CrespoHernandezTIWake(TopHatWakeModel):
|
|
|
299
300
|
twoa = 2 * self.induction.ct2a(ct)
|
|
300
301
|
|
|
301
302
|
# prepare output:
|
|
302
|
-
wake_deltas = np.zeros(n_targts, dtype=
|
|
303
|
+
wake_deltas = np.zeros(n_targts, dtype=config.dtype_double)
|
|
303
304
|
|
|
304
305
|
# calc near wake length, if not given
|
|
305
306
|
if self.near_wake_D is None:
|
|
@@ -2,6 +2,7 @@ import numpy as np
|
|
|
2
2
|
|
|
3
3
|
from foxes.core import WakeK
|
|
4
4
|
from foxes.models.wake_models.gaussian import GaussianWakeModel
|
|
5
|
+
from foxes.config import config
|
|
5
6
|
import foxes.variables as FV
|
|
6
7
|
import foxes.constants as FC
|
|
7
8
|
|
|
@@ -187,7 +188,7 @@ class Bastankhah2014(GaussianWakeModel):
|
|
|
187
188
|
else:
|
|
188
189
|
st_sel = np.zeros_like(x, dtype=bool)
|
|
189
190
|
n_sp = np.sum(st_sel)
|
|
190
|
-
ampld = np.zeros(n_sp, dtype=
|
|
191
|
-
sigma = np.zeros(n_sp, dtype=
|
|
191
|
+
ampld = np.zeros(n_sp, dtype=config.dtype_double)
|
|
192
|
+
sigma = np.zeros(n_sp, dtype=config.dtype_double)
|
|
192
193
|
|
|
193
194
|
return {FV.WS: (ampld, sigma)}, st_sel
|
|
@@ -2,6 +2,7 @@ import numpy as np
|
|
|
2
2
|
|
|
3
3
|
from foxes.models.wake_models.dist_sliced import DistSlicedWakeModel
|
|
4
4
|
from foxes.core import Model, WakeK
|
|
5
|
+
from foxes.config import config
|
|
5
6
|
import foxes.variables as FV
|
|
6
7
|
import foxes.constants as FC
|
|
7
8
|
|
|
@@ -570,7 +571,7 @@ class Bastankhah2016(DistSlicedWakeModel):
|
|
|
570
571
|
# select targets:
|
|
571
572
|
st_sel = self.model.get_data(Bastankhah2016Model.ST_SEL, mdata)
|
|
572
573
|
n_sp_sel = np.sum(st_sel)
|
|
573
|
-
wdeltas = {FV.WS: np.zeros((n_sp_sel, n_y_per_z), dtype=
|
|
574
|
+
wdeltas = {FV.WS: np.zeros((n_sp_sel, n_y_per_z), dtype=config.dtype_double)}
|
|
574
575
|
if np.any(st_sel):
|
|
575
576
|
# apply filter:
|
|
576
577
|
yz = yz[st_sel]
|
|
@@ -2,6 +2,7 @@ import numpy as np
|
|
|
2
2
|
|
|
3
3
|
from foxes.core import WakeK
|
|
4
4
|
from foxes.models.wake_models.gaussian import GaussianWakeModel
|
|
5
|
+
from foxes.config import config
|
|
5
6
|
import foxes.variables as FV
|
|
6
7
|
import foxes.constants as FC
|
|
7
8
|
|
|
@@ -188,8 +189,7 @@ class TurbOParkWake(GaussianWakeModel):
|
|
|
188
189
|
fdata=fdata,
|
|
189
190
|
tdata=tdata,
|
|
190
191
|
downwind_index=downwind_index,
|
|
191
|
-
upcast=
|
|
192
|
-
selection=st_sel,
|
|
192
|
+
upcast=True,
|
|
193
193
|
)
|
|
194
194
|
|
|
195
195
|
# get k:
|
|
@@ -211,6 +211,7 @@ class TurbOParkWake(GaussianWakeModel):
|
|
|
211
211
|
epsilon = self.sbeta_factor * np.sqrt(beta)
|
|
212
212
|
del a, beta
|
|
213
213
|
|
|
214
|
+
ati = ati[st_sel]
|
|
214
215
|
alpha = self.c1 * ati
|
|
215
216
|
beta = self.c2 * ati / np.sqrt(ct)
|
|
216
217
|
|
|
@@ -218,7 +219,6 @@ class TurbOParkWake(GaussianWakeModel):
|
|
|
218
219
|
sigma = D * (
|
|
219
220
|
epsilon
|
|
220
221
|
+ k
|
|
221
|
-
* ati
|
|
222
222
|
/ beta
|
|
223
223
|
* (
|
|
224
224
|
np.sqrt((alpha + beta * x / D) ** 2 + 1)
|
|
@@ -246,8 +246,8 @@ class TurbOParkWake(GaussianWakeModel):
|
|
|
246
246
|
else:
|
|
247
247
|
st_sel = np.zeros_like(x, dtype=bool)
|
|
248
248
|
n_sp = np.sum(st_sel)
|
|
249
|
-
ampld = np.zeros(n_sp, dtype=
|
|
250
|
-
sigma = np.zeros(n_sp, dtype=
|
|
249
|
+
ampld = np.zeros(n_sp, dtype=config.dtype_double)
|
|
250
|
+
sigma = np.zeros(n_sp, dtype=config.dtype_double)
|
|
251
251
|
|
|
252
252
|
return {FV.WS: (ampld, sigma)}, st_sel
|
|
253
253
|
|
|
@@ -318,6 +318,8 @@ class TurbOParkWakeIX(GaussianWakeModel):
|
|
|
318
318
|
self.induction = induction
|
|
319
319
|
self.wake_k = WakeK(**wake_k)
|
|
320
320
|
|
|
321
|
+
assert not self.wake_k.is_kTI, f"{self.name}: Cannot apply ka or ambka setup"
|
|
322
|
+
|
|
321
323
|
def __repr__(self):
|
|
322
324
|
iname = (
|
|
323
325
|
self.induction if isinstance(self.induction, str) else self.induction.name
|
|
@@ -507,8 +509,8 @@ class TurbOParkWakeIX(GaussianWakeModel):
|
|
|
507
509
|
else:
|
|
508
510
|
st_sel = np.zeros_like(x, dtype=bool)
|
|
509
511
|
n_sp = np.sum(st_sel)
|
|
510
|
-
ampld = np.zeros(n_sp, dtype=
|
|
511
|
-
sigma = np.zeros(n_sp, dtype=
|
|
512
|
+
ampld = np.zeros(n_sp, dtype=config.dtype_double)
|
|
513
|
+
sigma = np.zeros(n_sp, dtype=config.dtype_double)
|
|
512
514
|
|
|
513
515
|
return {FV.WS: (ampld, sigma)}, st_sel
|
|
514
516
|
|
foxes/output/calc_points.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
from xarray import Dataset
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
import foxes.variables as FV
|
|
4
|
+
from foxes.config import config
|
|
6
5
|
from foxes.utils import write_nc
|
|
6
|
+
import foxes.variables as FV
|
|
7
|
+
import foxes.constants as FC
|
|
7
8
|
|
|
8
9
|
from .output import Output
|
|
9
10
|
|
|
@@ -67,7 +68,7 @@ class PointCalculator(Output):
|
|
|
67
68
|
weight_turbine: int, optional
|
|
68
69
|
Index of the turbine from which to take the weight
|
|
69
70
|
to_file: str, optional
|
|
70
|
-
|
|
71
|
+
The output netCDF file name
|
|
71
72
|
write_vars: list of str
|
|
72
73
|
The variables to be written to file, or None
|
|
73
74
|
for all
|
|
@@ -87,7 +88,9 @@ class PointCalculator(Output):
|
|
|
87
88
|
pts = points
|
|
88
89
|
p_has_s = True
|
|
89
90
|
elif points.shape[-1] == 3 and len(points.shape) == 2:
|
|
90
|
-
pts = np.zeros(
|
|
91
|
+
pts = np.zeros(
|
|
92
|
+
[self.algo.n_states] + list(points.shape), dtype=config.dtype_double
|
|
93
|
+
)
|
|
91
94
|
pts[:] = points[None, :]
|
|
92
95
|
p_has_s = False
|
|
93
96
|
else:
|
foxes/output/farm_layout.py
CHANGED
|
@@ -4,7 +4,7 @@ import pandas as pd
|
|
|
4
4
|
import matplotlib.pyplot as plt
|
|
5
5
|
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
from foxes.config import config
|
|
8
8
|
import foxes.variables as FV
|
|
9
9
|
from foxes.output.output import Output
|
|
10
10
|
|
|
@@ -31,7 +31,13 @@ class FarmLayoutOutput(Output):
|
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
33
|
def __init__(
|
|
34
|
-
self,
|
|
34
|
+
self,
|
|
35
|
+
farm,
|
|
36
|
+
farm_results=None,
|
|
37
|
+
from_results=False,
|
|
38
|
+
results_state=None,
|
|
39
|
+
D=None,
|
|
40
|
+
**kwargs,
|
|
35
41
|
):
|
|
36
42
|
"""
|
|
37
43
|
Constructor.
|
|
@@ -48,8 +54,11 @@ class FarmLayoutOutput(Output):
|
|
|
48
54
|
The state index, for from_res
|
|
49
55
|
D: float, optional
|
|
50
56
|
The rotor diameter, if not from data
|
|
57
|
+
kwargs: dict, optional
|
|
58
|
+
Additional parameters for the base class
|
|
51
59
|
|
|
52
60
|
"""
|
|
61
|
+
super().__init__(**kwargs)
|
|
53
62
|
self.farm = farm
|
|
54
63
|
self.fres = farm_results
|
|
55
64
|
self.from_res = from_results
|
|
@@ -75,7 +84,7 @@ class FarmLayoutOutput(Output):
|
|
|
75
84
|
|
|
76
85
|
"""
|
|
77
86
|
|
|
78
|
-
data = np.zeros([self.farm.n_turbines, 3], dtype=
|
|
87
|
+
data = np.zeros([self.farm.n_turbines, 3], dtype=config.dtype_double)
|
|
79
88
|
|
|
80
89
|
if self.from_res:
|
|
81
90
|
data[:, 0] = self.fres[FV.X][self.rstate]
|
|
@@ -284,14 +293,14 @@ class FarmLayoutOutput(Output):
|
|
|
284
293
|
|
|
285
294
|
return ax
|
|
286
295
|
|
|
287
|
-
def write_plot(self,
|
|
296
|
+
def write_plot(self, file_name=None, fontsize=8, **kwargs):
|
|
288
297
|
"""
|
|
289
298
|
Writes the layout plot to file.
|
|
290
299
|
|
|
291
300
|
Parameters
|
|
292
301
|
----------
|
|
293
|
-
|
|
294
|
-
|
|
302
|
+
file_name: str
|
|
303
|
+
Name of the file into which to plot, or None
|
|
295
304
|
for default
|
|
296
305
|
fontsize: int
|
|
297
306
|
Size of the turbine numbers
|
|
@@ -303,8 +312,9 @@ class FarmLayoutOutput(Output):
|
|
|
303
312
|
ax = self.get_figure(fontsize=fontsize, ret_im=False, **kwargs)
|
|
304
313
|
fig = ax.get_figure()
|
|
305
314
|
|
|
306
|
-
fname =
|
|
307
|
-
|
|
315
|
+
fname = file_name if file_name is not None else self.farm.name + ".png"
|
|
316
|
+
fpath = self.get_fpath(fname)
|
|
317
|
+
fig.savefig(fpath, bbox_inches="tight")
|
|
308
318
|
|
|
309
319
|
plt.close(fig)
|
|
310
320
|
|
|
@@ -325,14 +335,14 @@ class FarmLayoutOutput(Output):
|
|
|
325
335
|
fname = file_path if file_path is not None else self.farm.name + ".xyh"
|
|
326
336
|
np.savetxt(fname, data, header="x y h")
|
|
327
337
|
|
|
328
|
-
def write_csv(self,
|
|
338
|
+
def write_csv(self, file_name=None, type_col=None, algo=None):
|
|
329
339
|
"""
|
|
330
340
|
Writes csv layout file.
|
|
331
341
|
|
|
332
342
|
Parameters
|
|
333
343
|
----------
|
|
334
|
-
|
|
335
|
-
|
|
344
|
+
file_name: str
|
|
345
|
+
Name of the file into which to plot, or None
|
|
336
346
|
for default
|
|
337
347
|
type_col: str, optional
|
|
338
348
|
Name of the turbine type column
|
|
@@ -343,7 +353,8 @@ class FarmLayoutOutput(Output):
|
|
|
343
353
|
|
|
344
354
|
data = self.get_layout_data()
|
|
345
355
|
|
|
346
|
-
fname =
|
|
356
|
+
fname = file_name if file_name is not None else self.farm.name + ".csv"
|
|
357
|
+
fpath = self.get_fpath(fname)
|
|
347
358
|
|
|
348
359
|
lyt = pd.DataFrame(index=range(len(data)), columns=["name", "x", "y", "h", "D"])
|
|
349
360
|
lyt.index.name = "index"
|
|
@@ -356,22 +367,23 @@ class FarmLayoutOutput(Output):
|
|
|
356
367
|
if type_col is not None:
|
|
357
368
|
lyt[type_col] = [m.name for m in algo.farm_controller.turbine_types]
|
|
358
369
|
|
|
359
|
-
lyt.to_csv(
|
|
370
|
+
lyt.to_csv(fpath)
|
|
360
371
|
|
|
361
|
-
def write_json(self,
|
|
372
|
+
def write_json(self, file_name=None):
|
|
362
373
|
"""
|
|
363
374
|
Writes xyh layout file.
|
|
364
375
|
|
|
365
376
|
Parameters
|
|
366
377
|
----------
|
|
367
|
-
|
|
368
|
-
|
|
378
|
+
file_name: str
|
|
379
|
+
Name of the file into which to plot, or None
|
|
369
380
|
for default
|
|
370
381
|
|
|
371
382
|
"""
|
|
372
383
|
|
|
373
384
|
data = self.get_layout_dict()
|
|
374
385
|
|
|
375
|
-
fname =
|
|
376
|
-
|
|
386
|
+
fname = file_name if file_name is not None else self.farm.name + ".json"
|
|
387
|
+
fpath = self.get_fpath(fname)
|
|
388
|
+
with open(fpath, "w") as outfile:
|
|
377
389
|
json.dump(data, outfile, indent=4)
|