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
|
@@ -77,7 +77,7 @@ def read_turbine_types(wio_farm, mbook, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
77
77
|
return FV.REWS if wse == 1 else (FV.REWS2 if wse == 2 else FV.REWS3)
|
|
78
78
|
|
|
79
79
|
_print(f" Creating model '{tname}'", level=3)
|
|
80
|
-
_print(
|
|
80
|
+
_print(" Turbine type class: PCtFomTwo", level=3)
|
|
81
81
|
mbook.turbine_types[tname] = TurbineType.new(
|
|
82
82
|
ttype_type="PCtFromTwo",
|
|
83
83
|
data_source_P=data_P,
|
|
@@ -111,7 +111,7 @@ def read_turbine_types(wio_farm, mbook, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
111
111
|
data_ct = pd.DataFrame(data={"ws": ws_ct, "ct": ct})
|
|
112
112
|
|
|
113
113
|
_print(f" Creating model '{tname}'", level=3)
|
|
114
|
-
_print(
|
|
114
|
+
_print(" Turbine type class: CpCtFromTwo", level=3)
|
|
115
115
|
mbook.turbine_types[tname] = TurbineType.new(
|
|
116
116
|
ttype_type="CpCtFromTwo",
|
|
117
117
|
data_source_cp=data_cp,
|
|
@@ -126,7 +126,7 @@ def read_turbine_types(wio_farm, mbook, ws_exp_P, ws_exp_ct, verbosity):
|
|
|
126
126
|
_print(" ", mbook.turbine_types[tname], level=3)
|
|
127
127
|
|
|
128
128
|
else:
|
|
129
|
-
raise KeyError(
|
|
129
|
+
raise KeyError("Expecting either 'power_curve' or 'Cp_curve'")
|
|
130
130
|
|
|
131
131
|
return ttypes
|
|
132
132
|
|
|
@@ -157,7 +157,7 @@ def read_layout(lname, ldict, farm, ttypes, verbosity=1):
|
|
|
157
157
|
cdict = Dict(ldict["coordinates"], name="coordinates")
|
|
158
158
|
tmap = ldict.get_item("turbine_types", None)
|
|
159
159
|
if verbosity > 2:
|
|
160
|
-
print(
|
|
160
|
+
print(" Turbine type map:", tmap)
|
|
161
161
|
for i, xy in enumerate(zip(cdict["x"], cdict["y"])):
|
|
162
162
|
tt = ttypes[tmap[i] if tmap is not None else 0]
|
|
163
163
|
farm.add_turbine(
|
|
@@ -211,7 +211,7 @@ def read_farm(wio_dict, mbook, verbosity):
|
|
|
211
211
|
if isinstance(wfarm, dict):
|
|
212
212
|
layouts = Dict(wfarm, name=wio_farm.name + ".layouts")
|
|
213
213
|
else:
|
|
214
|
-
layouts = {str(i):
|
|
214
|
+
layouts = {str(i): lf for i, lf in enumerate(wfarm)}
|
|
215
215
|
layouts = Dict(layouts, name=wio_farm.name + ".layouts")
|
|
216
216
|
if verbosity > 2:
|
|
217
217
|
print(" Reading layouts")
|
|
@@ -22,6 +22,8 @@ wio2foxes = {
|
|
|
22
22
|
"LMO": FV.MOL,
|
|
23
23
|
"z0": FV.Z0,
|
|
24
24
|
"reference_height": FV.H,
|
|
25
|
+
"weibull_a": FV.WEIBULL_A,
|
|
26
|
+
"weibull_k": FV.WEIBULL_k,
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
""" Mapping from foxes to windio variables
|
|
@@ -134,8 +136,6 @@ def read_wind_resource_field(
|
|
|
134
136
|
|
|
135
137
|
"""
|
|
136
138
|
if name in [
|
|
137
|
-
"weibull_a",
|
|
138
|
-
"weibull_k",
|
|
139
139
|
"potential_temperature",
|
|
140
140
|
"friction_velocity",
|
|
141
141
|
"k",
|
|
@@ -178,6 +178,8 @@ def read_wind_resource_field(
|
|
|
178
178
|
"LMO",
|
|
179
179
|
"z0",
|
|
180
180
|
"reference_height",
|
|
181
|
+
"weibull_a",
|
|
182
|
+
"weibull_k",
|
|
181
183
|
] and _read_multi_dimensional_data(name, wio_data, fields, dims):
|
|
182
184
|
return True
|
|
183
185
|
|
|
@@ -159,6 +159,55 @@ def _get_MultiHeightNCTimeseries(
|
|
|
159
159
|
return False
|
|
160
160
|
|
|
161
161
|
|
|
162
|
+
def _get_WeibullSectors(
|
|
163
|
+
coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
|
|
164
|
+
):
|
|
165
|
+
"""Try to generate Weibull sector parameters
|
|
166
|
+
:group: input.yaml.windio
|
|
167
|
+
"""
|
|
168
|
+
if (
|
|
169
|
+
FV.WEIBULL_A in fields
|
|
170
|
+
and FV.WEIBULL_k in fields
|
|
171
|
+
and "sector_probability" in fields
|
|
172
|
+
and len(dims[FV.WEIBULL_A]) == 1
|
|
173
|
+
and len(dims[FV.WEIBULL_k]) == 1
|
|
174
|
+
and len(dims["sector_probability"]) == 1
|
|
175
|
+
):
|
|
176
|
+
if verbosity > 2:
|
|
177
|
+
print(" selecting class 'WeibullSectors'")
|
|
178
|
+
|
|
179
|
+
data = {}
|
|
180
|
+
fix = {}
|
|
181
|
+
c = dims[FV.WEIBULL_A][0]
|
|
182
|
+
for v, d in fields.items():
|
|
183
|
+
if dims[v] == (c,):
|
|
184
|
+
data[v] = d
|
|
185
|
+
elif len(dims[v]) == 0:
|
|
186
|
+
fix[v] = d
|
|
187
|
+
elif verbosity > 2:
|
|
188
|
+
print(f" ignoring field '{v}' with dims {dims[v]}")
|
|
189
|
+
fix.update({v: d for v, d in fixval.items() if v not in data})
|
|
190
|
+
|
|
191
|
+
if FV.WD in coords:
|
|
192
|
+
data[FV.WD] = coords[FV.WD]
|
|
193
|
+
|
|
194
|
+
sdata = pd.DataFrame(index=range(len(fields[FV.WEIBULL_A])), data=data)
|
|
195
|
+
sdata.index.name = "sector"
|
|
196
|
+
states_dict.update(
|
|
197
|
+
dict(
|
|
198
|
+
states_type="WeibullSectors",
|
|
199
|
+
data_source=sdata,
|
|
200
|
+
ws_bins=coords.get(FV.WS, np.arange(30)),
|
|
201
|
+
output_vars=ovars,
|
|
202
|
+
var2ncvar={FV.WEIGHT: "sector_probability"},
|
|
203
|
+
fixed_vars=fix,
|
|
204
|
+
profiles=profiles,
|
|
205
|
+
)
|
|
206
|
+
)
|
|
207
|
+
return True
|
|
208
|
+
return False
|
|
209
|
+
|
|
210
|
+
|
|
162
211
|
def get_states(coords, fields, dims, verbosity=1):
|
|
163
212
|
"""
|
|
164
213
|
Reads states parameters from windio input
|
|
@@ -200,6 +249,9 @@ def get_states(coords, fields, dims, verbosity=1):
|
|
|
200
249
|
or _get_MultiHeightNCTimeseries(
|
|
201
250
|
coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
|
|
202
251
|
)
|
|
252
|
+
or _get_WeibullSectors(
|
|
253
|
+
coords, fields, dims, states_dict, ovars, fixval, profiles, verbosity
|
|
254
|
+
)
|
|
203
255
|
):
|
|
204
256
|
return States.new(**states_dict)
|
|
205
257
|
else:
|
|
@@ -43,7 +43,7 @@ def read_windio(wio_dict, verbosity=1):
|
|
|
43
43
|
if not isinstance(wio_dict, Dict):
|
|
44
44
|
wio_dict = Dict(wio_dict, name="windio")
|
|
45
45
|
|
|
46
|
-
_print(
|
|
46
|
+
_print("Reading windio data")
|
|
47
47
|
_print(" Name:", wio_dict.pop_item("name", None))
|
|
48
48
|
_print(" Contents:", [k for k in wio_dict.keys()])
|
|
49
49
|
|
foxes/models/__init__.py
CHANGED
|
@@ -2,18 +2,19 @@
|
|
|
2
2
|
Model collection.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from . import turbine_types
|
|
6
|
-
from . import rotor_models
|
|
7
|
-
from . import turbine_models
|
|
8
|
-
from . import farm_models
|
|
9
|
-
from . import partial_wakes
|
|
10
|
-
from . import wake_frames
|
|
11
|
-
from . import wake_models
|
|
12
|
-
from . import
|
|
13
|
-
from . import
|
|
14
|
-
from . import
|
|
15
|
-
from . import
|
|
16
|
-
from . import
|
|
17
|
-
from . import
|
|
5
|
+
from . import turbine_types as turbine_types
|
|
6
|
+
from . import rotor_models as rotor_models
|
|
7
|
+
from . import turbine_models as turbine_models
|
|
8
|
+
from . import farm_models as farm_models
|
|
9
|
+
from . import partial_wakes as partial_wakes
|
|
10
|
+
from . import wake_frames as wake_frames
|
|
11
|
+
from . import wake_models as wake_models
|
|
12
|
+
from . import wake_deflections as wake_deflections
|
|
13
|
+
from . import wake_superpositions as wake_superpositions
|
|
14
|
+
from . import farm_controllers as farm_controllers
|
|
15
|
+
from . import vertical_profiles as vertical_profiles
|
|
16
|
+
from . import point_models as point_models
|
|
17
|
+
from . import axial_induction as axial_induction
|
|
18
|
+
from . import ground_models as ground_models
|
|
18
19
|
|
|
19
|
-
from .model_book import ModelBook
|
|
20
|
+
from .model_book import ModelBook as ModelBook
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
from .betz import BetzAxialInduction
|
|
2
|
-
from .madsen import MadsenAxialInduction
|
|
1
|
+
from .betz import BetzAxialInduction as BetzAxialInduction
|
|
2
|
+
from .madsen import MadsenAxialInduction as MadsenAxialInduction
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
from .no_ground import NoGround
|
|
2
|
-
from .wake_mirror import WakeMirror
|
|
1
|
+
from .no_ground import NoGround as NoGround
|
|
2
|
+
from .wake_mirror import WakeMirror as WakeMirror
|
|
3
|
+
from .wake_mirror import GroundMirror as GroundMirror
|
|
@@ -75,13 +75,14 @@ class WakeMirror(GroundModel):
|
|
|
75
75
|
# assert(np.all(fdata[FV.H]==fdata[FV.TXYH[..., 2]]))
|
|
76
76
|
|
|
77
77
|
# contribution from main wake:
|
|
78
|
-
wcoos = algo.wake_frame.get_wake_coos(
|
|
78
|
+
wcoos = algo.wake_frame.get_wake_coos(
|
|
79
|
+
algo, mdata, fdata, tdata, downwind_index, wmodel
|
|
80
|
+
)
|
|
79
81
|
wmodel.contribute(algo, mdata, fdata, tdata, downwind_index, wcoos, wake_deltas)
|
|
80
82
|
|
|
81
83
|
# contribution from mirrors:
|
|
82
84
|
tdata[FC.TARGETS] = tdata[FC.TARGETS].copy() # making sure this is no ref
|
|
83
85
|
for h in self.heights:
|
|
84
|
-
|
|
85
86
|
fdata[FV.TXYH][:, downwind_index, 2] = hh + 2 * (h - hh)
|
|
86
87
|
|
|
87
88
|
pwake.contribute(
|
|
@@ -136,7 +137,6 @@ class WakeMirror(GroundModel):
|
|
|
136
137
|
# contribution from mirrors:
|
|
137
138
|
tdata[FC.TARGETS] = tdata[FC.TARGETS].copy() # making sure this is no ref
|
|
138
139
|
for h in self.heights:
|
|
139
|
-
|
|
140
140
|
fdata[FV.TXYH][:, downwind_index, 2] = hh + 2 * (h - hh)
|
|
141
141
|
|
|
142
142
|
wcoos = algo.wake_frame.get_wake_coos(
|
foxes/models/model_book.py
CHANGED
|
@@ -17,6 +17,7 @@ from foxes.core import (
|
|
|
17
17
|
AxialInductionModel,
|
|
18
18
|
TurbineInductionModel,
|
|
19
19
|
GroundModel,
|
|
20
|
+
WakeDeflection,
|
|
20
21
|
)
|
|
21
22
|
|
|
22
23
|
|
|
@@ -62,6 +63,9 @@ class ModelBook:
|
|
|
62
63
|
ground_models: foxes.utils.FDict
|
|
63
64
|
The ground models. Keys: model name str,
|
|
64
65
|
values: foxes.core.GroundModel
|
|
66
|
+
wake_deflections: foxes.utils.FDict
|
|
67
|
+
The wake deflection models. Keys: model name str,
|
|
68
|
+
values: foxes.core.WakeDeflection
|
|
65
69
|
sources: foxes.utils.FDict
|
|
66
70
|
All sources dict
|
|
67
71
|
base_classes: foxes.utils.FDict
|
|
@@ -231,15 +235,78 @@ class ModelBook:
|
|
|
231
235
|
hints={"n2": "(Number of points in square grid)"},
|
|
232
236
|
)
|
|
233
237
|
|
|
238
|
+
self.wake_deflections = FDict(
|
|
239
|
+
name="wake_deflections",
|
|
240
|
+
no_deflection=fm.wake_deflections.NoDeflection(),
|
|
241
|
+
Bastankhah2016=fm.wake_deflections.Bastankhah2016Deflection(),
|
|
242
|
+
Jimenez=fm.wake_deflections.JimenezDeflection(rotate=True),
|
|
243
|
+
JimenezProj=fm.wake_deflections.JimenezDeflection(rotate=False),
|
|
244
|
+
JimenezPath=fm.wake_deflections.JimenezDeflection(rotate=None),
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
self.wake_deflections.add_factory(
|
|
248
|
+
fm.wake_deflections.JimenezDeflection,
|
|
249
|
+
"Jimenez_b<beta>",
|
|
250
|
+
beta=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
251
|
+
hints={"beta": "(The Jimenez beta coefficient, e.g. 01 for 0.1)"},
|
|
252
|
+
kwargs=dict(rotate=True),
|
|
253
|
+
)
|
|
254
|
+
self.wake_deflections.add_factory(
|
|
255
|
+
fm.wake_deflections.JimenezDeflection,
|
|
256
|
+
"Jimenez_b<beta>_dx<dx>",
|
|
257
|
+
beta=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
258
|
+
dx=lambda dx: float(dx),
|
|
259
|
+
var2arg={"dx": "step_x"},
|
|
260
|
+
hints={
|
|
261
|
+
"beta": "(The Jimenez beta coefficient, e.g. 01 for 0.1)",
|
|
262
|
+
"dx": "(The step size in m for integration along wake path, e.g. 10)",
|
|
263
|
+
},
|
|
264
|
+
kwargs=dict(rotate=True),
|
|
265
|
+
)
|
|
266
|
+
self.wake_deflections.add_factory(
|
|
267
|
+
fm.wake_deflections.JimenezDeflection,
|
|
268
|
+
"JimenezProj_b<beta>",
|
|
269
|
+
beta=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
270
|
+
hints={"beta": "(The Jimenez beta coefficient, e.g. 01 for 0.1)"},
|
|
271
|
+
kwargs=dict(rotate=False),
|
|
272
|
+
)
|
|
273
|
+
self.wake_deflections.add_factory(
|
|
274
|
+
fm.wake_deflections.JimenezDeflection,
|
|
275
|
+
"JimenezProj_b<beta>_dx<dx>",
|
|
276
|
+
beta=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
277
|
+
dx=lambda dx: float(dx),
|
|
278
|
+
var2arg={"dx": "step_x"},
|
|
279
|
+
hints={
|
|
280
|
+
"beta": "(The Jimenez beta coefficient, e.g. 01 for 0.1)",
|
|
281
|
+
"dx": "(The step size in m for integration along wake path, e.g. 10)",
|
|
282
|
+
},
|
|
283
|
+
kwargs=dict(rotate=False),
|
|
284
|
+
)
|
|
285
|
+
self.wake_deflections.add_factory(
|
|
286
|
+
fm.wake_deflections.JimenezDeflection,
|
|
287
|
+
"JimenezPath_b<beta>",
|
|
288
|
+
beta=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
289
|
+
hints={"beta": "(The Jimenez beta coefficient, e.g. 01 for 0.1)"},
|
|
290
|
+
kwargs=dict(rotate=None),
|
|
291
|
+
)
|
|
292
|
+
self.wake_deflections.add_factory(
|
|
293
|
+
fm.wake_deflections.JimenezDeflection,
|
|
294
|
+
"JimenezPath_b<beta>_dx<dx>",
|
|
295
|
+
beta=lambda x: float(f"0.{x[1:]}" if x[0] == "0" else float(x)),
|
|
296
|
+
dx=lambda dx: float(dx),
|
|
297
|
+
var2arg={"dx": "step_x"},
|
|
298
|
+
hints={
|
|
299
|
+
"beta": "(The Jimenez beta coefficient, e.g. 01 for 0.1)",
|
|
300
|
+
"dx": "(The step size in m for integration along wake path, e.g. 10)",
|
|
301
|
+
},
|
|
302
|
+
kwargs=dict(rotate=None),
|
|
303
|
+
)
|
|
304
|
+
|
|
234
305
|
self.wake_frames = FDict(
|
|
235
306
|
name="wake_frames",
|
|
236
|
-
rotor_wd=fm.wake_frames.RotorWD(
|
|
307
|
+
rotor_wd=fm.wake_frames.RotorWD(),
|
|
237
308
|
rotor_wd_farmo=fm.wake_frames.FarmOrder(),
|
|
238
309
|
)
|
|
239
|
-
self.wake_frames.add_k_factory(
|
|
240
|
-
fm.wake_frames.YawedWakes,
|
|
241
|
-
"yawed_[wake_k]",
|
|
242
|
-
)
|
|
243
310
|
self.wake_frames.add_factory(
|
|
244
311
|
fm.wake_frames.Streamlines2D,
|
|
245
312
|
"streamlines_<step>",
|
|
@@ -336,6 +403,8 @@ class ModelBook:
|
|
|
336
403
|
ti_cubic=fm.wake_superpositions.TIPow(pow=3, superp_to_amb="quadratic"),
|
|
337
404
|
ti_quartic=fm.wake_superpositions.TIPow(pow=4, superp_to_amb="quadratic"),
|
|
338
405
|
ti_max=fm.wake_superpositions.TIMax(superp_to_amb="quadratic"),
|
|
406
|
+
vector=fm.wake_superpositions.WindVectorLinear(scale_amb=False),
|
|
407
|
+
vector_amb=fm.wake_superpositions.WindVectorLinear(scale_amb=True),
|
|
339
408
|
)
|
|
340
409
|
|
|
341
410
|
self.axial_induction = FDict(name="induction_models")
|
|
@@ -348,76 +417,114 @@ class ModelBook:
|
|
|
348
417
|
fm.wake_models.wind.JensenWake,
|
|
349
418
|
"Jensen_<superposition>_[wake_k]",
|
|
350
419
|
kwargs=dict(induction="Betz"),
|
|
351
|
-
superposition=lambda s: f"ws_{s}"
|
|
352
|
-
|
|
420
|
+
superposition=lambda s: f"ws_{s}"
|
|
421
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
422
|
+
else s,
|
|
423
|
+
hints={
|
|
424
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
425
|
+
},
|
|
353
426
|
)
|
|
354
427
|
|
|
355
428
|
self.wake_models.add_k_factory(
|
|
356
429
|
fm.wake_models.wind.Bastankhah2014,
|
|
357
430
|
"Bastankhah2014_<superposition>_[wake_k]",
|
|
358
431
|
kwargs=dict(sbeta_factor=0.2, induction="Madsen"),
|
|
359
|
-
superposition=lambda s: f"ws_{s}"
|
|
360
|
-
|
|
432
|
+
superposition=lambda s: f"ws_{s}"
|
|
433
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
434
|
+
else s,
|
|
435
|
+
hints={
|
|
436
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
437
|
+
},
|
|
361
438
|
)
|
|
362
439
|
self.wake_models.add_k_factory(
|
|
363
440
|
fm.wake_models.wind.Bastankhah2014,
|
|
364
441
|
"Bastankhah2014B_<superposition>_[wake_k]",
|
|
365
442
|
kwargs=dict(sbeta_factor=0.2, induction="Betz"),
|
|
366
|
-
superposition=lambda s: f"ws_{s}"
|
|
367
|
-
|
|
443
|
+
superposition=lambda s: f"ws_{s}"
|
|
444
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
445
|
+
else s,
|
|
446
|
+
hints={
|
|
447
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
448
|
+
},
|
|
368
449
|
)
|
|
369
450
|
self.wake_models.add_k_factory(
|
|
370
451
|
fm.wake_models.wind.Bastankhah2014,
|
|
371
452
|
"Bastankhah025_<superposition>_[wake_k]",
|
|
372
453
|
kwargs=dict(sbeta_factor=0.25, induction="Madsen"),
|
|
373
|
-
superposition=lambda s: f"ws_{s}"
|
|
374
|
-
|
|
454
|
+
superposition=lambda s: f"ws_{s}"
|
|
455
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
456
|
+
else s,
|
|
457
|
+
hints={
|
|
458
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
459
|
+
},
|
|
375
460
|
)
|
|
376
461
|
self.wake_models.add_k_factory(
|
|
377
462
|
fm.wake_models.wind.Bastankhah2014,
|
|
378
463
|
"Bastankhah025B_<superposition>_[wake_k]",
|
|
379
464
|
kwargs=dict(sbeta_factor=0.25, induction="Betz"),
|
|
380
|
-
superposition=lambda s: f"ws_{s}"
|
|
381
|
-
|
|
465
|
+
superposition=lambda s: f"ws_{s}"
|
|
466
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
467
|
+
else s,
|
|
468
|
+
hints={
|
|
469
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
470
|
+
},
|
|
382
471
|
)
|
|
383
472
|
|
|
384
473
|
self.wake_models.add_k_factory(
|
|
385
474
|
fm.wake_models.wind.Bastankhah2016,
|
|
386
475
|
"Bastankhah2016_<superposition>_[wake_k]",
|
|
387
476
|
kwargs=dict(induction="Madsen"),
|
|
388
|
-
superposition=lambda s: f"ws_{s}"
|
|
389
|
-
|
|
477
|
+
superposition=lambda s: f"ws_{s}"
|
|
478
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
479
|
+
else s,
|
|
480
|
+
hints={
|
|
481
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
482
|
+
},
|
|
390
483
|
)
|
|
391
484
|
self.wake_models.add_k_factory(
|
|
392
485
|
fm.wake_models.wind.Bastankhah2016,
|
|
393
486
|
"Bastankhah2016B_<superposition>_[wake_k]",
|
|
394
487
|
kwargs=dict(induction="Betz"),
|
|
395
|
-
superposition=lambda s: f"ws_{s}"
|
|
396
|
-
|
|
488
|
+
superposition=lambda s: f"ws_{s}"
|
|
489
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
490
|
+
else s,
|
|
491
|
+
hints={
|
|
492
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
493
|
+
},
|
|
397
494
|
)
|
|
398
495
|
|
|
399
496
|
self.wake_models.add_k_factory(
|
|
400
497
|
fm.wake_models.wind.TurbOParkWake,
|
|
401
498
|
"TurbOPark_<superposition>_[wake_k]",
|
|
402
499
|
kwargs=dict(induction="Madsen"),
|
|
403
|
-
superposition=lambda s: f"ws_{s}"
|
|
404
|
-
|
|
500
|
+
superposition=lambda s: f"ws_{s}"
|
|
501
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
502
|
+
else s,
|
|
503
|
+
hints={
|
|
504
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
505
|
+
},
|
|
405
506
|
)
|
|
406
507
|
self.wake_models.add_k_factory(
|
|
407
508
|
fm.wake_models.wind.TurbOParkWake,
|
|
408
509
|
"TurbOParkB_<superposition>_[wake_k]",
|
|
409
510
|
kwargs=dict(induction="Betz"),
|
|
410
|
-
superposition=lambda s: f"ws_{s}"
|
|
411
|
-
|
|
511
|
+
superposition=lambda s: f"ws_{s}"
|
|
512
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
513
|
+
else s,
|
|
514
|
+
hints={
|
|
515
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
516
|
+
},
|
|
412
517
|
)
|
|
413
518
|
|
|
414
519
|
self.wake_models.add_k_factory(
|
|
415
520
|
fm.wake_models.wind.TurbOParkWakeIX,
|
|
416
521
|
"TurbOParkIX_<superposition>_[wake_k]_dx<dx>",
|
|
417
|
-
superposition=lambda s: f"ws_{s}"
|
|
522
|
+
superposition=lambda s: f"ws_{s}"
|
|
523
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
524
|
+
else s,
|
|
418
525
|
dx=lambda x: float(x),
|
|
419
526
|
hints={
|
|
420
|
-
"superposition": "(Superposition, e.g. linear for ws_linear)",
|
|
527
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)",
|
|
421
528
|
"dx": "(Integration step in m)",
|
|
422
529
|
},
|
|
423
530
|
)
|
|
@@ -460,39 +567,53 @@ class ModelBook:
|
|
|
460
567
|
hints={"superposition": "(Superposition, e.g. linear for ti_linear)"},
|
|
461
568
|
)
|
|
462
569
|
|
|
463
|
-
self.wake_models[
|
|
570
|
+
self.wake_models["RHB"] = fm.wake_models.induction.RankineHalfBody()
|
|
464
571
|
|
|
465
|
-
self.wake_models[
|
|
572
|
+
self.wake_models["VortexSheet"] = fm.wake_models.induction.VortexSheet()
|
|
466
573
|
self.wake_models.add_factory(
|
|
467
574
|
fm.wake_models.induction.VortexSheet,
|
|
468
575
|
"VortexSheet_<superposition>",
|
|
469
|
-
superposition=lambda s: f"ws_{s}"
|
|
470
|
-
|
|
576
|
+
superposition=lambda s: f"ws_{s}"
|
|
577
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
578
|
+
else s,
|
|
579
|
+
hints={
|
|
580
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
581
|
+
},
|
|
471
582
|
)
|
|
472
583
|
|
|
473
|
-
self.wake_models[
|
|
584
|
+
self.wake_models["Rathmann"] = fm.wake_models.induction.Rathmann()
|
|
474
585
|
self.wake_models.add_factory(
|
|
475
586
|
fm.wake_models.induction.Rathmann,
|
|
476
587
|
"Rathmann_<superposition>",
|
|
477
|
-
superposition=lambda s: f"ws_{s}"
|
|
478
|
-
|
|
588
|
+
superposition=lambda s: f"ws_{s}"
|
|
589
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
590
|
+
else s,
|
|
591
|
+
hints={
|
|
592
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
593
|
+
},
|
|
479
594
|
)
|
|
480
595
|
|
|
481
|
-
self.wake_models[
|
|
482
|
-
self.wake_models[
|
|
483
|
-
fm.wake_models.induction.SelfSimilar2020()
|
|
484
|
-
)
|
|
596
|
+
self.wake_models["SelfSimilar"] = fm.wake_models.induction.SelfSimilar()
|
|
597
|
+
self.wake_models["SelfSimilar2020"] = fm.wake_models.induction.SelfSimilar2020()
|
|
485
598
|
self.wake_models.add_factory(
|
|
486
599
|
fm.wake_models.induction.SelfSimilar,
|
|
487
600
|
"SelfSimilar_<superposition>",
|
|
488
|
-
superposition=lambda s: f"ws_{s}"
|
|
489
|
-
|
|
601
|
+
superposition=lambda s: f"ws_{s}"
|
|
602
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
603
|
+
else s,
|
|
604
|
+
hints={
|
|
605
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
606
|
+
},
|
|
490
607
|
)
|
|
491
608
|
self.wake_models.add_factory(
|
|
492
609
|
fm.wake_models.induction.SelfSimilar2020,
|
|
493
610
|
"SelfSimilar2020_<superposition>",
|
|
494
|
-
superposition=lambda s: f"ws_{s}"
|
|
495
|
-
|
|
611
|
+
superposition=lambda s: f"ws_{s}"
|
|
612
|
+
if f"ws_{s}" in self.wake_superpositions
|
|
613
|
+
else s,
|
|
614
|
+
hints={
|
|
615
|
+
"superposition": "(Superposition, e.g. linear for ws_linear, or vector)"
|
|
616
|
+
},
|
|
496
617
|
)
|
|
497
618
|
|
|
498
619
|
self.ground_models = FDict(name="ground_models")
|
|
@@ -517,6 +638,7 @@ class ModelBook:
|
|
|
517
638
|
farm_controllers=self.farm_controllers,
|
|
518
639
|
partial_wakes=self.partial_wakes,
|
|
519
640
|
wake_frames=self.wake_frames,
|
|
641
|
+
wake_deflections=self.wake_deflections,
|
|
520
642
|
wake_superpositions=self.wake_superpositions,
|
|
521
643
|
wake_models=self.wake_models,
|
|
522
644
|
axial_induction=self.axial_induction,
|
|
@@ -532,6 +654,7 @@ class ModelBook:
|
|
|
532
654
|
farm_controllers=FarmController,
|
|
533
655
|
partial_wakes=PartialWakesModel,
|
|
534
656
|
wake_frames=WakeFrame,
|
|
657
|
+
wake_deflections=WakeDeflection,
|
|
535
658
|
wake_superpositions=WakeSuperposition,
|
|
536
659
|
wake_models=WakeModel,
|
|
537
660
|
axial_induction=AxialInductionModel,
|
|
@@ -563,16 +686,19 @@ class ModelBook:
|
|
|
563
686
|
if subset is None or k in subset:
|
|
564
687
|
print(k)
|
|
565
688
|
print("-" * len(k))
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
689
|
+
any = False
|
|
690
|
+
for mname in sorted(list(ms.keys())):
|
|
691
|
+
if search is None or search in mname:
|
|
692
|
+
print(f"{mname}: {ms[mname]}")
|
|
693
|
+
any = True
|
|
694
|
+
if isinstance(ms, FDict):
|
|
695
|
+
for f in ms.factories:
|
|
696
|
+
if search is None or search in f.name_template:
|
|
697
|
+
if any:
|
|
573
698
|
print()
|
|
574
|
-
|
|
575
|
-
|
|
699
|
+
print(f)
|
|
700
|
+
any = True
|
|
701
|
+
if not any:
|
|
576
702
|
print("(none)")
|
|
577
703
|
print()
|
|
578
704
|
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Partial wake models.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .centre import PartialCentre
|
|
6
|
-
from .rotor_points import RotorPoints
|
|
7
|
-
from .top_hat import PartialTopHat
|
|
8
|
-
from .axiwake import PartialAxiwake
|
|
9
|
-
from .segregated import PartialSegregated
|
|
10
|
-
from .grid import PartialGrid
|
|
5
|
+
from .centre import PartialCentre as PartialCentre
|
|
6
|
+
from .rotor_points import RotorPoints as RotorPoints
|
|
7
|
+
from .top_hat import PartialTopHat as PartialTopHat
|
|
8
|
+
from .axiwake import PartialAxiwake as PartialAxiwake
|
|
9
|
+
from .segregated import PartialSegregated as PartialSegregated
|
|
10
|
+
from .grid import PartialGrid as PartialGrid
|
|
@@ -101,8 +101,6 @@ class PartialAxiwake(PartialCentre):
|
|
|
101
101
|
The wake deltas. Key: variable name,
|
|
102
102
|
value: numpy.ndarray with shape
|
|
103
103
|
(n_states, n_targets, n_tpoints, ...)
|
|
104
|
-
wmodel: foxes.core.WakeModel
|
|
105
|
-
The wake model
|
|
106
104
|
|
|
107
105
|
"""
|
|
108
106
|
# check:
|
|
@@ -199,16 +197,43 @@ class PartialAxiwake(PartialCentre):
|
|
|
199
197
|
algo, mdata, fdata, tdata, downwind_index, x, r
|
|
200
198
|
)
|
|
201
199
|
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
# run superposition models:
|
|
201
|
+
if wmodel.affects_ws and wmodel.has_uv:
|
|
202
|
+
assert wmodel.has_vector_wind_superp, (
|
|
203
|
+
f"{self.name}: Expecting vector wind superposition in wake model '{wmodel.name}', got '{wmodel.wind_superposition}'"
|
|
204
|
+
)
|
|
205
|
+
if FV.WS in wdeltas or FV.UV in wdeltas:
|
|
206
|
+
if FV.UV not in wdeltas:
|
|
207
|
+
wmodel.vec_superp.wdeltas_ws2uv(
|
|
208
|
+
algo, fdata, tdata, downwind_index, wdeltas, st_sel
|
|
209
|
+
)
|
|
210
|
+
duv = np.einsum("snd,sn->sd", wdeltas.pop(FV.UV), weights[st_sel])
|
|
211
|
+
wake_deltas[FV.UV] = wmodel.vec_superp.add_wake_vector(
|
|
212
|
+
algo,
|
|
213
|
+
mdata,
|
|
214
|
+
fdata,
|
|
215
|
+
tdata,
|
|
216
|
+
downwind_index,
|
|
217
|
+
st_sel,
|
|
218
|
+
wake_deltas[FV.UV],
|
|
219
|
+
duv[:, None],
|
|
220
|
+
)
|
|
221
|
+
del duv
|
|
222
|
+
for v in [FV.WS, FV.WD, FV.UV]:
|
|
223
|
+
if v in wdeltas:
|
|
224
|
+
del wdeltas[v]
|
|
204
225
|
|
|
226
|
+
for v, wdel in wdeltas.items():
|
|
205
227
|
try:
|
|
206
228
|
superp = wmodel.superp[v]
|
|
207
229
|
except KeyError:
|
|
230
|
+
s = {v: m.name for v, m in wmodel.superp.items()}
|
|
208
231
|
raise KeyError(
|
|
209
|
-
f"Model '{self.name}': Missing wake superposition entry for variable '{v}' in wake model '{wmodel.name}', found {
|
|
232
|
+
f"Model '{self.name}': Missing wake superposition entry for variable '{v}' in wake model '{wmodel.name}', found {s}"
|
|
210
233
|
)
|
|
211
234
|
|
|
235
|
+
d = np.einsum("sn,sn->s", wdel, weights[st_sel])
|
|
236
|
+
|
|
212
237
|
wake_deltas[v] = superp.add_wake(
|
|
213
238
|
algo,
|
|
214
239
|
mdata,
|