foxes 0.5.1__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 +132 -85
- 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.1.dist-info → foxes-0.5.2.dist-info}/METADATA +1 -1
- {foxes-0.5.1.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.1.dist-info → foxes-0.5.2.dist-info}/LICENSE +0 -0
- {foxes-0.5.1.dist-info → foxes-0.5.2.dist-info}/WHEEL +0 -0
- {foxes-0.5.1.dist-info → foxes-0.5.2.dist-info}/top_level.txt +0 -0
- {foxes-0.5.1.dist-info → foxes-0.5.2.dist-info}/zip-safe +0 -0
|
@@ -0,0 +1,173 @@
|
|
|
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 WSMax(WakeSuperposition):
|
|
8
|
+
"""
|
|
9
|
+
Max 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_model_result = np.abs(scale * wake_model_result)
|
|
124
|
+
odelta = wake_delta[sel_sp]
|
|
125
|
+
|
|
126
|
+
wake_delta[sel_sp] = np.maximum(odelta, wake_model_result)
|
|
127
|
+
|
|
128
|
+
return wake_delta
|
|
129
|
+
|
|
130
|
+
def calc_final_wake_delta(
|
|
131
|
+
self,
|
|
132
|
+
algo,
|
|
133
|
+
mdata,
|
|
134
|
+
fdata,
|
|
135
|
+
pdata,
|
|
136
|
+
variable,
|
|
137
|
+
amb_results,
|
|
138
|
+
wake_delta,
|
|
139
|
+
):
|
|
140
|
+
"""
|
|
141
|
+
Calculate the final wake delta after adding all
|
|
142
|
+
contributions.
|
|
143
|
+
|
|
144
|
+
Parameters
|
|
145
|
+
----------
|
|
146
|
+
algo: foxes.core.Algorithm
|
|
147
|
+
The calculation algorithm
|
|
148
|
+
mdata: foxes.core.Data
|
|
149
|
+
The model data
|
|
150
|
+
fdata: foxes.core.Data
|
|
151
|
+
The farm data
|
|
152
|
+
pdata: foxes.core.Data
|
|
153
|
+
The evaluation point data
|
|
154
|
+
variable: str
|
|
155
|
+
The variable name for which the wake deltas applies
|
|
156
|
+
amb_results: numpy.ndarray
|
|
157
|
+
The ambient results, shape: (n_states, n_points)
|
|
158
|
+
wake_delta: numpy.ndarray
|
|
159
|
+
The wake deltas, shape: (n_states, n_points)
|
|
160
|
+
|
|
161
|
+
Returns
|
|
162
|
+
-------
|
|
163
|
+
final_wake_delta: numpy.ndarray
|
|
164
|
+
The final wake delta, which will be added to the ambient
|
|
165
|
+
results by simple plus operation. Shape: (n_states, n_points)
|
|
166
|
+
|
|
167
|
+
"""
|
|
168
|
+
w = -wake_delta
|
|
169
|
+
if self.lim_low is not None:
|
|
170
|
+
w = np.maximum(w, self.lim_low - amb_results)
|
|
171
|
+
if self.lim_high is not None:
|
|
172
|
+
w = np.minimum(w, self.lim_high - amb_results)
|
|
173
|
+
return w
|
|
@@ -0,0 +1,175 @@
|
|
|
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 WSPow(WakeSuperposition):
|
|
8
|
+
"""
|
|
9
|
+
Power supersposition of wind deficit results
|
|
10
|
+
|
|
11
|
+
Attributes
|
|
12
|
+
----------
|
|
13
|
+
pow: float
|
|
14
|
+
The power to which to take the wake results
|
|
15
|
+
scale_amb: bool
|
|
16
|
+
Flag for scaling wind deficit with ambient wind speed
|
|
17
|
+
instead of waked wind speed
|
|
18
|
+
lim_low: float
|
|
19
|
+
Lower limit of the final waked wind speed
|
|
20
|
+
lim_high: float
|
|
21
|
+
Upper limit of the final waked wind speed
|
|
22
|
+
|
|
23
|
+
:group: models.wake_superpositions
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, pow, scale_amb=False, lim_low=None, lim_high=None):
|
|
28
|
+
"""
|
|
29
|
+
Constructor.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
pow: float
|
|
34
|
+
The power to which to take the wake results
|
|
35
|
+
scale_amb: bool
|
|
36
|
+
Flag for scaling wind deficit with ambient wind speed
|
|
37
|
+
instead of waked wind speed
|
|
38
|
+
lim_low: float
|
|
39
|
+
Lower limit of the final waked wind speed
|
|
40
|
+
lim_high: float
|
|
41
|
+
Upper limit of the final waked wind speed
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
super().__init__()
|
|
45
|
+
|
|
46
|
+
self.pow = pow
|
|
47
|
+
self.scale_amb = scale_amb
|
|
48
|
+
self.lim_low = lim_low
|
|
49
|
+
self.lim_high = lim_high
|
|
50
|
+
|
|
51
|
+
def input_farm_vars(self, algo):
|
|
52
|
+
"""
|
|
53
|
+
The variables which are needed for running
|
|
54
|
+
the model.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
algo: foxes.core.Algorithm
|
|
59
|
+
The calculation algorithm
|
|
60
|
+
|
|
61
|
+
Returns
|
|
62
|
+
-------
|
|
63
|
+
input_vars: list of str
|
|
64
|
+
The input variable names
|
|
65
|
+
|
|
66
|
+
"""
|
|
67
|
+
return [FV.AMB_REWS] if self.scale_amb else [FV.REWS]
|
|
68
|
+
|
|
69
|
+
def calc_wakes_plus_wake(
|
|
70
|
+
self,
|
|
71
|
+
algo,
|
|
72
|
+
mdata,
|
|
73
|
+
fdata,
|
|
74
|
+
pdata,
|
|
75
|
+
states_source_turbine,
|
|
76
|
+
sel_sp,
|
|
77
|
+
variable,
|
|
78
|
+
wake_delta,
|
|
79
|
+
wake_model_result,
|
|
80
|
+
):
|
|
81
|
+
"""
|
|
82
|
+
Add a wake delta to previous wake deltas.
|
|
83
|
+
|
|
84
|
+
Parameters
|
|
85
|
+
----------
|
|
86
|
+
algo: foxes.core.Algorithm
|
|
87
|
+
The calculation algorithm
|
|
88
|
+
mdata: foxes.core.Data
|
|
89
|
+
The model data
|
|
90
|
+
fdata: foxes.core.Data
|
|
91
|
+
The farm data
|
|
92
|
+
pdata: foxes.core.Data
|
|
93
|
+
The evaluation point data
|
|
94
|
+
states_source_turbine: numpy.ndarray
|
|
95
|
+
For each state, one turbine index for the
|
|
96
|
+
wake causing turbine. Shape: (n_states,)
|
|
97
|
+
sel_sp: numpy.ndarray of bool
|
|
98
|
+
The selection of points, shape: (n_states, n_points)
|
|
99
|
+
variable: str
|
|
100
|
+
The variable name for which the wake deltas applies
|
|
101
|
+
wake_delta: numpy.ndarray
|
|
102
|
+
The original wake deltas, shape: (n_states, n_points)
|
|
103
|
+
wake_model_result: numpy.ndarray
|
|
104
|
+
The new wake deltas of the selected points,
|
|
105
|
+
shape: (n_sel_sp,)
|
|
106
|
+
|
|
107
|
+
Returns
|
|
108
|
+
-------
|
|
109
|
+
wdelta: numpy.ndarray
|
|
110
|
+
The updated wake deltas, shape: (n_states, n_points)
|
|
111
|
+
|
|
112
|
+
"""
|
|
113
|
+
if variable not in [FV.REWS, FV.REWS2, FV.REWS3, FV.WS]:
|
|
114
|
+
raise ValueError(f"Superposition '{self.name}': Expecting wind speed variable, got {variable}")
|
|
115
|
+
|
|
116
|
+
if np.any(sel_sp):
|
|
117
|
+
scale = self.get_data(
|
|
118
|
+
FV.AMB_REWS if self.scale_amb else FV.REWS,
|
|
119
|
+
FC.STATE_POINT,
|
|
120
|
+
lookup="w",
|
|
121
|
+
algo=algo,
|
|
122
|
+
fdata=fdata,
|
|
123
|
+
pdata=pdata,
|
|
124
|
+
upcast=True,
|
|
125
|
+
states_source_turbine=states_source_turbine,
|
|
126
|
+
)[sel_sp]
|
|
127
|
+
|
|
128
|
+
wake_delta[sel_sp] += np.abs(scale * wake_model_result)**self.pow
|
|
129
|
+
|
|
130
|
+
return wake_delta
|
|
131
|
+
|
|
132
|
+
def calc_final_wake_delta(
|
|
133
|
+
self,
|
|
134
|
+
algo,
|
|
135
|
+
mdata,
|
|
136
|
+
fdata,
|
|
137
|
+
pdata,
|
|
138
|
+
variable,
|
|
139
|
+
amb_results,
|
|
140
|
+
wake_delta,
|
|
141
|
+
):
|
|
142
|
+
"""
|
|
143
|
+
Calculate the final wake delta after adding all
|
|
144
|
+
contributions.
|
|
145
|
+
|
|
146
|
+
Parameters
|
|
147
|
+
----------
|
|
148
|
+
algo: foxes.core.Algorithm
|
|
149
|
+
The calculation algorithm
|
|
150
|
+
mdata: foxes.core.Data
|
|
151
|
+
The model data
|
|
152
|
+
fdata: foxes.core.Data
|
|
153
|
+
The farm data
|
|
154
|
+
pdata: foxes.core.Data
|
|
155
|
+
The evaluation point data
|
|
156
|
+
variable: str
|
|
157
|
+
The variable name for which the wake deltas applies
|
|
158
|
+
amb_results: numpy.ndarray
|
|
159
|
+
The ambient results, shape: (n_states, n_points)
|
|
160
|
+
wake_delta: numpy.ndarray
|
|
161
|
+
The wake deltas, shape: (n_states, n_points)
|
|
162
|
+
|
|
163
|
+
Returns
|
|
164
|
+
-------
|
|
165
|
+
final_wake_delta: numpy.ndarray
|
|
166
|
+
The final wake delta, which will be added to the ambient
|
|
167
|
+
results by simple plus operation. Shape: (n_states, n_points)
|
|
168
|
+
|
|
169
|
+
"""
|
|
170
|
+
w = -wake_delta**(1/self.pow)
|
|
171
|
+
if self.lim_low is not None:
|
|
172
|
+
w = np.maximum(w, self.lim_low - amb_results)
|
|
173
|
+
if self.lim_high is not None:
|
|
174
|
+
w = np.minimum(w, self.lim_high - amb_results)
|
|
175
|
+
return w
|
|
@@ -2,11 +2,11 @@ import numpy as np
|
|
|
2
2
|
|
|
3
3
|
from foxes.core import WakeSuperposition
|
|
4
4
|
import foxes.variables as FV
|
|
5
|
+
import foxes.constants as FC
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
class ProductSuperposition(WakeSuperposition):
|
|
7
|
+
class WSProduct(WakeSuperposition):
|
|
8
8
|
"""
|
|
9
|
-
Product wind
|
|
9
|
+
Product supersposition of wind deficit results
|
|
10
10
|
|
|
11
11
|
This is based on the idea that the dimensionless
|
|
12
12
|
wind deficit should be rescaled with the wake
|
|
@@ -18,12 +18,10 @@ class ProductSuperposition(WakeSuperposition):
|
|
|
18
18
|
|
|
19
19
|
Attributes
|
|
20
20
|
----------
|
|
21
|
-
lim_low:
|
|
22
|
-
Lower
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Higher limits of the final wake deltas. Key: variable str,
|
|
26
|
-
value: float
|
|
21
|
+
lim_low: float
|
|
22
|
+
Lower limit of the final waked wind speed
|
|
23
|
+
lim_high: float
|
|
24
|
+
Upper limit of the final waked wind speed
|
|
27
25
|
|
|
28
26
|
:group: models.wake_superpositions
|
|
29
27
|
|
|
@@ -35,18 +33,35 @@ class ProductSuperposition(WakeSuperposition):
|
|
|
35
33
|
|
|
36
34
|
Parameters
|
|
37
35
|
----------
|
|
38
|
-
lim_low:
|
|
39
|
-
Lower
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Higher limits of the final wake deltas. Key: variable str,
|
|
43
|
-
value: float
|
|
36
|
+
lim_low: float
|
|
37
|
+
Lower limit of the final waked wind speed
|
|
38
|
+
lim_high: float
|
|
39
|
+
Upper limit of the final waked wind speed
|
|
44
40
|
|
|
45
41
|
"""
|
|
46
42
|
super().__init__()
|
|
43
|
+
|
|
47
44
|
self.lim_low = lim_low
|
|
48
45
|
self.lim_high = lim_high
|
|
49
46
|
|
|
47
|
+
def input_farm_vars(self, algo):
|
|
48
|
+
"""
|
|
49
|
+
The variables which are needed for running
|
|
50
|
+
the model.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
algo: foxes.core.Algorithm
|
|
55
|
+
The calculation algorithm
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
input_vars: list of str
|
|
60
|
+
The input variable names
|
|
61
|
+
|
|
62
|
+
"""
|
|
63
|
+
return [FV.AMB_REWS] if self.scale_amb else [FV.REWS]
|
|
64
|
+
|
|
50
65
|
def calc_wakes_plus_wake(
|
|
51
66
|
self,
|
|
52
67
|
algo,
|
|
@@ -91,10 +106,16 @@ class ProductSuperposition(WakeSuperposition):
|
|
|
91
106
|
The updated wake deltas, shape: (n_states, n_points)
|
|
92
107
|
|
|
93
108
|
"""
|
|
109
|
+
if variable not in [FV.REWS, FV.REWS2, FV.REWS3, FV.WS]:
|
|
110
|
+
raise ValueError(f"Superposition '{self.name}': Expecting wind speed variable, got {variable}")
|
|
111
|
+
|
|
112
|
+
if np.any(sel_sp):
|
|
113
|
+
|
|
114
|
+
if np.max(np.abs(wake_delta)) < 1e-14:
|
|
115
|
+
wake_delta[:] = 1
|
|
116
|
+
|
|
117
|
+
wake_delta[sel_sp] *= 1 + wake_model_result
|
|
94
118
|
|
|
95
|
-
if np.max(np.abs(wake_delta)) < 1e-14:
|
|
96
|
-
wake_delta[:] = 1
|
|
97
|
-
wake_delta[sel_sp] *= 1 + wake_model_result
|
|
98
119
|
return wake_delta
|
|
99
120
|
|
|
100
121
|
def calc_final_wake_delta(
|
|
@@ -136,8 +157,8 @@ class ProductSuperposition(WakeSuperposition):
|
|
|
136
157
|
|
|
137
158
|
"""
|
|
138
159
|
w = amb_results * (wake_delta - 1)
|
|
139
|
-
if self.lim_low is not None
|
|
140
|
-
w = np.maximum(w, self.lim_low
|
|
141
|
-
if self.lim_high is not None
|
|
142
|
-
w = np.minimum(w, self.lim_high
|
|
160
|
+
if self.lim_low is not None:
|
|
161
|
+
w = np.maximum(w, self.lim_low - amb_results)
|
|
162
|
+
if self.lim_high is not None:
|
|
163
|
+
w = np.minimum(w, self.lim_high - amb_results)
|
|
143
164
|
return w
|
|
@@ -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 WSQuadratic(WakeSuperposition):
|
|
8
|
+
"""
|
|
9
|
+
Quadratic 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)**2
|
|
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 = -np.sqrt(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
|
foxes/output/__init__.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Output tools and functions.
|
|
3
3
|
"""
|
|
4
|
+
from .round import round_defaults
|
|
4
5
|
from .output import Output
|
|
5
6
|
from .farm_layout import FarmLayoutOutput
|
|
6
7
|
from .farm_results_eval import FarmResultsEval
|
|
@@ -9,5 +10,8 @@ from .results_writer import ResultsWriter
|
|
|
9
10
|
from .state_turbine_map import StateTurbineMap
|
|
10
11
|
from .turbine_type_curves import TurbineTypeCurves
|
|
11
12
|
from .animation import Animator
|
|
13
|
+
from .calc_points import PointCalculator
|
|
14
|
+
from .slice_data import SliceData
|
|
12
15
|
|
|
13
16
|
from .flow_plots_2d import FlowPlots2D, SeqFlowAnimationPlugin
|
|
17
|
+
from . import grids
|