foxes 1.3__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 +0 -1
- 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 +21 -17
- foxes/algorithms/__init__.py +6 -6
- foxes/algorithms/downwind/__init__.py +2 -2
- foxes/algorithms/downwind/downwind.py +44 -12
- foxes/algorithms/downwind/models/__init__.py +6 -6
- foxes/algorithms/downwind/models/farm_wakes_calc.py +11 -9
- foxes/algorithms/downwind/models/init_farm_data.py +0 -1
- foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
- foxes/algorithms/downwind/models/set_amb_point_results.py +6 -6
- 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 +9 -5
- foxes/algorithms/sequential/__init__.py +3 -3
- foxes/algorithms/sequential/models/__init__.py +2 -2
- foxes/algorithms/sequential/sequential.py +3 -4
- foxes/config/__init__.py +5 -1
- foxes/constants.py +16 -0
- foxes/core/__init__.py +45 -22
- foxes/core/algorithm.py +0 -1
- foxes/core/data.py +19 -18
- foxes/core/engine.py +9 -13
- foxes/core/farm_controller.py +2 -2
- 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 +3 -3
- foxes/core/states.py +2 -3
- 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 -12
- foxes/input/states/create/__init__.py +3 -2
- foxes/input/states/field_data_nc.py +10 -24
- foxes/input/states/multi_height.py +9 -6
- foxes/input/states/one_point_flow.py +0 -4
- foxes/input/states/single.py +1 -1
- foxes/input/states/states_table.py +10 -7
- foxes/input/states/weibull_sectors.py +225 -0
- foxes/input/states/wrg_states.py +7 -5
- 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 +41 -11
- foxes/models/partial_wakes/segregated.py +2 -25
- 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/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 +41 -7
- foxes/models/wake_frames/streamlines.py +8 -6
- foxes/models/wake_frames/timelines.py +9 -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 +2 -2
- foxes/output/farm_results_eval.py +15 -15
- foxes/output/flow_plots_2d/__init__.py +2 -2
- foxes/output/flow_plots_2d/get_fig.py +4 -2
- foxes/output/rose_plot.py +3 -3
- 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/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.3.dist-info → foxes-1.4.dist-info}/METADATA +6 -15
- foxes-1.4.dist-info/RECORD +320 -0
- {foxes-1.3.dist-info → foxes-1.4.dist-info}/WHEEL +1 -1
- 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 +1 -1
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
- 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 +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +0 -1
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +0 -1
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +0 -1
- 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 +0 -1
- foxes/output/round.py +0 -10
- foxes/utils/pandas_helpers.py +0 -178
- foxes-1.3.dist-info/RECORD +0 -313
- {foxes-1.3.dist-info → foxes-1.4.dist-info}/entry_points.txt +0 -0
- {foxes-1.3.dist-info → foxes-1.4.dist-info/licenses}/LICENSE +0 -0
- {foxes-1.3.dist-info → foxes-1.4.dist-info}/top_level.txt +0 -0
|
@@ -39,3 +39,50 @@ class PartialCentre(RotorPoints):
|
|
|
39
39
|
|
|
40
40
|
"""
|
|
41
41
|
return fdata[FV.TXYH][:, :, None], np.ones(1, dtype=config.dtype_double)
|
|
42
|
+
|
|
43
|
+
def map_rotor_results(
|
|
44
|
+
self,
|
|
45
|
+
algo,
|
|
46
|
+
mdata,
|
|
47
|
+
fdata,
|
|
48
|
+
tdata,
|
|
49
|
+
variable,
|
|
50
|
+
rotor_res,
|
|
51
|
+
rotor_weights,
|
|
52
|
+
):
|
|
53
|
+
"""
|
|
54
|
+
Map ambient rotor point results onto target points.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
algo: foxes.core.Algorithm
|
|
59
|
+
The calculation algorithm
|
|
60
|
+
mdata: foxes.core.MData
|
|
61
|
+
The model data
|
|
62
|
+
fdata: foxes.core.FData
|
|
63
|
+
The farm data
|
|
64
|
+
tdata: foxes.core.TData
|
|
65
|
+
The target point data
|
|
66
|
+
variable: str
|
|
67
|
+
The variable name to map
|
|
68
|
+
rotor_res: numpy.ndarray
|
|
69
|
+
The results at rotor points, shape:
|
|
70
|
+
(n_states, n_turbines, n_rotor_points)
|
|
71
|
+
rotor_weights: numpy.ndarray
|
|
72
|
+
The rotor point weights, shape: (n_rotor_points,)
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
res: numpy.ndarray
|
|
77
|
+
The mapped results at target points, shape:
|
|
78
|
+
(n_states, n_targets, n_tpoints)
|
|
79
|
+
|
|
80
|
+
"""
|
|
81
|
+
if rotor_res.shape[2] > 1:
|
|
82
|
+
return np.einsum(
|
|
83
|
+
"str,r->st",
|
|
84
|
+
rotor_res,
|
|
85
|
+
rotor_weights,
|
|
86
|
+
)[:, :, None]
|
|
87
|
+
else:
|
|
88
|
+
return rotor_res
|
|
@@ -39,13 +39,52 @@ class RotorPoints(PartialWakesModel):
|
|
|
39
39
|
algo.get_from_chunk_store(FC.ROTOR_WEIGHTS, mdata=mdata),
|
|
40
40
|
)
|
|
41
41
|
|
|
42
|
+
def map_rotor_results(
|
|
43
|
+
self,
|
|
44
|
+
algo,
|
|
45
|
+
mdata,
|
|
46
|
+
fdata,
|
|
47
|
+
tdata,
|
|
48
|
+
variable,
|
|
49
|
+
rotor_res,
|
|
50
|
+
rotor_weights,
|
|
51
|
+
):
|
|
52
|
+
"""
|
|
53
|
+
Map ambient rotor point results onto target points.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
algo: foxes.core.Algorithm
|
|
58
|
+
The calculation algorithm
|
|
59
|
+
mdata: foxes.core.MData
|
|
60
|
+
The model data
|
|
61
|
+
fdata: foxes.core.FData
|
|
62
|
+
The farm data
|
|
63
|
+
tdata: foxes.core.TData
|
|
64
|
+
The target point data
|
|
65
|
+
variable: str
|
|
66
|
+
The variable name to map
|
|
67
|
+
rotor_res: numpy.ndarray
|
|
68
|
+
The results at rotor points, shape:
|
|
69
|
+
(n_states, n_turbines, n_rotor_points)
|
|
70
|
+
rotor_weights: numpy.ndarray
|
|
71
|
+
The rotor point weights, shape: (n_rotor_points,)
|
|
72
|
+
|
|
73
|
+
Returns
|
|
74
|
+
-------
|
|
75
|
+
res: numpy.ndarray
|
|
76
|
+
The mapped results at target points, shape:
|
|
77
|
+
(n_states, n_targets, n_tpoints)
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
return rotor_res
|
|
81
|
+
|
|
42
82
|
def finalize_wakes(
|
|
43
83
|
self,
|
|
44
84
|
algo,
|
|
45
85
|
mdata,
|
|
46
86
|
fdata,
|
|
47
87
|
tdata,
|
|
48
|
-
amb_res,
|
|
49
88
|
rpoint_weights,
|
|
50
89
|
wake_deltas,
|
|
51
90
|
wmodel,
|
|
@@ -67,11 +106,6 @@ class RotorPoints(PartialWakesModel):
|
|
|
67
106
|
The farm data
|
|
68
107
|
tdata: foxes.core.Data
|
|
69
108
|
The target point data
|
|
70
|
-
amb_res: dict
|
|
71
|
-
The ambient results at the target points
|
|
72
|
-
of all rotors. Key: variable name, value
|
|
73
|
-
np.ndarray of shape:
|
|
74
|
-
(n_states, n_turbines, n_rotor_points)
|
|
75
109
|
rpoint_weights: numpy.ndarray
|
|
76
110
|
The rotor point weights, shape: (n_rotor_points,)
|
|
77
111
|
wake_deltas: dict
|
|
@@ -91,14 +125,10 @@ class RotorPoints(PartialWakesModel):
|
|
|
91
125
|
of shape (n_states, n_rotor_points)
|
|
92
126
|
|
|
93
127
|
"""
|
|
94
|
-
ares = {
|
|
95
|
-
v: d[:, downwind_index, None] if d.shape[1] > 1 else d[:, 0, None]
|
|
96
|
-
for v, d in amb_res.items()
|
|
97
|
-
}
|
|
98
128
|
wdel = {
|
|
99
129
|
v: d[:, downwind_index, None].copy() if d.shape[1] > 1 else d[:, 0, None]
|
|
100
130
|
for v, d in wake_deltas.items()
|
|
101
131
|
}
|
|
102
|
-
wmodel.finalize_wake_deltas(algo, mdata, fdata,
|
|
132
|
+
wmodel.finalize_wake_deltas(algo, mdata, fdata, tdata, wdel)
|
|
103
133
|
|
|
104
134
|
return {v: d[:, 0] for v, d in wdel.items()}
|
|
@@ -87,7 +87,6 @@ class PartialSegregated(PartialWakesModel):
|
|
|
87
87
|
mdata,
|
|
88
88
|
fdata,
|
|
89
89
|
tdata,
|
|
90
|
-
amb_res,
|
|
91
90
|
rpoint_weights,
|
|
92
91
|
wake_deltas,
|
|
93
92
|
wmodel,
|
|
@@ -109,11 +108,6 @@ class PartialSegregated(PartialWakesModel):
|
|
|
109
108
|
The farm data
|
|
110
109
|
tdata: foxes.core.Data
|
|
111
110
|
The target point data
|
|
112
|
-
amb_res: dict
|
|
113
|
-
The ambient results at the target points
|
|
114
|
-
of all rotors. Key: variable name, value
|
|
115
|
-
np.ndarray of shape:
|
|
116
|
-
(n_states, n_turbines, n_rotor_points)
|
|
117
111
|
rpoint_weights: numpy.ndarray
|
|
118
112
|
The rotor point weights, shape: (n_rotor_points,)
|
|
119
113
|
wake_deltas: dict
|
|
@@ -138,25 +132,8 @@ class PartialSegregated(PartialWakesModel):
|
|
|
138
132
|
gweights = tdata[FC.TWEIGHTS]
|
|
139
133
|
|
|
140
134
|
wdel = {v: d[:, downwind_index, None].copy() for v, d in wake_deltas.items()}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
ares = {
|
|
144
|
-
v: d[:, downwind_index, None] if d.shape[1] > 1 else d[:, 0, None]
|
|
145
|
-
for v, d in amb_res.items()
|
|
146
|
-
}
|
|
147
|
-
else:
|
|
148
|
-
ares = {}
|
|
149
|
-
for v, d in amb_res.items():
|
|
150
|
-
ares[v] = np.zeros(
|
|
151
|
-
(n_states, 1, tdata.n_tpoints), dtype=config.dtype_double
|
|
152
|
-
)
|
|
153
|
-
ares[v][:] = np.einsum(
|
|
154
|
-
"sp,p->s",
|
|
155
|
-
d[:, downwind_index] if d.shape[1] > 1 else d[:, 0],
|
|
156
|
-
rpoint_weights,
|
|
157
|
-
)[:, None, None]
|
|
158
|
-
|
|
159
|
-
wmodel.finalize_wake_deltas(algo, mdata, fdata, ares, wdel)
|
|
135
|
+
htdata = tdata.get_slice([FC.TURBINE], np.s_[downwind_index])
|
|
136
|
+
wmodel.finalize_wake_deltas(algo, mdata, fdata, htdata, wdel)
|
|
160
137
|
|
|
161
138
|
for v in wdel.keys():
|
|
162
139
|
hdel = np.zeros((n_states, n_rotor_points), dtype=config.dtype_double)
|
|
@@ -126,8 +126,6 @@ class PartialTopHat(PartialCentre):
|
|
|
126
126
|
The wake deltas. Key: variable name,
|
|
127
127
|
value: numpy.ndarray with shape
|
|
128
128
|
(n_states, n_targets, n_tpoints, ...)
|
|
129
|
-
wmodel: foxes.core.WakeModel
|
|
130
|
-
The wake model
|
|
131
129
|
|
|
132
130
|
"""
|
|
133
131
|
self.check_wmodel(wmodel, error=True)
|
|
@@ -182,6 +180,33 @@ class PartialTopHat(PartialCentre):
|
|
|
182
180
|
|
|
183
181
|
weights = calc_area(D / 2, wr, R) / (np.pi * (D / 2) ** 2)
|
|
184
182
|
|
|
183
|
+
# run superposition models:
|
|
184
|
+
if wmodel.affects_ws and wmodel.has_uv:
|
|
185
|
+
assert wmodel.has_vector_wind_superp, (
|
|
186
|
+
f"{self.name}: Expecting vector wind superposition in wake model '{wmodel.name}', got '{wmodel.wind_superposition}'"
|
|
187
|
+
)
|
|
188
|
+
if FV.UV in clw:
|
|
189
|
+
duv = clw.pop(FV.UV)
|
|
190
|
+
else:
|
|
191
|
+
clwe = {v: d[:, None] for v, d in clw.items()}
|
|
192
|
+
wmodel.vec_superp.wdeltas_ws2uv(
|
|
193
|
+
algo, fdata, tdata, downwind_index, clwe, st_sel
|
|
194
|
+
)
|
|
195
|
+
duv = np.einsum("sd,s->sd", clwe.pop(FV.UV)[:, 0], weights)
|
|
196
|
+
del clwe, clw[FV.WS]
|
|
197
|
+
if FV.WD in clw:
|
|
198
|
+
del clw[FV.WD]
|
|
199
|
+
wake_deltas[FV.UV] = wmodel.vec_superp.add_wake_vector(
|
|
200
|
+
algo,
|
|
201
|
+
mdata,
|
|
202
|
+
fdata,
|
|
203
|
+
tdata,
|
|
204
|
+
downwind_index,
|
|
205
|
+
st_sel,
|
|
206
|
+
wake_deltas[FV.UV],
|
|
207
|
+
duv[:, None],
|
|
208
|
+
)
|
|
209
|
+
|
|
185
210
|
for v, d in clw.items():
|
|
186
211
|
try:
|
|
187
212
|
superp = wmodel.superp[v]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Point models.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .wake_deltas import WakeDeltas
|
|
6
|
-
from .set_uniform_data import SetUniformData
|
|
7
|
-
from .tke2ti import TKE2TI
|
|
8
|
-
from .ustar2ti import Ustar2TI
|
|
5
|
+
from .wake_deltas import WakeDeltas as WakeDeltas
|
|
6
|
+
from .set_uniform_data import SetUniformData as SetUniformData
|
|
7
|
+
from .tke2ti import TKE2TI as TKE2TI
|
|
8
|
+
from .ustar2ti import Ustar2TI as Ustar2TI
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Turbine models.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .kTI_model import kTI
|
|
6
|
-
from .set_farm_vars import SetFarmVars
|
|
7
|
-
from .thrust2ct import Thrust2Ct
|
|
8
|
-
from .power_mask import PowerMask
|
|
9
|
-
from .sector_management import SectorManagement
|
|
10
|
-
from .table_factors import TableFactors
|
|
11
|
-
from .yaw2yawm import YAW2YAWM
|
|
12
|
-
from .yawm2yaw import YAWM2YAW
|
|
13
|
-
from .calculator import Calculator
|
|
14
|
-
from .rotor_centre_calc import RotorCentreCalc
|
|
15
|
-
from .lookup_table import LookupTable
|
|
5
|
+
from .kTI_model import kTI as kTI
|
|
6
|
+
from .set_farm_vars import SetFarmVars as SetFarmVars
|
|
7
|
+
from .thrust2ct import Thrust2Ct as Thrust2Ct
|
|
8
|
+
from .power_mask import PowerMask as PowerMask
|
|
9
|
+
from .sector_management import SectorManagement as SectorManagement
|
|
10
|
+
from .table_factors import TableFactors as TableFactors
|
|
11
|
+
from .yaw2yawm import YAW2YAWM as YAW2YAWM
|
|
12
|
+
from .yawm2yaw import YAWM2YAW as YAWM2YAW
|
|
13
|
+
from .calculator import Calculator as Calculator
|
|
14
|
+
from .rotor_centre_calc import RotorCentreCalc as RotorCentreCalc
|
|
15
|
+
from .lookup_table import LookupTable as LookupTable
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
import pandas as pd
|
|
3
|
-
from pathlib import Path
|
|
4
3
|
|
|
5
4
|
from foxes.core import TurbineType
|
|
6
5
|
from foxes.utils import PandasFileHelper
|
|
@@ -232,7 +231,6 @@ class PCtFile(TurbineType):
|
|
|
232
231
|
|
|
233
232
|
"""
|
|
234
233
|
if modify_ct or modify_P:
|
|
235
|
-
|
|
236
234
|
ws = self.data_ws
|
|
237
235
|
ct = self.data_ct
|
|
238
236
|
P = self.data_P
|
|
@@ -263,7 +263,6 @@ class PCtFromTwo(TurbineType):
|
|
|
263
263
|
|
|
264
264
|
"""
|
|
265
265
|
if modify_ct:
|
|
266
|
-
|
|
267
266
|
ws = self._data_ws_ct
|
|
268
267
|
ct = self._data_ct
|
|
269
268
|
|
|
@@ -291,7 +290,6 @@ class PCtFromTwo(TurbineType):
|
|
|
291
290
|
self._data_ct = np.concatenate([new_ct[:-1], ct], axis=0)
|
|
292
291
|
|
|
293
292
|
if modify_P:
|
|
294
|
-
|
|
295
293
|
ws = self._data_ws_P
|
|
296
294
|
P = self._data_P
|
|
297
295
|
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Turbine type models.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .PCt_file import PCtFile
|
|
6
|
-
from .PCt_from_two import PCtFromTwo
|
|
7
|
-
from .CpCt_file import CpCtFile
|
|
8
|
-
from .CpCt_from_two import CpCtFromTwo
|
|
9
|
-
from .null_type import NullType
|
|
10
|
-
from .wsrho2PCt_from_two import WsRho2PCtFromTwo
|
|
11
|
-
from .wsti2PCt_from_two import WsTI2PCtFromTwo
|
|
12
|
-
from .lookup import FromLookupTable
|
|
13
|
-
from .TBL_file import TBLFile
|
|
5
|
+
from .PCt_file import PCtFile as PCtFile
|
|
6
|
+
from .PCt_from_two import PCtFromTwo as PCtFromTwo
|
|
7
|
+
from .CpCt_file import CpCtFile as CpCtFile
|
|
8
|
+
from .CpCt_from_two import CpCtFromTwo as CpCtFromTwo
|
|
9
|
+
from .null_type import NullType as NullType
|
|
10
|
+
from .wsrho2PCt_from_two import WsRho2PCtFromTwo as WsRho2PCtFromTwo
|
|
11
|
+
from .wsti2PCt_from_two import WsTI2PCtFromTwo as WsTI2PCtFromTwo
|
|
12
|
+
from .lookup import FromLookupTable as FromLookupTable
|
|
13
|
+
from .TBL_file import TBLFile as TBLFile
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Vertical profile models.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .uniform import UniformProfile
|
|
6
|
-
from .abl_log_neutral_ws import ABLLogNeutralWsProfile
|
|
7
|
-
from .abl_log_stable_ws import ABLLogStableWsProfile
|
|
8
|
-
from .abl_log_unstable_ws import ABLLogUnstableWsProfile
|
|
9
|
-
from .abl_log_ws import ABLLogWsProfile
|
|
10
|
-
from .sheared_ws import ShearedProfile
|
|
11
|
-
from .data_profile import DataProfile
|
|
5
|
+
from .uniform import UniformProfile as UniformProfile
|
|
6
|
+
from .abl_log_neutral_ws import ABLLogNeutralWsProfile as ABLLogNeutralWsProfile
|
|
7
|
+
from .abl_log_stable_ws import ABLLogStableWsProfile as ABLLogStableWsProfile
|
|
8
|
+
from .abl_log_unstable_ws import ABLLogUnstableWsProfile as ABLLogUnstableWsProfile
|
|
9
|
+
from .abl_log_ws import ABLLogWsProfile as ABLLogWsProfile
|
|
10
|
+
from .sheared_ws import ShearedProfile as ShearedProfile
|
|
11
|
+
from .data_profile import DataProfile as DataProfile
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
|
|
3
|
-
from foxes.
|
|
3
|
+
from foxes.config import config
|
|
4
|
+
from foxes.core.wake_deflection import WakeDeflection
|
|
5
|
+
from foxes.core.wake_model import WakeK
|
|
4
6
|
from foxes.models.wake_models.wind.bastankhah16 import (
|
|
5
7
|
Bastankhah2016Model,
|
|
6
8
|
Bastankhah2016,
|
|
7
9
|
)
|
|
8
|
-
from foxes.config import config
|
|
9
|
-
import foxes.variables as FV
|
|
10
10
|
import foxes.constants as FC
|
|
11
|
-
|
|
12
|
-
from .rotor_wd import RotorWD
|
|
11
|
+
import foxes.variables as FV
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
class
|
|
14
|
+
class Bastankhah2016Deflection(WakeDeflection):
|
|
16
15
|
"""
|
|
17
16
|
Bend the wakes for yawed turbines, based on the
|
|
18
17
|
Bastankhah 2016 wake model
|
|
@@ -28,25 +27,26 @@ class YawedWakes(WakeFrame):
|
|
|
28
27
|
----------
|
|
29
28
|
model: Bastankhah2016Model
|
|
30
29
|
The model for computing common data
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
:
|
|
30
|
+
alpha: float
|
|
31
|
+
model parameter used to determine onset of far wake region,
|
|
32
|
+
if not found in wake model
|
|
33
|
+
beta: float
|
|
34
|
+
model parameter used to determine onset of far wake region,
|
|
35
|
+
if not found in wake model
|
|
36
|
+
wake_k: dict
|
|
37
|
+
Parameters for the WakeK class, if not found in wake model
|
|
38
|
+
induction: foxes.core.AxialInductionModel
|
|
39
|
+
The induction model, if not found in wake model
|
|
40
|
+
|
|
41
|
+
:group: models.wake_deflections
|
|
40
42
|
|
|
41
43
|
"""
|
|
42
44
|
|
|
43
45
|
def __init__(
|
|
44
46
|
self,
|
|
45
|
-
base_frame=RotorWD(),
|
|
46
47
|
alpha=0.58,
|
|
47
48
|
beta=0.07,
|
|
48
49
|
induction="Madsen",
|
|
49
|
-
max_length_km=30,
|
|
50
50
|
**wake_k,
|
|
51
51
|
):
|
|
52
52
|
"""
|
|
@@ -54,8 +54,6 @@ class YawedWakes(WakeFrame):
|
|
|
54
54
|
|
|
55
55
|
Parameters
|
|
56
56
|
----------
|
|
57
|
-
base_frame: foxes.core.WakeFrame
|
|
58
|
-
The wake frame from which to start
|
|
59
57
|
alpha: float
|
|
60
58
|
model parameter used to determine onset of far wake region,
|
|
61
59
|
if not found in wake model
|
|
@@ -66,13 +64,10 @@ class YawedWakes(WakeFrame):
|
|
|
66
64
|
The induction model, if not found in wake model
|
|
67
65
|
wake_k: dict, optional
|
|
68
66
|
Parameters for the WakeK class, if not found in wake model
|
|
69
|
-
max_length_km: float
|
|
70
|
-
The maximal wake length in km
|
|
71
67
|
|
|
72
68
|
"""
|
|
73
|
-
super().__init__(
|
|
69
|
+
super().__init__()
|
|
74
70
|
|
|
75
|
-
self.base_frame = base_frame
|
|
76
71
|
self.model = None
|
|
77
72
|
self.alpha = alpha
|
|
78
73
|
self.beta = beta
|
|
@@ -98,7 +93,7 @@ class YawedWakes(WakeFrame):
|
|
|
98
93
|
Names of all sub models
|
|
99
94
|
|
|
100
95
|
"""
|
|
101
|
-
return [self.wake_k, self.
|
|
96
|
+
return [self.wake_k, self.model]
|
|
102
97
|
|
|
103
98
|
def initialize(self, algo, verbosity=0, force=False):
|
|
104
99
|
"""
|
|
@@ -138,30 +133,6 @@ class YawedWakes(WakeFrame):
|
|
|
138
133
|
|
|
139
134
|
super().initialize(algo, verbosity, force)
|
|
140
135
|
|
|
141
|
-
def calc_order(self, algo, mdata, fdata):
|
|
142
|
-
"""
|
|
143
|
-
Calculates the order of turbine evaluation.
|
|
144
|
-
|
|
145
|
-
This function is executed on a single chunk of data,
|
|
146
|
-
all computations should be based on numpy arrays.
|
|
147
|
-
|
|
148
|
-
Parameters
|
|
149
|
-
----------
|
|
150
|
-
algo: foxes.core.Algorithm
|
|
151
|
-
The calculation algorithm
|
|
152
|
-
mdata: foxes.core.MData
|
|
153
|
-
The model data
|
|
154
|
-
fdata: foxes.core.FData
|
|
155
|
-
The farm data
|
|
156
|
-
|
|
157
|
-
Returns
|
|
158
|
-
-------
|
|
159
|
-
order: numpy.ndarray
|
|
160
|
-
The turbine order, shape: (n_states, n_turbines)
|
|
161
|
-
|
|
162
|
-
"""
|
|
163
|
-
return self.base_frame.calc_order(algo, mdata, fdata)
|
|
164
|
-
|
|
165
136
|
def _update_y(self, algo, mdata, fdata, tdata, downwind_index, x, y):
|
|
166
137
|
"""
|
|
167
138
|
Helper function for y deflection
|
|
@@ -227,16 +198,20 @@ class YawedWakes(WakeFrame):
|
|
|
227
198
|
# apply deflection:
|
|
228
199
|
y[st_sel] -= ydef
|
|
229
200
|
|
|
230
|
-
def
|
|
201
|
+
def calc_deflection(
|
|
231
202
|
self,
|
|
232
203
|
algo,
|
|
233
204
|
mdata,
|
|
234
205
|
fdata,
|
|
235
206
|
tdata,
|
|
236
207
|
downwind_index,
|
|
208
|
+
coos,
|
|
237
209
|
):
|
|
238
210
|
"""
|
|
239
|
-
|
|
211
|
+
Calculates the wake deflection.
|
|
212
|
+
|
|
213
|
+
This function optionally adds FC.WDEFL_ROT_ANGLE or
|
|
214
|
+
FC.WDEFL_DWS_FACTOR to the tdata.
|
|
240
215
|
|
|
241
216
|
Parameters
|
|
242
217
|
----------
|
|
@@ -251,79 +226,25 @@ class YawedWakes(WakeFrame):
|
|
|
251
226
|
downwind_index: int
|
|
252
227
|
The index of the wake causing turbine
|
|
253
228
|
in the downwind order
|
|
229
|
+
coos: numpy.ndarray
|
|
230
|
+
The wake frame coordinates of the evaluation
|
|
231
|
+
points, shape: (n_states, n_targets, n_tpoints, 3)
|
|
254
232
|
|
|
255
233
|
Returns
|
|
256
234
|
-------
|
|
257
|
-
|
|
235
|
+
coos: numpy.ndarray
|
|
258
236
|
The wake frame coordinates of the evaluation
|
|
259
237
|
points, shape: (n_states, n_targets, n_tpoints, 3)
|
|
260
238
|
|
|
261
239
|
"""
|
|
262
|
-
# get unyawed results:
|
|
263
|
-
xyz = self.base_frame.get_wake_coos(
|
|
264
|
-
algo,
|
|
265
|
-
mdata,
|
|
266
|
-
fdata,
|
|
267
|
-
tdata,
|
|
268
|
-
downwind_index,
|
|
269
|
-
)
|
|
270
240
|
|
|
271
241
|
# take rotor average:
|
|
272
|
-
xy = np.einsum("stpd,p->std",
|
|
242
|
+
xy = np.einsum("stpd,p->std", coos[..., :2], tdata[FC.TWEIGHTS])
|
|
273
243
|
x = xy[:, :, 0]
|
|
274
244
|
y = xy[:, :, 1]
|
|
275
245
|
|
|
276
246
|
# apply deflection:
|
|
277
247
|
self._update_y(algo, mdata, fdata, tdata, downwind_index, x, y)
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
return xyz
|
|
281
|
-
|
|
282
|
-
def get_centreline_points(self, algo, mdata, fdata, downwind_index, x):
|
|
283
|
-
"""
|
|
284
|
-
Gets the points along the centreline for given
|
|
285
|
-
values of x.
|
|
286
|
-
|
|
287
|
-
Parameters
|
|
288
|
-
----------
|
|
289
|
-
algo: foxes.core.Algorithm
|
|
290
|
-
The calculation algorithm
|
|
291
|
-
mdata: foxes.core.MData
|
|
292
|
-
The model data
|
|
293
|
-
fdata: foxes.core.FData
|
|
294
|
-
The farm data
|
|
295
|
-
downwind_index: int
|
|
296
|
-
The index in the downwind order
|
|
297
|
-
x: numpy.ndarray
|
|
298
|
-
The wake frame x coordinates, shape: (n_states, n_points)
|
|
299
|
-
|
|
300
|
-
Returns
|
|
301
|
-
-------
|
|
302
|
-
points: numpy.ndarray
|
|
303
|
-
The centreline points, shape: (n_states, n_points, 3)
|
|
304
|
-
|
|
305
|
-
"""
|
|
306
|
-
points = self.base_frame.get_centreline_points(
|
|
307
|
-
algo, mdata, fdata, downwind_index, x
|
|
308
|
-
)
|
|
309
|
-
tdata = TData.from_points(points)
|
|
310
|
-
|
|
311
|
-
nx = np.zeros_like(points)
|
|
312
|
-
nx[:, 0] = points[:, 1] - points[:, 0]
|
|
313
|
-
nx[:, -1] = points[:, -1] - points[:, -2]
|
|
314
|
-
nx[:, 1:-1] = 0.5 * (points[:, 1:-1] - points[:, :-2]) + 0.5 * (
|
|
315
|
-
points[:, 2:] - points[:, 1:-1]
|
|
316
|
-
)
|
|
317
|
-
nx /= np.linalg.norm(nx, axis=-1)[:, :, None]
|
|
318
|
-
|
|
319
|
-
nz = np.zeros_like(nx)
|
|
320
|
-
nz[:, :, 2] = 1
|
|
321
|
-
ny = np.cross(nz, nx, axis=-1)
|
|
322
|
-
del nx, nz
|
|
323
|
-
|
|
324
|
-
y = np.zeros_like(x)
|
|
325
|
-
self._update_y(algo, mdata, fdata, tdata, downwind_index, x, y)
|
|
326
|
-
|
|
327
|
-
points += y[:, :, None] * ny
|
|
248
|
+
coos[..., 1] = y[:, :, None]
|
|
328
249
|
|
|
329
|
-
return
|
|
250
|
+
return coos
|