foxes 0.6.1__py3-none-any.whl → 0.7__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 +131 -65
- foxes/algorithms/downwind/models/__init__.py +2 -1
- foxes/algorithms/downwind/models/farm_wakes_calc.py +87 -55
- foxes/algorithms/downwind/models/init_farm_data.py +134 -0
- foxes/algorithms/downwind/models/point_wakes_calc.py +54 -65
- foxes/algorithms/downwind/models/{calc_order.py → reorder_farm_output.py} +28 -26
- foxes/algorithms/iterative/iterative.py +100 -51
- foxes/algorithms/iterative/models/convergence.py +3 -3
- foxes/algorithms/iterative/models/farm_wakes_calc.py +55 -48
- foxes/algorithms/sequential/models/seq_state.py +7 -6
- foxes/algorithms/sequential/sequential.py +81 -44
- foxes/constants.py +33 -18
- foxes/core/__init__.py +2 -2
- foxes/core/algorithm.py +31 -12
- foxes/core/data.py +335 -41
- foxes/core/data_calc_model.py +27 -23
- foxes/core/farm_controller.py +27 -28
- foxes/core/farm_data_model.py +26 -4
- foxes/core/model.py +186 -129
- foxes/core/partial_wakes_model.py +84 -81
- foxes/core/point_data_model.py +51 -18
- foxes/core/rotor_model.py +59 -77
- foxes/core/states.py +6 -6
- foxes/core/turbine_model.py +4 -4
- foxes/core/turbine_type.py +24 -0
- foxes/core/vertical_profile.py +3 -3
- foxes/core/wake_frame.py +91 -50
- foxes/core/wake_model.py +74 -43
- foxes/core/wake_superposition.py +29 -26
- foxes/input/farm_layout/__init__.py +1 -0
- foxes/input/farm_layout/from_random.py +49 -0
- foxes/input/states/__init__.py +1 -1
- foxes/input/states/create/__init__.py +1 -0
- foxes/input/states/create/random_abl_states.py +6 -2
- foxes/input/states/create/random_timeseries.py +56 -0
- foxes/input/states/field_data_nc.py +12 -8
- foxes/input/states/multi_height.py +24 -14
- foxes/input/states/scan_ws.py +13 -17
- foxes/input/states/single.py +28 -20
- foxes/input/states/states_table.py +22 -18
- foxes/models/axial_induction_models/betz.py +1 -1
- foxes/models/farm_models/turbine2farm.py +2 -2
- foxes/models/model_book.py +40 -14
- foxes/models/partial_wakes/__init__.py +2 -2
- foxes/models/partial_wakes/axiwake.py +73 -200
- foxes/models/partial_wakes/centre.py +40 -0
- foxes/models/partial_wakes/grid.py +7 -63
- foxes/models/partial_wakes/rotor_points.py +53 -147
- foxes/models/partial_wakes/segregated.py +158 -0
- foxes/models/partial_wakes/top_hat.py +88 -196
- foxes/models/point_models/set_uniform_data.py +4 -4
- foxes/models/point_models/tke2ti.py +4 -4
- foxes/models/point_models/wake_deltas.py +4 -4
- foxes/models/rotor_models/centre.py +15 -19
- foxes/models/rotor_models/grid.py +2 -1
- foxes/models/rotor_models/levels.py +2 -1
- foxes/models/turbine_models/__init__.py +0 -1
- foxes/models/turbine_models/calculator.py +11 -7
- foxes/models/turbine_models/kTI_model.py +13 -11
- foxes/models/turbine_models/lookup_table.py +22 -9
- foxes/models/turbine_models/power_mask.py +81 -51
- foxes/models/turbine_models/rotor_centre_calc.py +17 -20
- foxes/models/turbine_models/sector_management.py +5 -6
- foxes/models/turbine_models/set_farm_vars.py +49 -20
- foxes/models/turbine_models/table_factors.py +5 -5
- foxes/models/turbine_models/thrust2ct.py +9 -5
- foxes/models/turbine_models/yaw2yawm.py +7 -13
- foxes/models/turbine_models/yawm2yaw.py +7 -11
- foxes/models/turbine_types/PCt_file.py +84 -3
- foxes/models/turbine_types/PCt_from_two.py +7 -3
- foxes/models/turbine_types/null_type.py +2 -2
- foxes/models/turbine_types/wsrho2PCt_from_two.py +2 -2
- foxes/models/turbine_types/wsti2PCt_from_two.py +6 -2
- foxes/models/wake_frames/farm_order.py +26 -22
- foxes/models/wake_frames/rotor_wd.py +32 -31
- foxes/models/wake_frames/seq_dynamic_wakes.py +112 -64
- foxes/models/wake_frames/streamlines.py +51 -47
- foxes/models/wake_frames/timelines.py +59 -47
- foxes/models/wake_frames/yawed_wakes.py +63 -40
- foxes/models/wake_models/axisymmetric.py +31 -35
- foxes/models/wake_models/dist_sliced.py +50 -56
- foxes/models/wake_models/gaussian.py +33 -35
- foxes/models/wake_models/induction/rankine_half_body.py +79 -87
- foxes/models/wake_models/induction/rathmann.py +56 -63
- foxes/models/wake_models/induction/self_similar.py +59 -62
- foxes/models/wake_models/ti/crespo_hernandez.py +83 -74
- foxes/models/wake_models/ti/iec_ti.py +65 -75
- foxes/models/wake_models/top_hat.py +60 -69
- foxes/models/wake_models/wake_mirror.py +49 -54
- foxes/models/wake_models/wind/bastankhah14.py +44 -66
- foxes/models/wake_models/wind/bastankhah16.py +84 -111
- foxes/models/wake_models/wind/jensen.py +67 -89
- foxes/models/wake_models/wind/turbopark.py +93 -133
- foxes/models/wake_superpositions/ti_linear.py +33 -27
- foxes/models/wake_superpositions/ti_max.py +33 -27
- foxes/models/wake_superpositions/ti_pow.py +35 -27
- foxes/models/wake_superpositions/ti_quadratic.py +33 -27
- foxes/models/wake_superpositions/ws_linear.py +39 -32
- foxes/models/wake_superpositions/ws_max.py +40 -33
- foxes/models/wake_superpositions/ws_pow.py +39 -32
- foxes/models/wake_superpositions/ws_product.py +35 -28
- foxes/models/wake_superpositions/ws_quadratic.py +39 -32
- foxes/opt/constraints/min_dist.py +1 -1
- foxes/opt/objectives/farm_vars.py +1 -1
- foxes/opt/problems/layout/farm_layout.py +38 -97
- foxes/output/__init__.py +1 -0
- foxes/output/farm_results_eval.py +1 -1
- foxes/output/flow_plots_2d/flow_plots.py +2 -0
- foxes/output/flow_plots_2d/get_fig.py +2 -0
- foxes/output/grids.py +1 -1
- foxes/output/rose_plot.py +3 -3
- foxes/output/rotor_point_plots.py +117 -0
- foxes/output/turbine_type_curves.py +2 -2
- foxes/utils/__init__.py +2 -1
- foxes/utils/load.py +29 -0
- foxes/utils/random_xy.py +56 -0
- foxes/utils/runners/runners.py +13 -1
- foxes/utils/windrose_plot.py +1 -1
- foxes/variables.py +10 -0
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/METADATA +13 -7
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/RECORD +126 -122
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/WHEEL +1 -1
- foxes/models/partial_wakes/distsliced.py +0 -322
- foxes/models/partial_wakes/mapped.py +0 -252
- foxes/models/turbine_models/set_XYHD.py +0 -130
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/LICENSE +0 -0
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/top_level.txt +0 -0
- {foxes-0.6.1.dist-info → foxes-0.7.dist-info}/zip-safe +0 -0
|
@@ -157,7 +157,7 @@ class LookupTable(TurbineModel):
|
|
|
157
157
|
return super().load_data(algo, verbosity)
|
|
158
158
|
|
|
159
159
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
160
|
-
"""
|
|
160
|
+
"""
|
|
161
161
|
The main model calculation.
|
|
162
162
|
|
|
163
163
|
This function is executed on a single chunk of data,
|
|
@@ -167,13 +167,13 @@ class LookupTable(TurbineModel):
|
|
|
167
167
|
----------
|
|
168
168
|
algo: foxes.core.Algorithm
|
|
169
169
|
The calculation algorithm
|
|
170
|
-
mdata: foxes.core.
|
|
170
|
+
mdata: foxes.core.MData
|
|
171
171
|
The model data
|
|
172
|
-
fdata: foxes.core.
|
|
172
|
+
fdata: foxes.core.FData
|
|
173
173
|
The farm data
|
|
174
|
-
st_sel: numpy.ndarray of bool
|
|
174
|
+
st_sel: slice or numpy.ndarray of bool
|
|
175
175
|
The state-turbine selection,
|
|
176
|
-
shape: (n_states, n_turbines)
|
|
176
|
+
for shape: (n_states, n_turbines)
|
|
177
177
|
|
|
178
178
|
Returns
|
|
179
179
|
-------
|
|
@@ -182,15 +182,28 @@ class LookupTable(TurbineModel):
|
|
|
182
182
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
183
183
|
|
|
184
184
|
"""
|
|
185
|
+
data = {
|
|
186
|
+
v: self.get_data(
|
|
187
|
+
self.input_vars[0],
|
|
188
|
+
FC.STATE_TURBINE,
|
|
189
|
+
lookup="fs",
|
|
190
|
+
fdata=fdata,
|
|
191
|
+
upcast=True,
|
|
192
|
+
)[st_sel]
|
|
193
|
+
for v in self.input_vars
|
|
194
|
+
}
|
|
195
|
+
dims = {
|
|
196
|
+
v: ("_z") if len(data[v].shape) == 1 else ("_z", "_u")
|
|
197
|
+
for v in self.input_vars
|
|
198
|
+
}
|
|
185
199
|
indata = {
|
|
186
200
|
v: xr.DataArray(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
)[st_sel],
|
|
190
|
-
dims=["_z"],
|
|
201
|
+
data[v],
|
|
202
|
+
dims=dims[v],
|
|
191
203
|
)
|
|
192
204
|
for v in self.input_vars
|
|
193
205
|
}
|
|
206
|
+
del data, dims
|
|
194
207
|
|
|
195
208
|
odata = self._data.interp(**indata, **self._xargs)
|
|
196
209
|
|
|
@@ -24,12 +24,16 @@ class PowerMask(TurbineModel):
|
|
|
24
24
|
The wind speed variable for power lookup
|
|
25
25
|
factor_P: float
|
|
26
26
|
The power unit factor, e.g. 1000 for kW
|
|
27
|
+
P_lim: float
|
|
28
|
+
Threshold power delta for boosts
|
|
29
|
+
induction: foxes.core.AxialInductionModel
|
|
30
|
+
The induction model
|
|
27
31
|
|
|
28
32
|
:group: models.turbine_models
|
|
29
33
|
|
|
30
34
|
"""
|
|
31
35
|
|
|
32
|
-
def __init__(self, var_ws_P=FV.REWS3, factor_P=1.0e3):
|
|
36
|
+
def __init__(self, var_ws_P=FV.REWS3, factor_P=1.0e3, P_lim=100, induction="Betz"):
|
|
33
37
|
"""
|
|
34
38
|
Constructor.
|
|
35
39
|
|
|
@@ -39,12 +43,25 @@ class PowerMask(TurbineModel):
|
|
|
39
43
|
The wind speed variable for power lookup
|
|
40
44
|
factor_P: float
|
|
41
45
|
The power unit factor, e.g. 1000 for kW
|
|
46
|
+
P_lim: float
|
|
47
|
+
Threshold power delta for boosts
|
|
48
|
+
induction: foxes.core.AxialInductionModel or str
|
|
49
|
+
The induction model
|
|
42
50
|
|
|
43
51
|
"""
|
|
44
52
|
super().__init__()
|
|
45
53
|
|
|
46
54
|
self.var_ws_P = var_ws_P
|
|
47
55
|
self.factor_P = factor_P
|
|
56
|
+
self.P_lim = P_lim
|
|
57
|
+
self.induction = induction
|
|
58
|
+
|
|
59
|
+
def __repr__(self):
|
|
60
|
+
iname = (
|
|
61
|
+
self.induction if isinstance(self.induction, str) else self.induction.name
|
|
62
|
+
)
|
|
63
|
+
a = f"var_ws_P={self.var_ws_P}, P_lim={self.P_lim}, induction={iname}"
|
|
64
|
+
return f"{type(self).__name__}({a})"
|
|
48
65
|
|
|
49
66
|
def output_farm_vars(self, algo):
|
|
50
67
|
"""
|
|
@@ -63,6 +80,18 @@ class PowerMask(TurbineModel):
|
|
|
63
80
|
"""
|
|
64
81
|
return [FV.P, FV.CT]
|
|
65
82
|
|
|
83
|
+
def sub_models(self):
|
|
84
|
+
"""
|
|
85
|
+
List of all sub-models
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
smdls: list of foxes.core.Model
|
|
90
|
+
All sub models
|
|
91
|
+
|
|
92
|
+
"""
|
|
93
|
+
return [self.induction]
|
|
94
|
+
|
|
66
95
|
def initialize(self, algo, verbosity=0):
|
|
67
96
|
"""
|
|
68
97
|
Initializes the model.
|
|
@@ -75,6 +104,8 @@ class PowerMask(TurbineModel):
|
|
|
75
104
|
The verbosity level, 0 = silent
|
|
76
105
|
|
|
77
106
|
"""
|
|
107
|
+
if isinstance(self.induction, str):
|
|
108
|
+
self.induction = algo.mbook.axial_induction[self.induction]
|
|
78
109
|
super().initialize(algo, verbosity)
|
|
79
110
|
|
|
80
111
|
self._P_rated = []
|
|
@@ -87,35 +118,68 @@ class PowerMask(TurbineModel):
|
|
|
87
118
|
self._P_rated.append(Pnom)
|
|
88
119
|
self._P_rated = np.array(self._P_rated, dtype=FC.DTYPE)
|
|
89
120
|
|
|
90
|
-
|
|
91
|
-
|
|
121
|
+
def calculate(self, algo, mdata, fdata, st_sel):
|
|
122
|
+
"""
|
|
123
|
+
The main model calculation.
|
|
124
|
+
|
|
125
|
+
This function is executed on a single chunk of data,
|
|
126
|
+
all computations should be based on numpy arrays.
|
|
127
|
+
|
|
128
|
+
Parameters
|
|
129
|
+
----------
|
|
130
|
+
algo: foxes.core.Algorithm
|
|
131
|
+
The calculation algorithm
|
|
132
|
+
mdata: foxes.core.MData
|
|
133
|
+
The model data
|
|
134
|
+
fdata: foxes.core.FData
|
|
135
|
+
The farm data
|
|
136
|
+
st_sel: slice or numpy.ndarray of bool
|
|
137
|
+
The state-turbine selection,
|
|
138
|
+
for shape: (n_states, n_turbines)
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
results: dict
|
|
143
|
+
The resulting data, keys: output variable str.
|
|
144
|
+
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
145
|
+
|
|
146
|
+
"""
|
|
147
|
+
# prepare:
|
|
148
|
+
P = fdata[FV.P]
|
|
149
|
+
max_P = fdata[FV.MAX_P]
|
|
150
|
+
P_rated = self._P_rated[None, :]
|
|
151
|
+
|
|
92
152
|
# select power entries for which this is active:
|
|
93
|
-
|
|
94
|
-
sel =
|
|
95
|
-
|
|
96
|
-
|
|
153
|
+
sel = np.zeros((fdata.n_states, fdata.n_turbines), dtype=bool)
|
|
154
|
+
sel[st_sel] = True
|
|
155
|
+
sel = (
|
|
156
|
+
sel
|
|
157
|
+
& ~np.isnan(max_P)
|
|
158
|
+
& (
|
|
159
|
+
((max_P < P_rated) & (P > max_P))
|
|
160
|
+
| ((max_P > P_rated) & (P > P_rated - self.P_lim))
|
|
161
|
+
)
|
|
97
162
|
)
|
|
98
163
|
if np.any(sel):
|
|
99
164
|
# apply selection:
|
|
100
165
|
max_P = max_P[sel]
|
|
101
|
-
ws =
|
|
102
|
-
rho =
|
|
103
|
-
r =
|
|
166
|
+
ws = fdata[self.var_ws_P][sel]
|
|
167
|
+
rho = fdata[FV.RHO][sel]
|
|
168
|
+
r = fdata[FV.D][sel] / 2
|
|
104
169
|
P = P[sel]
|
|
105
|
-
ct =
|
|
106
|
-
ct[ct > 1.0] = 1.0
|
|
170
|
+
ct = fdata[FV.CT][sel]
|
|
107
171
|
|
|
108
172
|
# calculate power efficiency e of turbine
|
|
109
173
|
# e is the ratio of the cp derived from the power curve
|
|
110
174
|
# and the theoretical cp from the turbine induction
|
|
111
|
-
cp = P / (0.5 * ws**3 * rho * np.pi * r**2) * factor_P
|
|
112
|
-
a =
|
|
175
|
+
cp = P / (0.5 * ws**3 * rho * np.pi * r**2) * self.factor_P
|
|
176
|
+
a = self.induction.ct2a(ct)
|
|
113
177
|
cp_a = 4 * a**3 - 8 * a**2 + 4 * a
|
|
114
178
|
e = cp / cp_a
|
|
115
179
|
del cp, a, cp_a, ct, P
|
|
116
180
|
|
|
117
181
|
# calculating new cp for changed power
|
|
118
|
-
cp = max_P / (0.5 * ws**3 * rho * np.pi * r**2) * factor_P
|
|
182
|
+
cp = max_P / (0.5 * ws**3 * rho * np.pi * r**2) * self.factor_P
|
|
119
183
|
|
|
120
184
|
# find roots:
|
|
121
185
|
N = len(cp)
|
|
@@ -130,43 +194,9 @@ class PowerMask(TurbineModel):
|
|
|
130
194
|
del a0, a1, a2, a3, rts
|
|
131
195
|
|
|
132
196
|
# set results:
|
|
133
|
-
P =
|
|
134
|
-
ct =
|
|
197
|
+
P = fdata[FV.P]
|
|
198
|
+
ct = fdata[FV.CT]
|
|
135
199
|
P[sel] = max_P
|
|
136
200
|
ct[sel] = 4 * a * (1 - a)
|
|
137
201
|
|
|
138
|
-
def calculate(self, algo, mdata, fdata, st_sel):
|
|
139
|
-
""" "
|
|
140
|
-
The main model calculation.
|
|
141
|
-
|
|
142
|
-
This function is executed on a single chunk of data,
|
|
143
|
-
all computations should be based on numpy arrays.
|
|
144
|
-
|
|
145
|
-
Parameters
|
|
146
|
-
----------
|
|
147
|
-
algo: foxes.core.Algorithm
|
|
148
|
-
The calculation algorithm
|
|
149
|
-
mdata: foxes.core.Data
|
|
150
|
-
The model data
|
|
151
|
-
fdata: foxes.core.Data
|
|
152
|
-
The farm data
|
|
153
|
-
st_sel: numpy.ndarray of bool
|
|
154
|
-
The state-turbine selection,
|
|
155
|
-
shape: (n_states, n_turbines)
|
|
156
|
-
|
|
157
|
-
Returns
|
|
158
|
-
-------
|
|
159
|
-
results: dict
|
|
160
|
-
The resulting data, keys: output variable str.
|
|
161
|
-
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
162
|
-
|
|
163
|
-
"""
|
|
164
|
-
|
|
165
|
-
# prepare:
|
|
166
|
-
max_P = fdata[FV.MAX_P]
|
|
167
|
-
rated_P = self._P_rated[None, :]
|
|
168
|
-
|
|
169
|
-
# calculate:
|
|
170
|
-
self.update_P_ct(fdata, max_P, rated_P, self.factor_P, var_ws=self.var_ws_P)
|
|
171
|
-
|
|
172
202
|
return {FV.P: fdata[FV.P], FV.CT: fdata[FV.CT]}
|
|
@@ -82,7 +82,7 @@ class RotorCentreCalc(TurbineModel):
|
|
|
82
82
|
return list(self.calc_vars.keys())
|
|
83
83
|
|
|
84
84
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
85
|
-
"""
|
|
85
|
+
"""
|
|
86
86
|
The main model calculation.
|
|
87
87
|
|
|
88
88
|
This function is executed on a single chunk of data,
|
|
@@ -92,13 +92,13 @@ class RotorCentreCalc(TurbineModel):
|
|
|
92
92
|
----------
|
|
93
93
|
algo: foxes.core.Algorithm
|
|
94
94
|
The calculation algorithm
|
|
95
|
-
mdata: foxes.core.
|
|
95
|
+
mdata: foxes.core.MData
|
|
96
96
|
The model data
|
|
97
|
-
fdata: foxes.core.
|
|
97
|
+
fdata: foxes.core.FData
|
|
98
98
|
The farm data
|
|
99
|
-
st_sel: numpy.ndarray of bool
|
|
99
|
+
st_sel: slice or numpy.ndarray of bool
|
|
100
100
|
The state-turbine selection,
|
|
101
|
-
shape: (n_states, n_turbines)
|
|
101
|
+
for shape: (n_states, n_turbines)
|
|
102
102
|
|
|
103
103
|
Returns
|
|
104
104
|
-------
|
|
@@ -107,29 +107,26 @@ class RotorCentreCalc(TurbineModel):
|
|
|
107
107
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
108
108
|
|
|
109
109
|
"""
|
|
110
|
-
# prepare point data:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
dims=dims,
|
|
120
|
-
loop_dims=[FC.STATE, FC.POINT],
|
|
110
|
+
# prepare target point data:
|
|
111
|
+
tdata = Data.from_points(
|
|
112
|
+
fdata[FV.TXYH],
|
|
113
|
+
data={
|
|
114
|
+
v: np.zeros_like(fdata[FV.X][:, :, None])
|
|
115
|
+
for v in self.calc_vars.values()
|
|
116
|
+
},
|
|
117
|
+
dims={v: (FC.STATE, FC.TARGET, FC.TPOINT) for v in self.calc_vars.values()},
|
|
118
|
+
name=f"{self.name}_tdata",
|
|
121
119
|
)
|
|
122
|
-
del dims
|
|
123
120
|
|
|
124
121
|
# run ambient calculation:
|
|
125
|
-
res = algo.states.calculate(algo, mdata, fdata,
|
|
122
|
+
res = algo.states.calculate(algo, mdata, fdata, tdata)
|
|
126
123
|
for v, a in FV.var2amb.items():
|
|
127
124
|
if v in res:
|
|
128
125
|
res[a] = res[v].copy()
|
|
129
|
-
|
|
126
|
+
tdata.update(res)
|
|
130
127
|
|
|
131
128
|
# run wake calculation:
|
|
132
|
-
res = self._wcalc.calculate(algo, mdata, fdata,
|
|
129
|
+
res = self._wcalc.calculate(algo, mdata, fdata, tdata)
|
|
133
130
|
|
|
134
131
|
# extract results:
|
|
135
132
|
out = {v: fdata[v] for v in self.calc_vars.keys()}
|
|
@@ -162,7 +162,7 @@ class SectorManagement(TurbineModel):
|
|
|
162
162
|
return self._tvars
|
|
163
163
|
|
|
164
164
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
165
|
-
"""
|
|
165
|
+
"""
|
|
166
166
|
The main model calculation.
|
|
167
167
|
|
|
168
168
|
This function is executed on a single chunk of data,
|
|
@@ -172,13 +172,13 @@ class SectorManagement(TurbineModel):
|
|
|
172
172
|
----------
|
|
173
173
|
algo: foxes.core.Algorithm
|
|
174
174
|
The calculation algorithm
|
|
175
|
-
mdata: foxes.core.
|
|
175
|
+
mdata: foxes.core.MData
|
|
176
176
|
The model data
|
|
177
|
-
fdata: foxes.core.
|
|
177
|
+
fdata: foxes.core.FData
|
|
178
178
|
The farm data
|
|
179
|
-
st_sel: numpy.ndarray of bool
|
|
179
|
+
st_sel: slice or numpy.ndarray of bool
|
|
180
180
|
The state-turbine selection,
|
|
181
|
-
shape: (n_states, n_turbines)
|
|
181
|
+
for shape: (n_states, n_turbines)
|
|
182
182
|
|
|
183
183
|
Returns
|
|
184
184
|
-------
|
|
@@ -187,7 +187,6 @@ class SectorManagement(TurbineModel):
|
|
|
187
187
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
188
188
|
|
|
189
189
|
"""
|
|
190
|
-
|
|
191
190
|
# prepare:
|
|
192
191
|
n_trbs = len(self._trbs)
|
|
193
192
|
if n_trbs == fdata.n_turbines and np.all(
|
|
@@ -2,6 +2,7 @@ import numpy as np
|
|
|
2
2
|
|
|
3
3
|
from foxes.core import TurbineModel
|
|
4
4
|
import foxes.constants as FC
|
|
5
|
+
import foxes.variables as FV
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class SetFarmVars(TurbineModel):
|
|
@@ -118,7 +119,7 @@ class SetFarmVars(TurbineModel):
|
|
|
118
119
|
return idata
|
|
119
120
|
|
|
120
121
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
121
|
-
"""
|
|
122
|
+
"""
|
|
122
123
|
The main model calculation.
|
|
123
124
|
|
|
124
125
|
This function is executed on a single chunk of data,
|
|
@@ -128,13 +129,13 @@ class SetFarmVars(TurbineModel):
|
|
|
128
129
|
----------
|
|
129
130
|
algo: foxes.core.Algorithm
|
|
130
131
|
The calculation algorithm
|
|
131
|
-
mdata: foxes.core.
|
|
132
|
+
mdata: foxes.core.MData
|
|
132
133
|
The model data
|
|
133
|
-
fdata: foxes.core.
|
|
134
|
+
fdata: foxes.core.FData
|
|
134
135
|
The farm data
|
|
135
|
-
st_sel: numpy.ndarray of bool
|
|
136
|
+
st_sel: slice or numpy.ndarray of bool
|
|
136
137
|
The state-turbine selection,
|
|
137
|
-
shape: (n_states, n_turbines)
|
|
138
|
+
for shape: (n_states, n_turbines)
|
|
138
139
|
|
|
139
140
|
Returns
|
|
140
141
|
-------
|
|
@@ -143,23 +144,51 @@ class SetFarmVars(TurbineModel):
|
|
|
143
144
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
144
145
|
|
|
145
146
|
"""
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
if self.pre_rotor:
|
|
148
|
+
order = np.s_[:]
|
|
149
|
+
ssel = np.s_[:]
|
|
150
|
+
else:
|
|
151
|
+
order = fdata[FV.ORDER]
|
|
152
|
+
ssel = fdata[FV.ORDER_SSEL]
|
|
153
|
+
|
|
154
|
+
bsel = np.zeros((fdata.n_states, fdata.n_turbines), dtype=bool)
|
|
155
|
+
bsel[st_sel] = True
|
|
149
156
|
|
|
150
157
|
for v in self.vars:
|
|
151
|
-
data = mdata[self.var(v)]
|
|
158
|
+
data = mdata[self.var(v)][ssel, order]
|
|
152
159
|
hsel = ~np.isnan(data)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
160
|
+
tsel = bsel & hsel
|
|
161
|
+
|
|
162
|
+
# special case of turbine positions:
|
|
163
|
+
if v in [FV.X, FV.Y]:
|
|
164
|
+
i = [FV.X, FV.Y].index(v)
|
|
165
|
+
for ti in np.where(tsel)[1]:
|
|
166
|
+
t = algo.farm.turbines[ti]
|
|
167
|
+
if len(t.xy.shape) == 1:
|
|
168
|
+
xy = np.zeros((algo.n_states, 2), dtype=FC.DTYPE)
|
|
169
|
+
xy[:] = t.xy[None, :]
|
|
170
|
+
t.xy = xy
|
|
171
|
+
i0 = fdata.states_i0()
|
|
172
|
+
hsel = tsel[:, ti]
|
|
173
|
+
ssel = i0 + np.where(hsel)[0]
|
|
174
|
+
t.xy[ssel, i] = data[hsel, ti]
|
|
175
|
+
|
|
176
|
+
# special case of rotor diameter and hub height:
|
|
177
|
+
if v in [FV.D, FV.H]:
|
|
178
|
+
for ti in np.where(tsel)[1]:
|
|
179
|
+
t = algo.farm.turbines[ti]
|
|
180
|
+
x = np.zeros(algo.n_states, dtype=FC.DTYPE)
|
|
181
|
+
if v == FV.D:
|
|
182
|
+
x[:] = t.D
|
|
183
|
+
t.D = x
|
|
184
|
+
else:
|
|
185
|
+
x[:] = t.H
|
|
186
|
+
t.H = x
|
|
187
|
+
i0 = fdata.states_i0()
|
|
188
|
+
hsel = tsel[:, ti]
|
|
189
|
+
ssel = i0 + np.where(hsel)[0]
|
|
190
|
+
x[ssel] = data[hsel, ti]
|
|
191
|
+
|
|
192
|
+
fdata[v][tsel] = data[tsel]
|
|
164
193
|
|
|
165
194
|
return {v: fdata[v] for v in self.vars}
|
|
@@ -117,7 +117,7 @@ class TableFactors(TurbineModel):
|
|
|
117
117
|
self._data = self._data.to_numpy(FC.DTYPE)
|
|
118
118
|
|
|
119
119
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
120
|
-
"""
|
|
120
|
+
"""
|
|
121
121
|
The main model calculation.
|
|
122
122
|
|
|
123
123
|
This function is executed on a single chunk of data,
|
|
@@ -127,13 +127,13 @@ class TableFactors(TurbineModel):
|
|
|
127
127
|
----------
|
|
128
128
|
algo: foxes.core.Algorithm
|
|
129
129
|
The calculation algorithm
|
|
130
|
-
mdata: foxes.core.
|
|
130
|
+
mdata: foxes.core.MData
|
|
131
131
|
The model data
|
|
132
|
-
fdata: foxes.core.
|
|
132
|
+
fdata: foxes.core.FData
|
|
133
133
|
The farm data
|
|
134
|
-
st_sel: numpy.ndarray of bool
|
|
134
|
+
st_sel: slice or numpy.ndarray of bool
|
|
135
135
|
The state-turbine selection,
|
|
136
|
-
shape: (n_states, n_turbines)
|
|
136
|
+
for shape: (n_states, n_turbines)
|
|
137
137
|
|
|
138
138
|
Returns
|
|
139
139
|
-------
|
|
@@ -35,6 +35,10 @@ class Thrust2Ct(TurbineModel):
|
|
|
35
35
|
self.thrust_var = thrust_var
|
|
36
36
|
self.WSCT = var_ws_ct
|
|
37
37
|
|
|
38
|
+
def __repr__(self):
|
|
39
|
+
a = f"thrust_var={self.thrust_var}, var_ws_ct={self.WSCT}"
|
|
40
|
+
return f"{type(self).__name__}({a})"
|
|
41
|
+
|
|
38
42
|
def output_farm_vars(self, algo):
|
|
39
43
|
"""
|
|
40
44
|
The variables which are being modified by the model.
|
|
@@ -53,7 +57,7 @@ class Thrust2Ct(TurbineModel):
|
|
|
53
57
|
return [FV.CT]
|
|
54
58
|
|
|
55
59
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
56
|
-
"""
|
|
60
|
+
"""
|
|
57
61
|
The main model calculation.
|
|
58
62
|
|
|
59
63
|
This function is executed on a single chunk of data,
|
|
@@ -63,13 +67,13 @@ class Thrust2Ct(TurbineModel):
|
|
|
63
67
|
----------
|
|
64
68
|
algo: foxes.core.Algorithm
|
|
65
69
|
The calculation algorithm
|
|
66
|
-
mdata: foxes.core.
|
|
70
|
+
mdata: foxes.core.MData
|
|
67
71
|
The model data
|
|
68
|
-
fdata: foxes.core.
|
|
72
|
+
fdata: foxes.core.FData
|
|
69
73
|
The farm data
|
|
70
|
-
st_sel: numpy.ndarray of bool
|
|
74
|
+
st_sel: slice or numpy.ndarray of bool
|
|
71
75
|
The state-turbine selection,
|
|
72
|
-
shape: (n_states, n_turbines)
|
|
76
|
+
for shape: (n_states, n_turbines)
|
|
73
77
|
|
|
74
78
|
Returns
|
|
75
79
|
-------
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
1
|
from foxes.core import TurbineModel
|
|
4
2
|
import foxes.variables as FV
|
|
5
3
|
import foxes.constants as FC
|
|
@@ -33,7 +31,7 @@ class YAW2YAWM(TurbineModel):
|
|
|
33
31
|
return [FV.YAWM]
|
|
34
32
|
|
|
35
33
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
36
|
-
"""
|
|
34
|
+
"""
|
|
37
35
|
The main model calculation.
|
|
38
36
|
|
|
39
37
|
This function is executed on a single chunk of data,
|
|
@@ -43,13 +41,13 @@ class YAW2YAWM(TurbineModel):
|
|
|
43
41
|
----------
|
|
44
42
|
algo: foxes.core.Algorithm
|
|
45
43
|
The calculation algorithm
|
|
46
|
-
mdata: foxes.core.
|
|
44
|
+
mdata: foxes.core.MData
|
|
47
45
|
The model data
|
|
48
|
-
fdata: foxes.core.
|
|
46
|
+
fdata: foxes.core.FData
|
|
49
47
|
The farm data
|
|
50
|
-
st_sel: numpy.ndarray of bool
|
|
48
|
+
st_sel: slice or numpy.ndarray of bool
|
|
51
49
|
The state-turbine selection,
|
|
52
|
-
shape: (n_states, n_turbines)
|
|
50
|
+
for shape: (n_states, n_turbines)
|
|
53
51
|
|
|
54
52
|
Returns
|
|
55
53
|
-------
|
|
@@ -58,12 +56,8 @@ class YAW2YAWM(TurbineModel):
|
|
|
58
56
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
59
57
|
|
|
60
58
|
"""
|
|
61
|
-
yaw =
|
|
62
|
-
|
|
63
|
-
)[st_sel]
|
|
64
|
-
wd = self.get_data(
|
|
65
|
-
FV.WD, FC.STATE_TURBINE, lookup="f", fdata=fdata, upcast=True
|
|
66
|
-
)[st_sel]
|
|
59
|
+
yaw = fdata[FV.YAW][st_sel]
|
|
60
|
+
wd = fdata[FV.WD][st_sel]
|
|
67
61
|
|
|
68
62
|
yawm = fdata[FV.YAWM]
|
|
69
63
|
yawm[st_sel] = delta_wd(wd, yaw)
|
|
@@ -32,7 +32,7 @@ class YAWM2YAW(TurbineModel):
|
|
|
32
32
|
return [FV.YAW]
|
|
33
33
|
|
|
34
34
|
def calculate(self, algo, mdata, fdata, st_sel):
|
|
35
|
-
"""
|
|
35
|
+
"""
|
|
36
36
|
The main model calculation.
|
|
37
37
|
|
|
38
38
|
This function is executed on a single chunk of data,
|
|
@@ -42,13 +42,13 @@ class YAWM2YAW(TurbineModel):
|
|
|
42
42
|
----------
|
|
43
43
|
algo: foxes.core.Algorithm
|
|
44
44
|
The calculation algorithm
|
|
45
|
-
mdata: foxes.core.
|
|
45
|
+
mdata: foxes.core.MData
|
|
46
46
|
The model data
|
|
47
|
-
fdata: foxes.core.
|
|
47
|
+
fdata: foxes.core.FData
|
|
48
48
|
The farm data
|
|
49
|
-
st_sel: numpy.ndarray of bool
|
|
49
|
+
st_sel: slice or numpy.ndarray of bool
|
|
50
50
|
The state-turbine selection,
|
|
51
|
-
shape: (n_states, n_turbines)
|
|
51
|
+
for shape: (n_states, n_turbines)
|
|
52
52
|
|
|
53
53
|
Returns
|
|
54
54
|
-------
|
|
@@ -57,12 +57,8 @@ class YAWM2YAW(TurbineModel):
|
|
|
57
57
|
Values: numpy.ndarray with shape (n_states, n_turbines)
|
|
58
58
|
|
|
59
59
|
"""
|
|
60
|
-
yawm =
|
|
61
|
-
|
|
62
|
-
)[st_sel]
|
|
63
|
-
wd = self.get_data(
|
|
64
|
-
FV.WD, FC.STATE_TURBINE, lookup="f", fdata=fdata, upcast=True
|
|
65
|
-
)[st_sel]
|
|
60
|
+
yawm = fdata[FV.YAWM][st_sel]
|
|
61
|
+
wd = fdata[FV.WD][st_sel]
|
|
66
62
|
|
|
67
63
|
yaw = fdata[FV.YAW]
|
|
68
64
|
yaw[st_sel] = np.mod(wd + yawm, 360.0)
|