foxes 1.2.5__py3-none-any.whl → 1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of foxes might be problematic. Click here for more details.
- docs/source/conf.py +3 -3
- examples/abl_states/run.py +2 -2
- examples/compare_rotors_pwakes/run.py +1 -1
- examples/compare_wakes/run.py +1 -2
- examples/dyn_wakes/run.py +29 -6
- examples/induction/run.py +3 -3
- examples/multi_height/run.py +1 -1
- examples/power_mask/run.py +2 -2
- examples/quickstart/run.py +16 -0
- examples/random_timeseries/run.py +3 -4
- examples/scan_row/run.py +3 -3
- examples/sequential/run.py +33 -10
- examples/single_state/run.py +3 -4
- examples/states_lookup_table/run.py +3 -3
- examples/streamline_wakes/run.py +27 -4
- examples/tab_file/run.py +3 -3
- examples/timelines/run.py +29 -5
- examples/timeseries/run.py +3 -3
- examples/timeseries_slurm/run.py +3 -3
- examples/wind_rose/run.py +3 -3
- examples/yawed_wake/run.py +16 -8
- foxes/__init__.py +22 -18
- foxes/algorithms/__init__.py +6 -6
- foxes/algorithms/downwind/__init__.py +2 -2
- foxes/algorithms/downwind/downwind.py +53 -27
- foxes/algorithms/downwind/models/__init__.py +6 -6
- foxes/algorithms/downwind/models/farm_wakes_calc.py +22 -14
- foxes/algorithms/downwind/models/init_farm_data.py +4 -5
- foxes/algorithms/downwind/models/point_wakes_calc.py +7 -13
- foxes/algorithms/downwind/models/reorder_farm_output.py +5 -1
- foxes/algorithms/downwind/models/set_amb_point_results.py +7 -7
- foxes/algorithms/iterative/__init__.py +7 -3
- foxes/algorithms/iterative/iterative.py +1 -2
- foxes/algorithms/iterative/models/__init__.py +7 -3
- foxes/algorithms/iterative/models/farm_wakes_calc.py +15 -8
- foxes/algorithms/sequential/__init__.py +3 -3
- foxes/algorithms/sequential/models/__init__.py +2 -2
- foxes/algorithms/sequential/models/seq_state.py +0 -18
- foxes/algorithms/sequential/sequential.py +8 -22
- foxes/config/__init__.py +5 -1
- foxes/constants.py +22 -0
- foxes/core/__init__.py +45 -22
- foxes/core/algorithm.py +0 -1
- foxes/core/data.py +56 -29
- foxes/core/engine.py +28 -14
- foxes/core/farm_controller.py +2 -2
- foxes/core/farm_data_model.py +1 -0
- foxes/core/ground_model.py +4 -13
- foxes/core/model.py +5 -5
- foxes/core/partial_wakes_model.py +147 -10
- foxes/core/point_data_model.py +2 -3
- foxes/core/rotor_model.py +42 -38
- foxes/core/states.py +4 -50
- foxes/core/turbine.py +2 -1
- foxes/core/wake_deflection.py +130 -0
- foxes/core/wake_model.py +222 -9
- foxes/core/wake_superposition.py +122 -4
- foxes/core/wind_farm.py +6 -6
- foxes/data/__init__.py +7 -2
- foxes/data/states/weibull_sectors_12.csv +13 -0
- foxes/data/states/weibull_sectors_12.nc +0 -0
- foxes/engines/__init__.py +14 -15
- foxes/engines/dask.py +39 -14
- foxes/engines/numpy.py +0 -3
- foxes/input/__init__.py +3 -3
- foxes/input/farm_layout/__init__.py +8 -8
- foxes/input/farm_layout/from_csv.py +1 -1
- foxes/input/farm_layout/ring.py +0 -1
- foxes/input/states/__init__.py +22 -11
- foxes/input/states/create/__init__.py +3 -2
- foxes/input/states/field_data_nc.py +48 -84
- foxes/input/states/multi_height.py +40 -60
- foxes/input/states/one_point_flow.py +22 -25
- foxes/input/states/scan.py +6 -19
- foxes/input/states/single.py +6 -18
- foxes/input/states/states_table.py +25 -44
- foxes/input/states/weibull_sectors.py +225 -0
- foxes/input/states/wrg_states.py +151 -37
- foxes/input/yaml/__init__.py +9 -3
- foxes/input/yaml/dict.py +19 -19
- foxes/input/yaml/windio/__init__.py +10 -5
- foxes/input/yaml/windio/read_attributes.py +2 -2
- foxes/input/yaml/windio/read_farm.py +5 -5
- foxes/input/yaml/windio/read_fields.py +4 -2
- foxes/input/yaml/windio/read_site.py +52 -0
- foxes/input/yaml/windio/windio.py +1 -1
- foxes/models/__init__.py +15 -14
- foxes/models/axial_induction/__init__.py +2 -2
- foxes/models/farm_controllers/__init__.py +1 -1
- foxes/models/farm_models/__init__.py +1 -1
- foxes/models/ground_models/__init__.py +3 -2
- foxes/models/ground_models/wake_mirror.py +3 -3
- foxes/models/model_book.py +175 -49
- foxes/models/partial_wakes/__init__.py +6 -6
- foxes/models/partial_wakes/axiwake.py +30 -5
- foxes/models/partial_wakes/centre.py +47 -0
- foxes/models/partial_wakes/rotor_points.py +45 -9
- foxes/models/partial_wakes/segregated.py +2 -20
- foxes/models/partial_wakes/top_hat.py +27 -2
- foxes/models/point_models/__init__.py +4 -4
- foxes/models/rotor_models/__init__.py +3 -3
- foxes/models/rotor_models/centre.py +6 -4
- foxes/models/turbine_models/__init__.py +11 -11
- foxes/models/turbine_models/set_farm_vars.py +0 -1
- foxes/models/turbine_types/PCt_file.py +0 -2
- foxes/models/turbine_types/PCt_from_two.py +0 -2
- foxes/models/turbine_types/__init__.py +9 -9
- foxes/models/vertical_profiles/__init__.py +7 -7
- foxes/models/wake_deflections/__init__.py +3 -0
- foxes/models/{wake_frames/yawed_wakes.py → wake_deflections/bastankhah2016.py} +32 -111
- foxes/models/wake_deflections/jimenez.py +277 -0
- foxes/models/wake_deflections/no_deflection.py +94 -0
- foxes/models/wake_frames/__init__.py +6 -7
- foxes/models/wake_frames/dynamic_wakes.py +12 -3
- foxes/models/wake_frames/rotor_wd.py +3 -1
- foxes/models/wake_frames/seq_dynamic_wakes.py +45 -8
- foxes/models/wake_frames/streamlines.py +8 -6
- foxes/models/wake_frames/timelines.py +19 -3
- foxes/models/wake_models/__init__.py +7 -7
- foxes/models/wake_models/dist_sliced.py +50 -84
- foxes/models/wake_models/gaussian.py +20 -0
- foxes/models/wake_models/induction/__init__.py +5 -5
- foxes/models/wake_models/induction/rankine_half_body.py +30 -71
- foxes/models/wake_models/induction/rathmann.py +65 -64
- foxes/models/wake_models/induction/self_similar.py +65 -68
- foxes/models/wake_models/induction/self_similar2020.py +0 -3
- foxes/models/wake_models/induction/vortex_sheet.py +71 -75
- foxes/models/wake_models/ti/__init__.py +2 -2
- foxes/models/wake_models/ti/crespo_hernandez.py +5 -3
- foxes/models/wake_models/ti/iec_ti.py +6 -4
- foxes/models/wake_models/top_hat.py +58 -7
- foxes/models/wake_models/wind/__init__.py +6 -4
- foxes/models/wake_models/wind/bastankhah14.py +25 -7
- foxes/models/wake_models/wind/bastankhah16.py +35 -3
- foxes/models/wake_models/wind/jensen.py +15 -2
- foxes/models/wake_models/wind/turbopark.py +28 -2
- foxes/models/wake_superpositions/__init__.py +18 -9
- foxes/models/wake_superpositions/ti_linear.py +4 -4
- foxes/models/wake_superpositions/ti_max.py +4 -4
- foxes/models/wake_superpositions/ti_pow.py +4 -4
- foxes/models/wake_superpositions/ti_quadratic.py +4 -4
- foxes/models/wake_superpositions/wind_vector.py +257 -0
- foxes/models/wake_superpositions/ws_linear.py +9 -10
- foxes/models/wake_superpositions/ws_max.py +8 -8
- foxes/models/wake_superpositions/ws_pow.py +8 -8
- foxes/models/wake_superpositions/ws_product.py +4 -4
- foxes/models/wake_superpositions/ws_quadratic.py +8 -8
- foxes/output/__init__.py +21 -19
- foxes/output/farm_layout.py +14 -6
- foxes/output/farm_results_eval.py +51 -27
- foxes/output/flow_plots_2d/__init__.py +2 -2
- foxes/output/flow_plots_2d/get_fig.py +4 -2
- foxes/output/rose_plot.py +23 -5
- foxes/output/seq_plugins/__init__.py +2 -2
- foxes/output/seq_plugins/seq_flow_ani_plugin.py +0 -3
- foxes/output/seq_plugins/seq_wake_debug_plugin.py +0 -1
- foxes/output/slice_data.py +16 -19
- foxes/output/turbine_type_curves.py +7 -8
- foxes/utils/__init__.py +37 -19
- foxes/utils/abl/__init__.py +4 -4
- foxes/utils/cubic_roots.py +1 -1
- foxes/utils/data_book.py +4 -3
- foxes/utils/dict.py +3 -3
- foxes/utils/exec_python.py +5 -5
- foxes/utils/factory.py +1 -3
- foxes/utils/geom2d/__init__.py +7 -5
- foxes/utils/geopandas_utils.py +2 -2
- foxes/utils/pandas_utils.py +4 -3
- foxes/utils/tab_files.py +0 -1
- foxes/utils/weibull.py +28 -0
- foxes/utils/wrg_utils.py +3 -1
- foxes/utils/xarray_utils.py +9 -2
- foxes/variables.py +67 -9
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/METADATA +14 -21
- foxes-1.4.dist-info/RECORD +320 -0
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/WHEEL +1 -1
- tests/0_consistency/iterative/test_iterative.py +2 -3
- tests/0_consistency/partial_wakes/test_partial_wakes.py +2 -2
- tests/1_verification/flappy_0_6/PCt_files/flappy/run.py +2 -3
- tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +48 -56
- tests/1_verification/flappy_0_6/abl_states/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +33 -36
- tests/1_verification/flappy_0_6/partial_top_hat/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +0 -2
- tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +3 -3
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +3 -4
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +3 -4
- tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +3 -4
- tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +3 -4
- tests/1_verification/flappy_0_6_2/grid_rotors/flappy/run.py +0 -2
- tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +3 -3
- tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +3 -3
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/flappy/run.py +0 -1
- tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +3 -4
- tests/3_examples/test_examples.py +3 -2
- foxes/output/round.py +0 -10
- foxes/utils/pandas_helpers.py +0 -178
- foxes-1.2.5.dist-info/RECORD +0 -312
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/entry_points.txt +0 -0
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info/licenses}/LICENSE +0 -0
- {foxes-1.2.5.dist-info → foxes-1.4.dist-info}/top_level.txt +0 -0
|
@@ -95,8 +95,8 @@ class TILinear(WakeSuperposition):
|
|
|
95
95
|
algo,
|
|
96
96
|
mdata,
|
|
97
97
|
fdata,
|
|
98
|
+
tdata,
|
|
98
99
|
variable,
|
|
99
|
-
amb_results,
|
|
100
100
|
wake_delta,
|
|
101
101
|
):
|
|
102
102
|
"""
|
|
@@ -111,11 +111,10 @@ class TILinear(WakeSuperposition):
|
|
|
111
111
|
The model data
|
|
112
112
|
fdata: foxes.core.FData
|
|
113
113
|
The farm data
|
|
114
|
+
tdata: foxes.core.TData
|
|
115
|
+
The target point data
|
|
114
116
|
variable: str
|
|
115
117
|
The variable name for which the wake deltas applies
|
|
116
|
-
amb_results: numpy.ndarray
|
|
117
|
-
The ambient results at targets,
|
|
118
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
119
118
|
wake_delta: numpy.ndarray
|
|
120
119
|
The wake deltas at targets, shape:
|
|
121
120
|
(n_states, n_targets, n_tpoints)
|
|
@@ -134,6 +133,7 @@ class TILinear(WakeSuperposition):
|
|
|
134
133
|
|
|
135
134
|
# quadratic superposition to ambient:
|
|
136
135
|
elif self.superp_to_amb == "quadratic":
|
|
136
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
137
137
|
return np.sqrt(wake_delta**2 + amb_results**2) - amb_results
|
|
138
138
|
|
|
139
139
|
# unknown ti delta:
|
|
@@ -95,8 +95,8 @@ class TIMax(WakeSuperposition):
|
|
|
95
95
|
algo,
|
|
96
96
|
mdata,
|
|
97
97
|
fdata,
|
|
98
|
+
tdata,
|
|
98
99
|
variable,
|
|
99
|
-
amb_results,
|
|
100
100
|
wake_delta,
|
|
101
101
|
):
|
|
102
102
|
"""
|
|
@@ -111,11 +111,10 @@ class TIMax(WakeSuperposition):
|
|
|
111
111
|
The model data
|
|
112
112
|
fdata: foxes.core.FData
|
|
113
113
|
The farm data
|
|
114
|
+
tdata: foxes.core.TData
|
|
115
|
+
The target point data
|
|
114
116
|
variable: str
|
|
115
117
|
The variable name for which the wake deltas applies
|
|
116
|
-
amb_results: numpy.ndarray
|
|
117
|
-
The ambient results at targets,
|
|
118
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
119
118
|
wake_delta: numpy.ndarray
|
|
120
119
|
The wake deltas at targets, shape:
|
|
121
120
|
(n_states, n_targets, n_tpoints)
|
|
@@ -134,6 +133,7 @@ class TIMax(WakeSuperposition):
|
|
|
134
133
|
|
|
135
134
|
# quadratic superposition to ambient:
|
|
136
135
|
elif self.superp_to_amb == "quadratic":
|
|
136
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
137
137
|
return np.sqrt(wake_delta**2 + amb_results**2) - amb_results
|
|
138
138
|
|
|
139
139
|
# unknown ti delta:
|
|
@@ -102,8 +102,8 @@ class TIPow(WakeSuperposition):
|
|
|
102
102
|
algo,
|
|
103
103
|
mdata,
|
|
104
104
|
fdata,
|
|
105
|
+
tdata,
|
|
105
106
|
variable,
|
|
106
|
-
amb_results,
|
|
107
107
|
wake_delta,
|
|
108
108
|
):
|
|
109
109
|
"""
|
|
@@ -118,11 +118,10 @@ class TIPow(WakeSuperposition):
|
|
|
118
118
|
The model data
|
|
119
119
|
fdata: foxes.core.FData
|
|
120
120
|
The farm data
|
|
121
|
+
tdata: foxes.core.TData
|
|
122
|
+
The target point data
|
|
121
123
|
variable: str
|
|
122
124
|
The variable name for which the wake deltas applies
|
|
123
|
-
amb_results: numpy.ndarray
|
|
124
|
-
The ambient results at targets,
|
|
125
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
126
125
|
wake_delta: numpy.ndarray
|
|
127
126
|
The wake deltas at targets, shape:
|
|
128
127
|
(n_states, n_targets, n_tpoints)
|
|
@@ -141,6 +140,7 @@ class TIPow(WakeSuperposition):
|
|
|
141
140
|
|
|
142
141
|
# quadratic superposition to ambient:
|
|
143
142
|
elif self.superp_to_amb == "quadratic":
|
|
143
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
144
144
|
return np.sqrt(wake_delta ** (2 / self.pow) + amb_results**2) - amb_results
|
|
145
145
|
|
|
146
146
|
# unknown ti delta:
|
|
@@ -95,8 +95,8 @@ class TIQuadratic(WakeSuperposition):
|
|
|
95
95
|
algo,
|
|
96
96
|
mdata,
|
|
97
97
|
fdata,
|
|
98
|
+
tdata,
|
|
98
99
|
variable,
|
|
99
|
-
amb_results,
|
|
100
100
|
wake_delta,
|
|
101
101
|
):
|
|
102
102
|
"""
|
|
@@ -111,11 +111,10 @@ class TIQuadratic(WakeSuperposition):
|
|
|
111
111
|
The model data
|
|
112
112
|
fdata: foxes.core.FData
|
|
113
113
|
The farm data
|
|
114
|
+
tdata: foxes.core.TData
|
|
115
|
+
The target point data
|
|
114
116
|
variable: str
|
|
115
117
|
The variable name for which the wake deltas applies
|
|
116
|
-
amb_results: numpy.ndarray
|
|
117
|
-
The ambient results at targets,
|
|
118
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
119
118
|
wake_delta: numpy.ndarray
|
|
120
119
|
The wake deltas at targets, shape:
|
|
121
120
|
(n_states, n_targets, n_tpoints)
|
|
@@ -134,6 +133,7 @@ class TIQuadratic(WakeSuperposition):
|
|
|
134
133
|
|
|
135
134
|
# quadratic superposition to ambient:
|
|
136
135
|
elif self.superp_to_amb == "quadratic":
|
|
136
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
137
137
|
return np.sqrt(wake_delta + amb_results**2) - amb_results
|
|
138
138
|
|
|
139
139
|
# unknown ti delta:
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from foxes.core import WindVectorWakeSuperposition
|
|
4
|
+
from foxes.utils import wd2uv, uv2wd, delta_wd
|
|
5
|
+
import foxes.variables as FV
|
|
6
|
+
import foxes.constants as FC
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WindVectorLinear(WindVectorWakeSuperposition):
|
|
10
|
+
"""
|
|
11
|
+
Linear superposition of wind deficit vector results
|
|
12
|
+
|
|
13
|
+
Attributes
|
|
14
|
+
----------
|
|
15
|
+
scale_amb: bool
|
|
16
|
+
Flag for scaling wind deficit with ambient wind speed
|
|
17
|
+
instead of waked wind speed
|
|
18
|
+
|
|
19
|
+
:group: models.wake_superpositions
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, scale_amb=False):
|
|
24
|
+
"""
|
|
25
|
+
Constructor.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
scale_amb: bool
|
|
30
|
+
Flag for scaling wind deficit with ambient wind speed
|
|
31
|
+
instead of waked wind speed
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
super().__init__()
|
|
35
|
+
self.scale_amb = scale_amb
|
|
36
|
+
|
|
37
|
+
def __repr__(self):
|
|
38
|
+
a = f"scale_amb={self.scale_amb}"
|
|
39
|
+
return f"{type(self).__name__}({a})"
|
|
40
|
+
|
|
41
|
+
def input_farm_vars(self, algo):
|
|
42
|
+
"""
|
|
43
|
+
The variables which are needed for running
|
|
44
|
+
the model.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
algo: foxes.core.Algorithm
|
|
49
|
+
The calculation algorithm
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
input_vars: list of str
|
|
54
|
+
The input variable names
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
return [FV.AMB_REWS] if self.scale_amb else [FV.REWS]
|
|
58
|
+
|
|
59
|
+
def wdeltas_ws2uv(self, algo, fdata, tdata, downwind_index, wdeltas, st_sel):
|
|
60
|
+
"""
|
|
61
|
+
Transform results from wind speed to wind vector data
|
|
62
|
+
|
|
63
|
+
Parameters
|
|
64
|
+
----------
|
|
65
|
+
algo: foxes.core.Algorithm
|
|
66
|
+
The calculation algorithm
|
|
67
|
+
fdata: foxes.core.FData
|
|
68
|
+
The farm data
|
|
69
|
+
tdata: foxes.core.TData
|
|
70
|
+
The target point data
|
|
71
|
+
downwind_index: int
|
|
72
|
+
The index of the wake causing turbine
|
|
73
|
+
in the downwind order
|
|
74
|
+
wdeltas: dict
|
|
75
|
+
The wake deltas. Key: variable name str,
|
|
76
|
+
value: numpy.ndarray, shape: (n_st_sel, n_tpoints)
|
|
77
|
+
st_sel: numpy.ndarray of bool
|
|
78
|
+
The state-target selection, for which the wake
|
|
79
|
+
is non-zero, shape: (n_states, n_targets)
|
|
80
|
+
|
|
81
|
+
Returns
|
|
82
|
+
-------
|
|
83
|
+
wdeltas: dict
|
|
84
|
+
The wake deltas. Key: variable name str,
|
|
85
|
+
value: numpy.ndarray, now respecting has_uv flag
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
if FV.AMB_UV not in tdata:
|
|
89
|
+
tdata[FV.AMB_UV] = wd2uv(tdata[FV.AMB_WD], tdata[FV.AMB_WS])
|
|
90
|
+
if FV.UV not in wdeltas:
|
|
91
|
+
assert FV.WS in wdeltas, (
|
|
92
|
+
f"{self.name}: Expecting '{FV.WS}' in wdeltas, got {list(wdeltas.keys())}"
|
|
93
|
+
)
|
|
94
|
+
scale = self.get_data(
|
|
95
|
+
FV.AMB_REWS if self.scale_amb else FV.REWS,
|
|
96
|
+
FC.STATE_TARGET_TPOINT,
|
|
97
|
+
lookup="w",
|
|
98
|
+
algo=algo,
|
|
99
|
+
fdata=fdata,
|
|
100
|
+
tdata=tdata,
|
|
101
|
+
downwind_index=downwind_index,
|
|
102
|
+
upcast=False,
|
|
103
|
+
selection=st_sel,
|
|
104
|
+
)
|
|
105
|
+
ws0 = tdata[FV.AMB_WS][st_sel]
|
|
106
|
+
wd0 = tdata[FV.AMB_WD][st_sel]
|
|
107
|
+
dws = scale * wdeltas.pop(FV.WS)
|
|
108
|
+
dwd = wdeltas.pop(FV.WD, 0)
|
|
109
|
+
wdeltas[FV.UV] = wd2uv(wd0 + dwd, ws0 + dws) - tdata[FV.AMB_UV][st_sel]
|
|
110
|
+
|
|
111
|
+
return wdeltas
|
|
112
|
+
|
|
113
|
+
def wdeltas_uv2ws(self, algo, fdata, tdata, downwind_index, wdeltas, st_sel):
|
|
114
|
+
"""
|
|
115
|
+
Transform results from wind vector to wind speed data
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
algo: foxes.core.Algorithm
|
|
120
|
+
The calculation algorithm
|
|
121
|
+
fdata: foxes.core.FData
|
|
122
|
+
The farm data
|
|
123
|
+
tdata: foxes.core.TData
|
|
124
|
+
The target point data
|
|
125
|
+
downwind_index: int
|
|
126
|
+
The index of the wake causing turbine
|
|
127
|
+
in the downwind order
|
|
128
|
+
wdeltas: dict
|
|
129
|
+
The wake deltas. Key: variable name str,
|
|
130
|
+
value: numpy.ndarray, shape: (n_st_sel, n_tpoints)
|
|
131
|
+
st_sel: numpy.ndarray of bool
|
|
132
|
+
The state-target selection, for which the wake
|
|
133
|
+
is non-zero, shape: (n_states, n_targets)
|
|
134
|
+
|
|
135
|
+
Returns
|
|
136
|
+
-------
|
|
137
|
+
wdeltas: dict
|
|
138
|
+
The wake deltas. Key: variable name str,
|
|
139
|
+
value: numpy.ndarray, now respecting has_uv flag
|
|
140
|
+
|
|
141
|
+
"""
|
|
142
|
+
if FV.UV in wdeltas:
|
|
143
|
+
scale = self.get_data(
|
|
144
|
+
FV.AMB_REWS if self.scale_amb else FV.REWS,
|
|
145
|
+
FC.STATE_TARGET_TPOINT,
|
|
146
|
+
lookup="w",
|
|
147
|
+
algo=algo,
|
|
148
|
+
fdata=fdata,
|
|
149
|
+
tdata=tdata,
|
|
150
|
+
downwind_index=downwind_index,
|
|
151
|
+
upcast=False,
|
|
152
|
+
selection=st_sel,
|
|
153
|
+
)
|
|
154
|
+
ws0 = tdata[FV.AMB_WS][st_sel]
|
|
155
|
+
wd0 = tdata[FV.AMB_WD][st_sel]
|
|
156
|
+
uv = tdata[FV.AMB_UV][st_sel] + wdeltas.pop(FV.UV)
|
|
157
|
+
wdeltas[FV.WD] = delta_wd(wd0, uv2wd(uv))
|
|
158
|
+
wdeltas[FV.WS] = (np.linalg.norm(uv, axis=-1) - ws0) / scale
|
|
159
|
+
|
|
160
|
+
return wdeltas
|
|
161
|
+
|
|
162
|
+
def add_wake_vector(
|
|
163
|
+
self,
|
|
164
|
+
algo,
|
|
165
|
+
mdata,
|
|
166
|
+
fdata,
|
|
167
|
+
tdata,
|
|
168
|
+
downwind_index,
|
|
169
|
+
st_sel,
|
|
170
|
+
wake_delta_uv,
|
|
171
|
+
wake_model_result_uv,
|
|
172
|
+
):
|
|
173
|
+
"""
|
|
174
|
+
Add a wake delta vector to previous wake deltas,
|
|
175
|
+
at rotor points.
|
|
176
|
+
|
|
177
|
+
Parameters
|
|
178
|
+
----------
|
|
179
|
+
algo: foxes.core.Algorithm
|
|
180
|
+
The calculation algorithm
|
|
181
|
+
mdata: foxes.core.MData
|
|
182
|
+
The model data
|
|
183
|
+
fdata: foxes.core.FData
|
|
184
|
+
The farm data
|
|
185
|
+
tdata: foxes.core.TData
|
|
186
|
+
The target point data
|
|
187
|
+
downwind_index: int
|
|
188
|
+
The index of the wake causing turbine
|
|
189
|
+
in the downwind order
|
|
190
|
+
st_sel: numpy.ndarray of bool
|
|
191
|
+
The selection of targets, shape: (n_states, n_targets)
|
|
192
|
+
wake_delta_uv: numpy.ndarray
|
|
193
|
+
The original wind vector wake deltas, shape:
|
|
194
|
+
(n_states, n_targets, n_tpoints, 2)
|
|
195
|
+
wake_model_result_uv: numpy.ndarray
|
|
196
|
+
The new wind vector wake deltas of the selected rotors,
|
|
197
|
+
shape: (n_st_sel, n_tpoints, 2, ...)
|
|
198
|
+
|
|
199
|
+
Returns
|
|
200
|
+
-------
|
|
201
|
+
wdelta_uv: numpy.ndarray
|
|
202
|
+
The updated wind vector wake deltas, shape:
|
|
203
|
+
(n_states, n_targets, n_tpoints, ...)
|
|
204
|
+
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
if np.any(st_sel):
|
|
208
|
+
wake_delta_uv[st_sel] += wake_model_result_uv
|
|
209
|
+
|
|
210
|
+
return wake_delta_uv
|
|
211
|
+
|
|
212
|
+
def calc_final_wake_delta_uv(
|
|
213
|
+
self,
|
|
214
|
+
algo,
|
|
215
|
+
mdata,
|
|
216
|
+
fdata,
|
|
217
|
+
tdata,
|
|
218
|
+
wake_delta_uv,
|
|
219
|
+
):
|
|
220
|
+
"""
|
|
221
|
+
Calculate the final wind vector wake delta after adding all
|
|
222
|
+
contributions.
|
|
223
|
+
|
|
224
|
+
Parameters
|
|
225
|
+
----------
|
|
226
|
+
algo: foxes.core.Algorithm
|
|
227
|
+
The calculation algorithm
|
|
228
|
+
mdata: foxes.core.MData
|
|
229
|
+
The model data
|
|
230
|
+
fdata: foxes.core.FData
|
|
231
|
+
The farm data
|
|
232
|
+
tdata: foxes.core.TData
|
|
233
|
+
The target point data
|
|
234
|
+
wake_delta_uv: numpy.ndarray
|
|
235
|
+
The original wind vector wake deltas, shape:
|
|
236
|
+
(n_states, n_targets, n_tpoints, 2)
|
|
237
|
+
|
|
238
|
+
Returns
|
|
239
|
+
-------
|
|
240
|
+
final_wake_delta_ws: numpy.ndarray
|
|
241
|
+
The final wind speed wake delta, which will be added to
|
|
242
|
+
the ambient results by simple plus operation. Shape:
|
|
243
|
+
(n_states, n_targets, n_tpoints)
|
|
244
|
+
final_wake_delta_wd: numpy.ndarray
|
|
245
|
+
The final wind direction wake delta, which will be added to
|
|
246
|
+
the ambient results by simple plus operation. Shape:
|
|
247
|
+
(n_states, n_targets, n_tpoints)
|
|
248
|
+
|
|
249
|
+
"""
|
|
250
|
+
if FV.AMB_UV not in tdata:
|
|
251
|
+
tdata[FV.AMB_UV] = wd2uv(tdata[FV.AMB_WD], tdata[FV.AMB_WS])
|
|
252
|
+
|
|
253
|
+
uv = tdata[FV.AMB_UV] + wake_delta_uv
|
|
254
|
+
dwd = delta_wd(tdata[FV.AMB_WD], uv2wd(uv))
|
|
255
|
+
dws = np.linalg.norm(uv, axis=-1) - tdata[FV.AMB_WS]
|
|
256
|
+
|
|
257
|
+
return dws, dwd
|
|
@@ -140,8 +140,8 @@ class WSLinear(WakeSuperposition):
|
|
|
140
140
|
algo,
|
|
141
141
|
mdata,
|
|
142
142
|
fdata,
|
|
143
|
+
tdata,
|
|
143
144
|
variable,
|
|
144
|
-
amb_results,
|
|
145
145
|
wake_delta,
|
|
146
146
|
):
|
|
147
147
|
"""
|
|
@@ -156,11 +156,10 @@ class WSLinear(WakeSuperposition):
|
|
|
156
156
|
The model data
|
|
157
157
|
fdata: foxes.core.FData
|
|
158
158
|
The farm data
|
|
159
|
+
tdata: foxes.core.TData
|
|
160
|
+
The target point data
|
|
159
161
|
variable: str
|
|
160
162
|
The variable name for which the wake deltas applies
|
|
161
|
-
amb_results: numpy.ndarray
|
|
162
|
-
The ambient results at targets,
|
|
163
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
164
163
|
wake_delta: numpy.ndarray
|
|
165
164
|
The wake deltas at targets, shape:
|
|
166
165
|
(n_states, n_targets, n_tpoints)
|
|
@@ -175,9 +174,9 @@ class WSLinear(WakeSuperposition):
|
|
|
175
174
|
"""
|
|
176
175
|
w = wake_delta
|
|
177
176
|
if self.lim_low is not None:
|
|
178
|
-
w = np.maximum(w, self.lim_low -
|
|
177
|
+
w = np.maximum(w, self.lim_low - tdata[FV.var2amb[variable]])
|
|
179
178
|
if self.lim_high is not None:
|
|
180
|
-
w = np.minimum(w, self.lim_high -
|
|
179
|
+
w = np.minimum(w, self.lim_high - tdata[FV.var2amb[variable]])
|
|
181
180
|
return w
|
|
182
181
|
|
|
183
182
|
|
|
@@ -296,8 +295,8 @@ class WSLinearLocal(WakeSuperposition):
|
|
|
296
295
|
algo,
|
|
297
296
|
mdata,
|
|
298
297
|
fdata,
|
|
298
|
+
tdata,
|
|
299
299
|
variable,
|
|
300
|
-
amb_results,
|
|
301
300
|
wake_delta,
|
|
302
301
|
):
|
|
303
302
|
"""
|
|
@@ -312,11 +311,10 @@ class WSLinearLocal(WakeSuperposition):
|
|
|
312
311
|
The model data
|
|
313
312
|
fdata: foxes.core.FData
|
|
314
313
|
The farm data
|
|
314
|
+
tdata: foxes.core.TData
|
|
315
|
+
The target point data
|
|
315
316
|
variable: str
|
|
316
317
|
The variable name for which the wake deltas applies
|
|
317
|
-
amb_results: numpy.ndarray
|
|
318
|
-
The ambient results at targets,
|
|
319
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
320
318
|
wake_delta: numpy.ndarray
|
|
321
319
|
The wake deltas at targets, shape:
|
|
322
320
|
(n_states, n_targets, n_tpoints)
|
|
@@ -329,6 +327,7 @@ class WSLinearLocal(WakeSuperposition):
|
|
|
329
327
|
(n_states, n_targets, n_tpoints)
|
|
330
328
|
|
|
331
329
|
"""
|
|
330
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
332
331
|
w = wake_delta * amb_results
|
|
333
332
|
if self.lim_low is not None:
|
|
334
333
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -143,8 +143,8 @@ class WSMax(WakeSuperposition):
|
|
|
143
143
|
algo,
|
|
144
144
|
mdata,
|
|
145
145
|
fdata,
|
|
146
|
+
tdata,
|
|
146
147
|
variable,
|
|
147
|
-
amb_results,
|
|
148
148
|
wake_delta,
|
|
149
149
|
):
|
|
150
150
|
"""
|
|
@@ -159,11 +159,10 @@ class WSMax(WakeSuperposition):
|
|
|
159
159
|
The model data
|
|
160
160
|
fdata: foxes.core.FData
|
|
161
161
|
The farm data
|
|
162
|
+
tdata: foxes.core.TData
|
|
163
|
+
The target point data
|
|
162
164
|
variable: str
|
|
163
165
|
The variable name for which the wake deltas applies
|
|
164
|
-
amb_results: numpy.ndarray
|
|
165
|
-
The ambient results at targets,
|
|
166
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
167
166
|
wake_delta: numpy.ndarray
|
|
168
167
|
The wake deltas at targets, shape:
|
|
169
168
|
(n_states, n_targets, n_tpoints)
|
|
@@ -176,6 +175,7 @@ class WSMax(WakeSuperposition):
|
|
|
176
175
|
(n_states, n_targets, n_tpoints)
|
|
177
176
|
|
|
178
177
|
"""
|
|
178
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
179
179
|
w = -wake_delta
|
|
180
180
|
if self.lim_low is not None:
|
|
181
181
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -302,8 +302,8 @@ class WSMaxLocal(WakeSuperposition):
|
|
|
302
302
|
algo,
|
|
303
303
|
mdata,
|
|
304
304
|
fdata,
|
|
305
|
+
tdata,
|
|
305
306
|
variable,
|
|
306
|
-
amb_results,
|
|
307
307
|
wake_delta,
|
|
308
308
|
):
|
|
309
309
|
"""
|
|
@@ -318,11 +318,10 @@ class WSMaxLocal(WakeSuperposition):
|
|
|
318
318
|
The model data
|
|
319
319
|
fdata: foxes.core.FData
|
|
320
320
|
The farm data
|
|
321
|
+
tdata: foxes.core.TData
|
|
322
|
+
The target point data
|
|
321
323
|
variable: str
|
|
322
324
|
The variable name for which the wake deltas applies
|
|
323
|
-
amb_results: numpy.ndarray
|
|
324
|
-
The ambient results at targets,
|
|
325
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
326
325
|
wake_delta: numpy.ndarray
|
|
327
326
|
The wake deltas at targets, shape:
|
|
328
327
|
(n_states, n_targets, n_tpoints)
|
|
@@ -335,6 +334,7 @@ class WSMaxLocal(WakeSuperposition):
|
|
|
335
334
|
(n_states, n_targets, n_tpoints)
|
|
336
335
|
|
|
337
336
|
"""
|
|
337
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
338
338
|
w = -wake_delta * amb_results
|
|
339
339
|
if self.lim_low is not None:
|
|
340
340
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -145,8 +145,8 @@ class WSPow(WakeSuperposition):
|
|
|
145
145
|
algo,
|
|
146
146
|
mdata,
|
|
147
147
|
fdata,
|
|
148
|
+
tdata,
|
|
148
149
|
variable,
|
|
149
|
-
amb_results,
|
|
150
150
|
wake_delta,
|
|
151
151
|
):
|
|
152
152
|
"""
|
|
@@ -161,11 +161,10 @@ class WSPow(WakeSuperposition):
|
|
|
161
161
|
The model data
|
|
162
162
|
fdata: foxes.core.FData
|
|
163
163
|
The farm data
|
|
164
|
+
tdata: foxes.core.TData
|
|
165
|
+
The target point data
|
|
164
166
|
variable: str
|
|
165
167
|
The variable name for which the wake deltas applies
|
|
166
|
-
amb_results: numpy.ndarray
|
|
167
|
-
The ambient results at targets,
|
|
168
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
169
168
|
wake_delta: numpy.ndarray
|
|
170
169
|
The wake deltas at targets, shape:
|
|
171
170
|
(n_states, n_targets, n_tpoints)
|
|
@@ -178,6 +177,7 @@ class WSPow(WakeSuperposition):
|
|
|
178
177
|
(n_states, n_targets, n_tpoints)
|
|
179
178
|
|
|
180
179
|
"""
|
|
180
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
181
181
|
w = -(wake_delta ** (1 / self.pow))
|
|
182
182
|
if self.lim_low is not None:
|
|
183
183
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -307,8 +307,8 @@ class WSPowLocal(WakeSuperposition):
|
|
|
307
307
|
algo,
|
|
308
308
|
mdata,
|
|
309
309
|
fdata,
|
|
310
|
+
tdata,
|
|
310
311
|
variable,
|
|
311
|
-
amb_results,
|
|
312
312
|
wake_delta,
|
|
313
313
|
):
|
|
314
314
|
"""
|
|
@@ -323,11 +323,10 @@ class WSPowLocal(WakeSuperposition):
|
|
|
323
323
|
The model data
|
|
324
324
|
fdata: foxes.core.FData
|
|
325
325
|
The farm data
|
|
326
|
+
tdata: foxes.core.TData
|
|
327
|
+
The target point data
|
|
326
328
|
variable: str
|
|
327
329
|
The variable name for which the wake deltas applies
|
|
328
|
-
amb_results: numpy.ndarray
|
|
329
|
-
The ambient results at targets,
|
|
330
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
331
330
|
wake_delta: numpy.ndarray
|
|
332
331
|
The wake deltas at targets, shape:
|
|
333
332
|
(n_states, n_targets, n_tpoints)
|
|
@@ -340,6 +339,7 @@ class WSPowLocal(WakeSuperposition):
|
|
|
340
339
|
(n_states, n_targets, n_tpoints)
|
|
341
340
|
|
|
342
341
|
"""
|
|
342
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
343
343
|
w = -(wake_delta ** (1 / self.pow)) * amb_results
|
|
344
344
|
if self.lim_low is not None:
|
|
345
345
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -131,8 +131,8 @@ class WSProduct(WakeSuperposition):
|
|
|
131
131
|
algo,
|
|
132
132
|
mdata,
|
|
133
133
|
fdata,
|
|
134
|
+
tdata,
|
|
134
135
|
variable,
|
|
135
|
-
amb_results,
|
|
136
136
|
wake_delta,
|
|
137
137
|
):
|
|
138
138
|
"""
|
|
@@ -147,11 +147,10 @@ class WSProduct(WakeSuperposition):
|
|
|
147
147
|
The model data
|
|
148
148
|
fdata: foxes.core.FData
|
|
149
149
|
The farm data
|
|
150
|
+
tdata: foxes.core.TData
|
|
151
|
+
The target point data
|
|
150
152
|
variable: str
|
|
151
153
|
The variable name for which the wake deltas applies
|
|
152
|
-
amb_results: numpy.ndarray
|
|
153
|
-
The ambient results at targets,
|
|
154
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
155
154
|
wake_delta: numpy.ndarray
|
|
156
155
|
The wake deltas at targets, shape:
|
|
157
156
|
(n_states, n_targets, n_tpoints)
|
|
@@ -164,6 +163,7 @@ class WSProduct(WakeSuperposition):
|
|
|
164
163
|
(n_states, n_targets, n_tpoints)
|
|
165
164
|
|
|
166
165
|
"""
|
|
166
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
167
167
|
w = amb_results * (wake_delta - 1)
|
|
168
168
|
if self.lim_low is not None:
|
|
169
169
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -140,8 +140,8 @@ class WSQuadratic(WakeSuperposition):
|
|
|
140
140
|
algo,
|
|
141
141
|
mdata,
|
|
142
142
|
fdata,
|
|
143
|
+
tdata,
|
|
143
144
|
variable,
|
|
144
|
-
amb_results,
|
|
145
145
|
wake_delta,
|
|
146
146
|
):
|
|
147
147
|
"""
|
|
@@ -156,11 +156,10 @@ class WSQuadratic(WakeSuperposition):
|
|
|
156
156
|
The model data
|
|
157
157
|
fdata: foxes.core.FData
|
|
158
158
|
The farm data
|
|
159
|
+
tdata: foxes.core.TData
|
|
160
|
+
The target point data
|
|
159
161
|
variable: str
|
|
160
162
|
The variable name for which the wake deltas applies
|
|
161
|
-
amb_results: numpy.ndarray
|
|
162
|
-
The ambient results at targets,
|
|
163
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
164
163
|
wake_delta: numpy.ndarray
|
|
165
164
|
The wake deltas at targets, shape:
|
|
166
165
|
(n_states, n_targets, n_tpoints)
|
|
@@ -173,6 +172,7 @@ class WSQuadratic(WakeSuperposition):
|
|
|
173
172
|
(n_states, n_targets, n_tpoints)
|
|
174
173
|
|
|
175
174
|
"""
|
|
175
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
176
176
|
w = -np.sqrt(wake_delta)
|
|
177
177
|
if self.lim_low is not None:
|
|
178
178
|
w = np.maximum(w, self.lim_low - amb_results)
|
|
@@ -296,8 +296,8 @@ class WSQuadraticLocal(WakeSuperposition):
|
|
|
296
296
|
algo,
|
|
297
297
|
mdata,
|
|
298
298
|
fdata,
|
|
299
|
+
tdata,
|
|
299
300
|
variable,
|
|
300
|
-
amb_results,
|
|
301
301
|
wake_delta,
|
|
302
302
|
):
|
|
303
303
|
"""
|
|
@@ -312,11 +312,10 @@ class WSQuadraticLocal(WakeSuperposition):
|
|
|
312
312
|
The model data
|
|
313
313
|
fdata: foxes.core.FData
|
|
314
314
|
The farm data
|
|
315
|
+
tdata: foxes.core.TData
|
|
316
|
+
The target point data
|
|
315
317
|
variable: str
|
|
316
318
|
The variable name for which the wake deltas applies
|
|
317
|
-
amb_results: numpy.ndarray
|
|
318
|
-
The ambient results at targets,
|
|
319
|
-
shape: (n_states, n_targets, n_tpoints)
|
|
320
319
|
wake_delta: numpy.ndarray
|
|
321
320
|
The wake deltas at targets, shape:
|
|
322
321
|
(n_states, n_targets, n_tpoints)
|
|
@@ -329,6 +328,7 @@ class WSQuadraticLocal(WakeSuperposition):
|
|
|
329
328
|
(n_states, n_targets, n_tpoints)
|
|
330
329
|
|
|
331
330
|
"""
|
|
331
|
+
amb_results = tdata[FV.var2amb[variable]]
|
|
332
332
|
w = -np.sqrt(wake_delta) * amb_results
|
|
333
333
|
if self.lim_low is not None:
|
|
334
334
|
w = np.maximum(w, self.lim_low - amb_results)
|