foxes 0.5.0.2__py3-none-any.whl → 0.5.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of foxes might be problematic. Click here for more details.
- foxes/VERSION +1 -1
- foxes/algorithms/downwind/downwind.py +41 -46
- foxes/algorithms/downwind/models/point_wakes_calc.py +4 -9
- foxes/algorithms/downwind/models/set_amb_point_results.py +5 -22
- foxes/core/algorithm.py +1 -1
- foxes/core/data_calc_model.py +26 -2
- foxes/core/partial_wakes_model.py +1 -1
- foxes/core/rotor_model.py +36 -2
- foxes/core/turbine_model.py +36 -0
- foxes/core/turbine_type.py +35 -1
- foxes/core/wake_frame.py +39 -3
- foxes/core/wake_model.py +36 -0
- foxes/models/model_book.py +129 -89
- foxes/models/turbine_models/rotor_centre_calc.py +1 -2
- foxes/models/turbine_types/CpCt_file.py +13 -3
- foxes/models/turbine_types/CpCt_from_two.py +14 -4
- foxes/models/vertical_profiles/abl_log_neutral_ws.py +32 -5
- foxes/models/vertical_profiles/abl_log_stable_ws.py +32 -4
- foxes/models/vertical_profiles/abl_log_unstable_ws.py +32 -4
- foxes/models/vertical_profiles/abl_log_ws.py +50 -18
- foxes/models/wake_frames/yawed_wakes.py +15 -9
- foxes/models/wake_models/induction/__init__.py +1 -1
- foxes/models/wake_models/induction/rankine_half_body.py +33 -7
- foxes/models/wake_models/ti/crespo_hernandez.py +6 -1
- foxes/models/wake_models/ti/iec_ti.py +5 -3
- foxes/models/wake_models/wind/__init__.py +2 -2
- foxes/models/wake_models/wind/{bastankhah.py → bastankhah14.py} +11 -14
- foxes/models/wake_models/wind/{porte_agel.py → bastankhah16.py} +24 -16
- foxes/models/wake_models/wind/turbopark.py +11 -22
- foxes/models/wake_superpositions/__init__.py +9 -5
- foxes/models/wake_superpositions/ti_linear.py +134 -0
- foxes/models/wake_superpositions/ti_max.py +134 -0
- foxes/models/wake_superpositions/{ti_superp.py → ti_pow.py} +15 -57
- foxes/models/wake_superpositions/ti_quadratic.py +134 -0
- foxes/models/wake_superpositions/ws_linear.py +170 -0
- foxes/models/wake_superpositions/ws_max.py +173 -0
- foxes/models/wake_superpositions/ws_pow.py +175 -0
- foxes/models/wake_superpositions/{product.py → ws_product.py} +43 -22
- foxes/models/wake_superpositions/ws_quadratic.py +170 -0
- foxes/output/__init__.py +4 -0
- foxes/output/calc_points.py +143 -0
- foxes/output/flow_plots_2d/__init__.py +1 -0
- foxes/output/flow_plots_2d/common.py +104 -1
- foxes/output/flow_plots_2d/flow_plots.py +237 -569
- foxes/output/flow_plots_2d/get_fig.py +183 -0
- foxes/output/flow_plots_2d/seq_flow_ani_plugin.py +0 -1
- foxes/output/grids.py +705 -0
- foxes/output/output.py +58 -11
- foxes/output/results_writer.py +101 -17
- foxes/output/round.py +10 -0
- foxes/output/slice_data.py +900 -0
- foxes/utils/__init__.py +5 -3
- foxes/utils/exec_python.py +56 -0
- foxes/utils/geopandas_utils.py +294 -0
- foxes/utils/pandas_utils.py +175 -0
- foxes/utils/plotly_utils.py +19 -0
- foxes/utils/xarray_utils.py +38 -0
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/METADATA +1 -1
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/RECORD +63 -49
- foxes/models/wake_superpositions/linear.py +0 -242
- foxes/models/wake_superpositions/max.py +0 -258
- foxes/models/wake_superpositions/quadratic.py +0 -252
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/LICENSE +0 -0
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/WHEEL +0 -0
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/top_level.txt +0 -0
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/zip-safe +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from foxes.core import WakeSuperposition
|
|
4
|
+
import foxes.variables as FV
|
|
5
|
+
|
|
6
|
+
class TILinear(WakeSuperposition):
|
|
7
|
+
"""
|
|
8
|
+
Linear wake superposition for TI.
|
|
9
|
+
|
|
10
|
+
Attributes
|
|
11
|
+
----------
|
|
12
|
+
superp_to_amb: str
|
|
13
|
+
The method for combining ambient with wake deltas:
|
|
14
|
+
linear or quadratic
|
|
15
|
+
|
|
16
|
+
:group: models.wake_superpositions
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, superp_to_amb="quadratic"):
|
|
21
|
+
"""
|
|
22
|
+
Constructor.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
superp_to_amb: str
|
|
27
|
+
The method for combining ambient with wake deltas:
|
|
28
|
+
linear or quadratic
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
super().__init__()
|
|
32
|
+
self.superp_to_amb = superp_to_amb
|
|
33
|
+
|
|
34
|
+
def calc_wakes_plus_wake(
|
|
35
|
+
self,
|
|
36
|
+
algo,
|
|
37
|
+
mdata,
|
|
38
|
+
fdata,
|
|
39
|
+
pdata,
|
|
40
|
+
states_source_turbine,
|
|
41
|
+
sel_sp,
|
|
42
|
+
variable,
|
|
43
|
+
wake_delta,
|
|
44
|
+
wake_model_result,
|
|
45
|
+
):
|
|
46
|
+
"""
|
|
47
|
+
Add a wake delta to previous wake deltas.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
algo: foxes.core.Algorithm
|
|
52
|
+
The calculation algorithm
|
|
53
|
+
mdata: foxes.core.Data
|
|
54
|
+
The model data
|
|
55
|
+
fdata: foxes.core.Data
|
|
56
|
+
The farm data
|
|
57
|
+
pdata: foxes.core.Data
|
|
58
|
+
The evaluation point data
|
|
59
|
+
states_source_turbine: numpy.ndarray
|
|
60
|
+
For each state, one turbine index for the
|
|
61
|
+
wake causing turbine. Shape: (n_states,)
|
|
62
|
+
sel_sp: numpy.ndarray of bool
|
|
63
|
+
The selection of points, shape: (n_states, n_points)
|
|
64
|
+
variable: str
|
|
65
|
+
The variable name for which the wake deltas applies
|
|
66
|
+
wake_delta: numpy.ndarray
|
|
67
|
+
The original wake deltas, shape: (n_states, n_points)
|
|
68
|
+
wake_model_result: numpy.ndarray
|
|
69
|
+
The new wake deltas of the selected points,
|
|
70
|
+
shape: (n_sel_sp,)
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
wdelta: numpy.ndarray
|
|
75
|
+
The updated wake deltas, shape: (n_states, n_points)
|
|
76
|
+
|
|
77
|
+
"""
|
|
78
|
+
if variable != FV.TI:
|
|
79
|
+
raise ValueError(f"Superposition '{self.name}': Expecting wake variable {FV.TI}, got {variable}")
|
|
80
|
+
|
|
81
|
+
wake_delta[sel_sp] += wake_model_result
|
|
82
|
+
return wake_delta
|
|
83
|
+
|
|
84
|
+
def calc_final_wake_delta(
|
|
85
|
+
self,
|
|
86
|
+
algo,
|
|
87
|
+
mdata,
|
|
88
|
+
fdata,
|
|
89
|
+
pdata,
|
|
90
|
+
variable,
|
|
91
|
+
amb_results,
|
|
92
|
+
wake_delta,
|
|
93
|
+
):
|
|
94
|
+
"""
|
|
95
|
+
Calculate the final wake delta after adding all
|
|
96
|
+
contributions.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
algo: foxes.core.Algorithm
|
|
101
|
+
The calculation algorithm
|
|
102
|
+
mdata: foxes.core.Data
|
|
103
|
+
The model data
|
|
104
|
+
fdata: foxes.core.Data
|
|
105
|
+
The farm data
|
|
106
|
+
pdata: foxes.core.Data
|
|
107
|
+
The evaluation point data
|
|
108
|
+
variable: str
|
|
109
|
+
The variable name for which the wake deltas applies
|
|
110
|
+
amb_results: numpy.ndarray
|
|
111
|
+
The ambient results, shape: (n_states, n_points)
|
|
112
|
+
wake_delta: numpy.ndarray
|
|
113
|
+
The wake deltas, shape: (n_states, n_points)
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
final_wake_delta: numpy.ndarray
|
|
118
|
+
The final wake delta, which will be added to the ambient
|
|
119
|
+
results by simple plus operation. Shape: (n_states, n_points)
|
|
120
|
+
|
|
121
|
+
"""
|
|
122
|
+
# linear superposition to ambient:
|
|
123
|
+
if self.superp_to_amb == "linear":
|
|
124
|
+
return wake_delta
|
|
125
|
+
|
|
126
|
+
# quadratic superposition to ambient:
|
|
127
|
+
elif self.superp_to_amb == "quadratic":
|
|
128
|
+
return np.sqrt(wake_delta**2 + amb_results**2) - amb_results
|
|
129
|
+
|
|
130
|
+
# unknown ti delta:
|
|
131
|
+
else:
|
|
132
|
+
raise ValueError(
|
|
133
|
+
f"Unknown superp_to_amb = '{self.superp_to_amb}', valid choices: linear, quadratic"
|
|
134
|
+
)
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from foxes.core import WakeSuperposition
|
|
4
|
+
import foxes.variables as FV
|
|
5
|
+
|
|
6
|
+
class TIMax(WakeSuperposition):
|
|
7
|
+
"""
|
|
8
|
+
Max wake superposition for TI.
|
|
9
|
+
|
|
10
|
+
Attributes
|
|
11
|
+
----------
|
|
12
|
+
superp_to_amb: str
|
|
13
|
+
The method for combining ambient with wake deltas:
|
|
14
|
+
linear or quadratic
|
|
15
|
+
|
|
16
|
+
:group: models.wake_superpositions
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, superp_to_amb="quadratic"):
|
|
21
|
+
"""
|
|
22
|
+
Constructor.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
superp_to_amb: str
|
|
27
|
+
The method for combining ambient with wake deltas:
|
|
28
|
+
linear or quadratic
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
super().__init__()
|
|
32
|
+
self.superp_to_amb = superp_to_amb
|
|
33
|
+
|
|
34
|
+
def calc_wakes_plus_wake(
|
|
35
|
+
self,
|
|
36
|
+
algo,
|
|
37
|
+
mdata,
|
|
38
|
+
fdata,
|
|
39
|
+
pdata,
|
|
40
|
+
states_source_turbine,
|
|
41
|
+
sel_sp,
|
|
42
|
+
variable,
|
|
43
|
+
wake_delta,
|
|
44
|
+
wake_model_result,
|
|
45
|
+
):
|
|
46
|
+
"""
|
|
47
|
+
Add a wake delta to previous wake deltas.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
algo: foxes.core.Algorithm
|
|
52
|
+
The calculation algorithm
|
|
53
|
+
mdata: foxes.core.Data
|
|
54
|
+
The model data
|
|
55
|
+
fdata: foxes.core.Data
|
|
56
|
+
The farm data
|
|
57
|
+
pdata: foxes.core.Data
|
|
58
|
+
The evaluation point data
|
|
59
|
+
states_source_turbine: numpy.ndarray
|
|
60
|
+
For each state, one turbine index for the
|
|
61
|
+
wake causing turbine. Shape: (n_states,)
|
|
62
|
+
sel_sp: numpy.ndarray of bool
|
|
63
|
+
The selection of points, shape: (n_states, n_points)
|
|
64
|
+
variable: str
|
|
65
|
+
The variable name for which the wake deltas applies
|
|
66
|
+
wake_delta: numpy.ndarray
|
|
67
|
+
The original wake deltas, shape: (n_states, n_points)
|
|
68
|
+
wake_model_result: numpy.ndarray
|
|
69
|
+
The new wake deltas of the selected points,
|
|
70
|
+
shape: (n_sel_sp,)
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
wdelta: numpy.ndarray
|
|
75
|
+
The updated wake deltas, shape: (n_states, n_points)
|
|
76
|
+
|
|
77
|
+
"""
|
|
78
|
+
if variable != FV.TI:
|
|
79
|
+
raise ValueError(f"Superposition '{self.name}': Expecting wake variable {FV.TI}, got {variable}")
|
|
80
|
+
|
|
81
|
+
wake_delta[sel_sp] = np.maximum(wake_model_result, wake_delta[sel_sp])
|
|
82
|
+
return wake_delta
|
|
83
|
+
|
|
84
|
+
def calc_final_wake_delta(
|
|
85
|
+
self,
|
|
86
|
+
algo,
|
|
87
|
+
mdata,
|
|
88
|
+
fdata,
|
|
89
|
+
pdata,
|
|
90
|
+
variable,
|
|
91
|
+
amb_results,
|
|
92
|
+
wake_delta,
|
|
93
|
+
):
|
|
94
|
+
"""
|
|
95
|
+
Calculate the final wake delta after adding all
|
|
96
|
+
contributions.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
algo: foxes.core.Algorithm
|
|
101
|
+
The calculation algorithm
|
|
102
|
+
mdata: foxes.core.Data
|
|
103
|
+
The model data
|
|
104
|
+
fdata: foxes.core.Data
|
|
105
|
+
The farm data
|
|
106
|
+
pdata: foxes.core.Data
|
|
107
|
+
The evaluation point data
|
|
108
|
+
variable: str
|
|
109
|
+
The variable name for which the wake deltas applies
|
|
110
|
+
amb_results: numpy.ndarray
|
|
111
|
+
The ambient results, shape: (n_states, n_points)
|
|
112
|
+
wake_delta: numpy.ndarray
|
|
113
|
+
The wake deltas, shape: (n_states, n_points)
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
final_wake_delta: numpy.ndarray
|
|
118
|
+
The final wake delta, which will be added to the ambient
|
|
119
|
+
results by simple plus operation. Shape: (n_states, n_points)
|
|
120
|
+
|
|
121
|
+
"""
|
|
122
|
+
# linear superposition to ambient:
|
|
123
|
+
if self.superp_to_amb == "linear":
|
|
124
|
+
return wake_delta
|
|
125
|
+
|
|
126
|
+
# quadratic superposition to ambient:
|
|
127
|
+
elif self.superp_to_amb == "quadratic":
|
|
128
|
+
return np.sqrt(wake_delta**2 + amb_results**2) - amb_results
|
|
129
|
+
|
|
130
|
+
# unknown ti delta:
|
|
131
|
+
else:
|
|
132
|
+
raise ValueError(
|
|
133
|
+
f"Unknown superp_to_amb = '{self.superp_to_amb}', valid choices: linear, quadratic"
|
|
134
|
+
)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import numpy as np
|
|
2
2
|
|
|
3
3
|
from foxes.core import WakeSuperposition
|
|
4
|
+
import foxes.variables as FV
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
class TISuperposition(WakeSuperposition):
|
|
6
|
+
class TIPow(WakeSuperposition):
|
|
7
7
|
"""
|
|
8
|
-
|
|
8
|
+
Power wake superposition for TI.
|
|
9
9
|
|
|
10
10
|
Attributes
|
|
11
11
|
----------
|
|
12
|
-
|
|
13
|
-
The
|
|
12
|
+
pow: float
|
|
13
|
+
The power to which to take the wake results
|
|
14
14
|
superp_to_amb: str
|
|
15
15
|
The method for combining ambient with wake deltas:
|
|
16
16
|
linear or quadratic
|
|
@@ -19,22 +19,21 @@ class TISuperposition(WakeSuperposition):
|
|
|
19
19
|
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
def __init__(self,
|
|
22
|
+
def __init__(self, pow, superp_to_amb="quadratic"):
|
|
23
23
|
"""
|
|
24
24
|
Constructor.
|
|
25
25
|
|
|
26
26
|
Parameters
|
|
27
27
|
----------
|
|
28
|
-
|
|
29
|
-
The
|
|
28
|
+
pow: float
|
|
29
|
+
The power to which to take the wake results
|
|
30
30
|
superp_to_amb: str
|
|
31
31
|
The method for combining ambient with wake deltas:
|
|
32
32
|
linear or quadratic
|
|
33
33
|
|
|
34
34
|
"""
|
|
35
35
|
super().__init__()
|
|
36
|
-
|
|
37
|
-
self.ti_superp = ti_superp
|
|
36
|
+
self.pow = pow
|
|
38
37
|
self.superp_to_amb = superp_to_amb
|
|
39
38
|
|
|
40
39
|
def calc_wakes_plus_wake(
|
|
@@ -81,31 +80,10 @@ class TISuperposition(WakeSuperposition):
|
|
|
81
80
|
The updated wake deltas, shape: (n_states, n_points)
|
|
82
81
|
|
|
83
82
|
"""
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
wake_delta[sel_sp] += wake_model_result
|
|
89
|
-
|
|
90
|
-
# quadratic ti delta:
|
|
91
|
-
elif self.ti_superp == "quadratic":
|
|
92
|
-
wake_delta[sel_sp] += wake_model_result**2
|
|
93
|
-
|
|
94
|
-
# power_N delta:
|
|
95
|
-
elif len(self.ti_superp) > 6 and self.ti_superp[:6] == "power_":
|
|
96
|
-
N = int(self.ti_superp[6:])
|
|
97
|
-
wake_delta[sel_sp] += wake_model_result**N
|
|
98
|
-
|
|
99
|
-
# max ti delta:
|
|
100
|
-
elif self.ti_superp == "max":
|
|
101
|
-
wake_delta[sel_sp] = np.maximum(wake_model_result, wake_delta[sel_sp])
|
|
102
|
-
|
|
103
|
-
# unknown ti delta:
|
|
104
|
-
else:
|
|
105
|
-
raise ValueError(
|
|
106
|
-
f"Unknown ti_superp = '{self.ti_superp}', valid choices: linear, quadratic, power_N, max"
|
|
107
|
-
)
|
|
108
|
-
|
|
83
|
+
if variable != FV.TI:
|
|
84
|
+
raise ValueError(f"Superposition '{self.name}': Expecting wake variable {FV.TI}, got {variable}")
|
|
85
|
+
|
|
86
|
+
wake_delta[sel_sp] += wake_model_result**self.pow
|
|
109
87
|
return wake_delta
|
|
110
88
|
|
|
111
89
|
def calc_final_wake_delta(
|
|
@@ -148,31 +126,11 @@ class TISuperposition(WakeSuperposition):
|
|
|
148
126
|
"""
|
|
149
127
|
# linear superposition to ambient:
|
|
150
128
|
if self.superp_to_amb == "linear":
|
|
151
|
-
|
|
152
|
-
return wake_delta
|
|
153
|
-
elif self.ti_superp == "quadratic":
|
|
154
|
-
return np.sqrt(wake_delta)
|
|
155
|
-
elif len(self.ti_superp) > 6 and self.ti_superp[:6] == "power_":
|
|
156
|
-
N = int(self.ti_superp[6:])
|
|
157
|
-
return wake_delta ** (1 / N)
|
|
158
|
-
else:
|
|
159
|
-
raise ValueError(
|
|
160
|
-
f"Unknown ti_superp = '{self.ti_superp}', valid choices: linear, quadratic, power_N, max"
|
|
161
|
-
)
|
|
129
|
+
return wake_delta ** (1/self.pow)
|
|
162
130
|
|
|
163
131
|
# quadratic superposition to ambient:
|
|
164
132
|
elif self.superp_to_amb == "quadratic":
|
|
165
|
-
|
|
166
|
-
return np.sqrt(wake_delta**2 + amb_results**2) - amb_results
|
|
167
|
-
elif self.ti_superp == "quadratic":
|
|
168
|
-
return np.sqrt(wake_delta + amb_results**2) - amb_results
|
|
169
|
-
elif len(self.ti_superp) > 6 and self.ti_superp[:6] == "power_":
|
|
170
|
-
N = int(self.ti_superp[6:])
|
|
171
|
-
return np.sqrt(wake_delta ** (2 / N) + amb_results**2) - amb_results
|
|
172
|
-
else:
|
|
173
|
-
raise ValueError(
|
|
174
|
-
f"Unknown ti_superp = '{self.ti_superp}', valid choices: linear, quadratic, power_N, max"
|
|
175
|
-
)
|
|
133
|
+
return np.sqrt(wake_delta **(2/self.pow) + amb_results**2) - amb_results
|
|
176
134
|
|
|
177
135
|
# unknown ti delta:
|
|
178
136
|
else:
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from foxes.core import WakeSuperposition
|
|
4
|
+
import foxes.variables as FV
|
|
5
|
+
|
|
6
|
+
class TIQuadratic(WakeSuperposition):
|
|
7
|
+
"""
|
|
8
|
+
Quadratic wake superposition for TI.
|
|
9
|
+
|
|
10
|
+
Attributes
|
|
11
|
+
----------
|
|
12
|
+
superp_to_amb: str
|
|
13
|
+
The method for combining ambient with wake deltas:
|
|
14
|
+
linear or quadratic
|
|
15
|
+
|
|
16
|
+
:group: models.wake_superpositions
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, superp_to_amb="quadratic"):
|
|
21
|
+
"""
|
|
22
|
+
Constructor.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
superp_to_amb: str
|
|
27
|
+
The method for combining ambient with wake deltas:
|
|
28
|
+
linear or quadratic
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
super().__init__()
|
|
32
|
+
self.superp_to_amb = superp_to_amb
|
|
33
|
+
|
|
34
|
+
def calc_wakes_plus_wake(
|
|
35
|
+
self,
|
|
36
|
+
algo,
|
|
37
|
+
mdata,
|
|
38
|
+
fdata,
|
|
39
|
+
pdata,
|
|
40
|
+
states_source_turbine,
|
|
41
|
+
sel_sp,
|
|
42
|
+
variable,
|
|
43
|
+
wake_delta,
|
|
44
|
+
wake_model_result,
|
|
45
|
+
):
|
|
46
|
+
"""
|
|
47
|
+
Add a wake delta to previous wake deltas.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
algo: foxes.core.Algorithm
|
|
52
|
+
The calculation algorithm
|
|
53
|
+
mdata: foxes.core.Data
|
|
54
|
+
The model data
|
|
55
|
+
fdata: foxes.core.Data
|
|
56
|
+
The farm data
|
|
57
|
+
pdata: foxes.core.Data
|
|
58
|
+
The evaluation point data
|
|
59
|
+
states_source_turbine: numpy.ndarray
|
|
60
|
+
For each state, one turbine index for the
|
|
61
|
+
wake causing turbine. Shape: (n_states,)
|
|
62
|
+
sel_sp: numpy.ndarray of bool
|
|
63
|
+
The selection of points, shape: (n_states, n_points)
|
|
64
|
+
variable: str
|
|
65
|
+
The variable name for which the wake deltas applies
|
|
66
|
+
wake_delta: numpy.ndarray
|
|
67
|
+
The original wake deltas, shape: (n_states, n_points)
|
|
68
|
+
wake_model_result: numpy.ndarray
|
|
69
|
+
The new wake deltas of the selected points,
|
|
70
|
+
shape: (n_sel_sp,)
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
wdelta: numpy.ndarray
|
|
75
|
+
The updated wake deltas, shape: (n_states, n_points)
|
|
76
|
+
|
|
77
|
+
"""
|
|
78
|
+
if variable != FV.TI:
|
|
79
|
+
raise ValueError(f"Superposition '{self.name}': Expecting wake variable {FV.TI}, got {variable}")
|
|
80
|
+
|
|
81
|
+
wake_delta[sel_sp] += wake_model_result**2
|
|
82
|
+
return wake_delta
|
|
83
|
+
|
|
84
|
+
def calc_final_wake_delta(
|
|
85
|
+
self,
|
|
86
|
+
algo,
|
|
87
|
+
mdata,
|
|
88
|
+
fdata,
|
|
89
|
+
pdata,
|
|
90
|
+
variable,
|
|
91
|
+
amb_results,
|
|
92
|
+
wake_delta,
|
|
93
|
+
):
|
|
94
|
+
"""
|
|
95
|
+
Calculate the final wake delta after adding all
|
|
96
|
+
contributions.
|
|
97
|
+
|
|
98
|
+
Parameters
|
|
99
|
+
----------
|
|
100
|
+
algo: foxes.core.Algorithm
|
|
101
|
+
The calculation algorithm
|
|
102
|
+
mdata: foxes.core.Data
|
|
103
|
+
The model data
|
|
104
|
+
fdata: foxes.core.Data
|
|
105
|
+
The farm data
|
|
106
|
+
pdata: foxes.core.Data
|
|
107
|
+
The evaluation point data
|
|
108
|
+
variable: str
|
|
109
|
+
The variable name for which the wake deltas applies
|
|
110
|
+
amb_results: numpy.ndarray
|
|
111
|
+
The ambient results, shape: (n_states, n_points)
|
|
112
|
+
wake_delta: numpy.ndarray
|
|
113
|
+
The wake deltas, shape: (n_states, n_points)
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
final_wake_delta: numpy.ndarray
|
|
118
|
+
The final wake delta, which will be added to the ambient
|
|
119
|
+
results by simple plus operation. Shape: (n_states, n_points)
|
|
120
|
+
|
|
121
|
+
"""
|
|
122
|
+
# linear superposition to ambient:
|
|
123
|
+
if self.superp_to_amb == "linear":
|
|
124
|
+
return np.sqrt(wake_delta)
|
|
125
|
+
|
|
126
|
+
# quadratic superposition to ambient:
|
|
127
|
+
elif self.superp_to_amb == "quadratic":
|
|
128
|
+
return np.sqrt(wake_delta + amb_results**2) - amb_results
|
|
129
|
+
|
|
130
|
+
# unknown ti delta:
|
|
131
|
+
else:
|
|
132
|
+
raise ValueError(
|
|
133
|
+
f"Unknown superp_to_amb = '{self.superp_to_amb}', valid choices: linear, quadratic"
|
|
134
|
+
)
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from foxes.core import WakeSuperposition
|
|
4
|
+
import foxes.variables as FV
|
|
5
|
+
import foxes.constants as FC
|
|
6
|
+
|
|
7
|
+
class WSLinear(WakeSuperposition):
|
|
8
|
+
"""
|
|
9
|
+
Linear supersposition of wind deficit results
|
|
10
|
+
|
|
11
|
+
Attributes
|
|
12
|
+
----------
|
|
13
|
+
scale_amb: bool
|
|
14
|
+
Flag for scaling wind deficit with ambient wind speed
|
|
15
|
+
instead of waked wind speed
|
|
16
|
+
lim_low: float
|
|
17
|
+
Lower limit of the final waked wind speed
|
|
18
|
+
lim_high: float
|
|
19
|
+
Upper limit of the final waked wind speed
|
|
20
|
+
|
|
21
|
+
:group: models.wake_superpositions
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, scale_amb=False, lim_low=None, lim_high=None):
|
|
26
|
+
"""
|
|
27
|
+
Constructor.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
scale_amb: bool
|
|
32
|
+
Flag for scaling wind deficit with ambient wind speed
|
|
33
|
+
instead of waked wind speed
|
|
34
|
+
lim_low: float
|
|
35
|
+
Lower limit of the final waked wind speed
|
|
36
|
+
lim_high: float
|
|
37
|
+
Upper limit of the final waked wind speed
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
super().__init__()
|
|
41
|
+
|
|
42
|
+
self.scale_amb = scale_amb
|
|
43
|
+
self.lim_low = lim_low
|
|
44
|
+
self.lim_high = lim_high
|
|
45
|
+
|
|
46
|
+
def input_farm_vars(self, algo):
|
|
47
|
+
"""
|
|
48
|
+
The variables which are needed for running
|
|
49
|
+
the model.
|
|
50
|
+
|
|
51
|
+
Parameters
|
|
52
|
+
----------
|
|
53
|
+
algo: foxes.core.Algorithm
|
|
54
|
+
The calculation algorithm
|
|
55
|
+
|
|
56
|
+
Returns
|
|
57
|
+
-------
|
|
58
|
+
input_vars: list of str
|
|
59
|
+
The input variable names
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
return [FV.AMB_REWS] if self.scale_amb else [FV.REWS]
|
|
63
|
+
|
|
64
|
+
def calc_wakes_plus_wake(
|
|
65
|
+
self,
|
|
66
|
+
algo,
|
|
67
|
+
mdata,
|
|
68
|
+
fdata,
|
|
69
|
+
pdata,
|
|
70
|
+
states_source_turbine,
|
|
71
|
+
sel_sp,
|
|
72
|
+
variable,
|
|
73
|
+
wake_delta,
|
|
74
|
+
wake_model_result,
|
|
75
|
+
):
|
|
76
|
+
"""
|
|
77
|
+
Add a wake delta to previous wake deltas.
|
|
78
|
+
|
|
79
|
+
Parameters
|
|
80
|
+
----------
|
|
81
|
+
algo: foxes.core.Algorithm
|
|
82
|
+
The calculation algorithm
|
|
83
|
+
mdata: foxes.core.Data
|
|
84
|
+
The model data
|
|
85
|
+
fdata: foxes.core.Data
|
|
86
|
+
The farm data
|
|
87
|
+
pdata: foxes.core.Data
|
|
88
|
+
The evaluation point data
|
|
89
|
+
states_source_turbine: numpy.ndarray
|
|
90
|
+
For each state, one turbine index for the
|
|
91
|
+
wake causing turbine. Shape: (n_states,)
|
|
92
|
+
sel_sp: numpy.ndarray of bool
|
|
93
|
+
The selection of points, shape: (n_states, n_points)
|
|
94
|
+
variable: str
|
|
95
|
+
The variable name for which the wake deltas applies
|
|
96
|
+
wake_delta: numpy.ndarray
|
|
97
|
+
The original wake deltas, shape: (n_states, n_points)
|
|
98
|
+
wake_model_result: numpy.ndarray
|
|
99
|
+
The new wake deltas of the selected points,
|
|
100
|
+
shape: (n_sel_sp,)
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
wdelta: numpy.ndarray
|
|
105
|
+
The updated wake deltas, shape: (n_states, n_points)
|
|
106
|
+
|
|
107
|
+
"""
|
|
108
|
+
if variable not in [FV.REWS, FV.REWS2, FV.REWS3, FV.WS]:
|
|
109
|
+
raise ValueError(f"Superposition '{self.name}': Expecting wind speed variable, got {variable}")
|
|
110
|
+
|
|
111
|
+
if np.any(sel_sp):
|
|
112
|
+
scale = self.get_data(
|
|
113
|
+
FV.AMB_REWS if self.scale_amb else FV.REWS,
|
|
114
|
+
FC.STATE_POINT,
|
|
115
|
+
lookup="w",
|
|
116
|
+
algo=algo,
|
|
117
|
+
fdata=fdata,
|
|
118
|
+
pdata=pdata,
|
|
119
|
+
upcast=True,
|
|
120
|
+
states_source_turbine=states_source_turbine,
|
|
121
|
+
)[sel_sp]
|
|
122
|
+
|
|
123
|
+
wake_delta[sel_sp] += scale * wake_model_result
|
|
124
|
+
|
|
125
|
+
return wake_delta
|
|
126
|
+
|
|
127
|
+
def calc_final_wake_delta(
|
|
128
|
+
self,
|
|
129
|
+
algo,
|
|
130
|
+
mdata,
|
|
131
|
+
fdata,
|
|
132
|
+
pdata,
|
|
133
|
+
variable,
|
|
134
|
+
amb_results,
|
|
135
|
+
wake_delta,
|
|
136
|
+
):
|
|
137
|
+
"""
|
|
138
|
+
Calculate the final wake delta after adding all
|
|
139
|
+
contributions.
|
|
140
|
+
|
|
141
|
+
Parameters
|
|
142
|
+
----------
|
|
143
|
+
algo: foxes.core.Algorithm
|
|
144
|
+
The calculation algorithm
|
|
145
|
+
mdata: foxes.core.Data
|
|
146
|
+
The model data
|
|
147
|
+
fdata: foxes.core.Data
|
|
148
|
+
The farm data
|
|
149
|
+
pdata: foxes.core.Data
|
|
150
|
+
The evaluation point data
|
|
151
|
+
variable: str
|
|
152
|
+
The variable name for which the wake deltas applies
|
|
153
|
+
amb_results: numpy.ndarray
|
|
154
|
+
The ambient results, shape: (n_states, n_points)
|
|
155
|
+
wake_delta: numpy.ndarray
|
|
156
|
+
The wake deltas, shape: (n_states, n_points)
|
|
157
|
+
|
|
158
|
+
Returns
|
|
159
|
+
-------
|
|
160
|
+
final_wake_delta: numpy.ndarray
|
|
161
|
+
The final wake delta, which will be added to the ambient
|
|
162
|
+
results by simple plus operation. Shape: (n_states, n_points)
|
|
163
|
+
|
|
164
|
+
"""
|
|
165
|
+
w = wake_delta
|
|
166
|
+
if self.lim_low is not None:
|
|
167
|
+
w = np.maximum(w, self.lim_low - amb_results)
|
|
168
|
+
if self.lim_high is not None:
|
|
169
|
+
w = np.minimum(w, self.lim_high - amb_results)
|
|
170
|
+
return w
|